logo
Published on

50 Must-know HTML, CSS and JavaScript Interview Questions by Ex-interviewers

Authors
  • avatar
    Name
    Ganesh Negi
    Twitter

50 Must-know HTML, CSS and JavaScript Interview Questions by Ex-interviewers

Javascript DSA Questions With Answers

Mastering HTML, CSS, and JavaScript is essential for anyone aiming to start a career in web development.

However, landing a job in this competitive field can be daunting, especially for newcomers.

One of the most important stages in the hiring process is the technical interview, where your understanding of these core technologies is put to the test. To support your preparation and help you feel more confident, we’ve put together a curated list of 50 commonly asked interview questions and answers focusing on HTML, CSS, and JavaScript.

1. What is Hoisting in JavaScript?

Hoisting is a behavior in JavaScript where variable and function declarations are moved to the top of their containing scope during the compilation stage. It's important to note that only the declarations are hoisted—not the initial assignments. Read more

2. How you differentiate between let, var, and const ?

We can differentiate var, let and const in following:-

  1. Scope:
  • var: Function-scoped pr globally scoped.

  • let and const: Block-scoped, Confined to their nearest enclosing block means that a variable or declaration is only accessible within the block (such as ) where it is defined, and not outside of it. This is commonly seen with variables declared using let and const in JavaScript, which are limited to block scope rather than function or global scope.

function test() {
  var a = 1;
  let b = 2;
  const c = 3;
}
console.log(a); // ReferenceError
console.log(b); // ReferenceError
console.log(c); // ReferenceError

  1. Initialization:
  • var and let: Can be declared without initialization.

  • const: Must be initialized during declaration.

var a;
let b;
const c; // SyntaxError: Missing initializer

  1. Redeclaration:
  • var: Allows redeclaration in the same scope.

  • let and const: Redeclaration is not allowed.

var x = 1;
var x = 2; // Valid

let y = 1;
let y = 2; // SyntaxError

  1. Reassignment:
  • var and let: Reassignment is allowed.

  • const: Reassignment is not allowed.

const z = 1;
z = 2; // TypeError

  1. Hoisting:
  • var: Hoisted and initialized to undefined.

  • let and const: Hoisted but not initialized, causing a ReferenceError if accessed before declaration.

console.log(a); // undefined
var a = 1;

console.log(b); // ReferenceError
let b = 2;

3. What Is the Difference Between == and === ?

Equality Operator (==):

Performs type coercion, meaning it converts the operands to the same type before making the comparison.

Can lead to unintended or confusing results, especially when comparing values of different types (e.g., 0 == '0' is true).

42 == '42'; // true
0 == false; // true
null == undefined; // true


Strict Equality Operator (===):

Does not perform type coercion; it compares both the value and the data type.

Provides more reliable and predictable results, making it the preferred choice for most comparisons in JavaScript (e.g., 0 === '0' is false).

42 === '42'; // false
0 === false; // false
null === undefined; // false

Best Practice:

Use === instead of == to prevent unexpected results caused by type coercion. This ensures more precise and predictable comparisons. The only common exception is when intentionally checking for both null and undefined using ==, as null == undefined evaluates to true.

var value = null;
console.log(value == null); // true
console.log(value === null); // true

4. What Is the Event Loop in JavaScript?

The Event Loop in JavaScript

The event loop enables JavaScript to manage asynchronous operations efficiently on a single-threaded environment, allowing non-blocking execution and maintaining responsiveness.

Key Components:

Call Stack: Manages function execution in a Last In, First Out (LIFO) manner.

Web APIs: Browser-provided features that handle async operations like setTimeout, fetch, and DOM events.

Task Queue (Macrotask Queue): Holds callback functions from tasks such as timers and event listeners.

Microtask Queue: Stores high-priority tasks like Promise.then() and MutationObserver callbacks.

Execution Flow:

Synchronous Code runs first via the call stack.

Microtasks are executed right after the current stack is clear.

Macrotasks are then processed from the task queue.

This cycle repeats, ensuring asynchronous tasks are executed in the correct order without interrupting the main thread.

5. What Is Event Delegation?

Event Delegation in JavaScript

Event delegation is a technique where a single event listener is attached to a parent element to manage events triggered by its child elements. It leverages event bubbling, where events propagate up the DOM tree.

Benefits:

Improved Performance: Minimizes memory usage by reducing the number of individual event listeners.

Dynamic Handling: Easily manages events on child elements that are added or removed dynamically.

Cleaner Code: Centralizes event handling, making the codebase more maintainable and organized.

document.getElementById('parent').addEventListener('click', (event) => {
  if (event.target.tagName === 'BUTTON') {
    console.log(`Clicked ${event.target.textContent}`);
  }
});

6. How Does this Work in JavaScript?

The value of this is determined by how a function is called, not where it’s defined. Here are the key binding rules:

Rules:

Default Binding: When a function is called without context, this refers to the global object (window in browsers, global in Node.js).

function show() { console.log(this); }
show(); // window (in browsers)

Implicit Binding: When a function is called as a method of an object, this refers to the object before the dot.

const obj = { name: 'JS', greet() { console.log(this.name); } };
obj.greet(); // 'JS'

Explicit Binding: You can manually set this using call(), apply(), or bind().

function sayName() { console.log(this.name); }
const user = { name: 'Alice' };
sayName.call(user); // 'Alice'

Arrow Functions: Arrow functions do not have their own this. Instead, they lexically inherit it from the surrounding (parent) scope.

const obj = {
  name: 'Arrow',
  say: () => console.log(this.name)
};
obj.say(); // undefined (inherits from global scope)

7. What Are <script>, <script async>, and <script defer> ?

1. <script> (No Attribute)

Blocks HTML parsing while the script is downloaded and executed.

Can delay page rendering, especially with large or slow-loading scripts.

<script src="script.js"></script>

2. <script async>

Downloads the script asynchronously (non-blocking).

Executes immediately once the script is ready, even if HTML parsing isn’t finished.

Ideal for independent scripts (e.g., analytics), but may execute out of order.

<script src="script.js" async></script>

3. <script defer>

Downloads asynchronously, but defers execution until after the entire HTML document is parsed.

Ensures scripts run in order and only after the DOM is ready.

Best for scripts that depend on the DOM structure.

<script src="script.js" defer></script>

| Attribute  | Download | Execution Time             | Blocks Parsing | Maintains Order |
| ---------- | -------- | -------------------------- | -------------- | --------------- |
| `<script>` | Sync     | Immediately                | Yes            | Yes             |
| `async`    | Async    | As soon as ready           | No             | No              |
| `defer`    | Async    | After HTML is fully parsed | No             | Yes             |


8. How Do null, undefined, and Undeclared Variables Differ ?

null

Represents the intentional absence of any object value.

It’s explicitly assigned by the developer.

Use === for accurate checks (value === null).

let a = null;
console.log(a); // null

undefined

Indicates that a variable has been declared but not assigned a value.

Automatically assigned by JavaScript.

let b;
console.log(b); // undefined

Undeclared

Refers to variables that have never been declared in the current scope.

Accessing them results in a ReferenceError.

console.log(c); // ReferenceError: c is not defined

| Type        | Description                  | Assigned By | Error on Access |
| ----------- | ---------------------------- | ----------- | --------------- |
| `null`      | Explicitly no value          | Developer   | No              |
| `undefined` | Declared but not initialized | JavaScript  | No              |
| Undeclared  | Not declared in scope        || **Yes**         |

9. What Is the Difference Between .call and .apply?

.call:

Accepts arguments as a comma-separated list.

.apply:

Accepts arguments as an array.

function sum(a, b) {
  return a + b;
}
console.log(sum.call(null, 1, 2)); // 3
console.log(sum.apply(null, [1, 2])); // 3

10. What Is Function.prototype.bind and Why Is It Useful?

The bind() method creates a new function with a permanently bound this context, and optionally, preset arguments. This is especially helpful when passing methods as callbacks or event handlers, ensuring they maintain the correct this reference.

const john = {
  age: 42,
  getAge: function () {
    return this.age;
  },
};

console.log(john.getAge()); // 42

const unboundGetAge = john.getAge;
console.log(unboundGetAge()); // undefined

const boundGetAge = john.getAge.bind(john);
console.log(boundGetAge()); // 42

const mary = { age: 21 };
const boundGetAgeMary = john.getAge.bind(mary);
console.log(boundGetAgeMary()); // 21

11. Why Use Arrow Functions in Constructors?

Arrow functions differ from regular functions in how they handle the this keyword. They lexically bind this, meaning they inherit it from their surrounding scope at the time of definition, not execution.

Key Points:

Arrow functions do not have their own this.

this refers to the context where the arrow function was defined, not where it's called.

Ideal for callbacks, event handlers, and methods inside classes when you want to preserve the surrounding context.

function Person(name) {
  this.name = name;
  setTimeout(() => {
    console.log(this.name); // 'Alice' — inherited from Person's context
  }, 1000);
}

const p = new Person('Alice');

12. How Can You Create Objects in JavaScript?

  1. Object Literals:
  • const person = { firstName: 'John', lastName: 'Doe' };
  1. Object() Constructor:
const person = new Object();
person.firstName = 'John';
person.lastName = 'Doe';

  1. Object.create():
const proto = {
  greet() {
    console.log('Hello!');
  },
};
const person = Object.create(proto);
person.greet(); // Hello!

  1. ES2015 Classes:
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }
}

12. How you define Higher-Order Functions?

Higher-order functions either:

  • Take other functions as arguments.

  • Return functions.

function multiplier(factor) {
 return function (number) {
   return number * factor;
 };
}

const double = multiplier(2);
console.log(double(5)); // 10

13. What Is Event Bubbling?

Event bubbling occurs when an event originates on the target element and then propagates upward through its parent elements in the DOM hierarchy.

parent.addEventListener('click', () => console.log('Parent clicked'));
child.addEventListener('click', () => console.log('Child clicked'));

Clicking the child triggers both handlers.

14. What Is Event Capturing?

Event capturing occurs when an event starts at the root and propagates down to the target element.

parent.addEventListener('click', () => console.log('Parent capturing'), true);

15. How can You Differentiate Between Synchronous and Asynchronous Functions?

Synchronous Functions:-

  • Execute operations in a sequential, step-by-step manner
  • Block the program's execution until the current task completes
  • Adhere to a strict, line-by-line execution order
  • Are generally easier to comprehend and debug due to their predictable flow
  • Common use cases include reading files synchronously and iterating over large datasets
const fs = require('fs');
const data = fs.readFileSync('large-file.txt', 'utf8');
console.log(data); // Blocks until file is read
console.log('End of the program');

Asynchronous Functions:-

  • Allow the program to continue running without waiting for the task to finish
  • Enable other operations to proceed while waiting for responses or the completion of time-consuming tasks
  • Are non-blocking, facilitating concurrent execution and enhancing performance and responsiveness
  • Commonly used for network requests, file I/O, timers, and animations
console.log('Start of the program');

fetch('https://api.example.com/data')
  .then((response) => response.json())
  .then((data) => console.log(data)) // Non-blocking
  .catch((error) => console.error(error));

console.log('End of program');

16. What Are the Differences Between Map/Set and WeakMap/WeakSet?

JavaScript provides Map/Set and WeakMap/WeakSet for handling collections of data, but they differ significantly in behavior and use cases. Here’s a breakdown of the main differences:

Key Types

Map / Set: Accept any value as keys or entries—objects, primitives, functions, etc.

WeakMap / WeakSet: Only accept objects as keys. Primitives (e.g., strings, numbers) are not allowed.

Memory Management

Map / Set: Maintain strong references to keys and values, which prevents garbage collection.

WeakMap / WeakSet: Use weak references, allowing keys (objects) to be garbage-collected when no other references exist.

Key Enumeration

Map / Set: Iterable—you can loop through keys, values, or entries using for...of, .keys(), .values(), etc.

WeakMap / WeakSet: Not iterable—you cannot enumerate keys or values, for security and performance reasons.

Size Tracking

Map / Set: Have a .size property to reflect the number of items.

WeakMap / WeakSet: Do not expose a size property because entries can be removed at any time due to garbage collection.

let obj = {};
const map = new Map();
const weakMap = new WeakMap();

map.set('key', 'value');         // valid
map.set(obj, 'objectValue');     // valid

weakMap.set(obj, 'metaData');    // valid
// weakMap.set('key', 'value');  // Error: keys must be objects