JavaScript Advanced Interview Questions

28 questions with detailed answers

Question:
Explain what a closure is in JavaScript and provide an example.
Answer:

A closure is a function that has access to variables in its outer (enclosing) scope even after the outer function has returned. It gives you access to an outer function's scope from an inner function.

Example:
function outerFunction(x) {
return function innerFunction(y) {
return x + y;
};
}

const addFive = outerFunction(5);
console.log(addFive(3)); // 8

Here, innerFunction has access to the variable x from outerFunction even after outerFunction has finished executing.

Question:
Explain the differences between let, const, and var in JavaScript.
Answer:

var: Function-scoped, can be redeclared and updated, hoisted with undefined initialization.

let: Block-scoped, cannot be redeclared in same scope, can be updated, hoisted but not initialized (temporal dead zone).

const: Block-scoped, cannot be redeclared or updated, must be initialized at declaration, hoisted but not initialized.

Example:
var a = 1; // function scoped
let b = 2; // block scoped
const c = 3; // block scoped, immutable

Question:
Explain event delegation in JavaScript and its benefits.
Answer:

Event delegation is a technique where you attach a single event listener to a parent element to handle events for multiple child elements. It leverages event bubbling.

Benefits:
- Better performance (fewer event listeners)
- Works with dynamically added elements
- Cleaner code

Example:
document.getElementById('parent').addEventListener('click', function(e) {
if (e.target.classList.contains('child')) {
console.log('Child clicked!');
}
});

Question:
Explain the difference between loose equality (==) and strict equality (===) in JavaScript.
Answer:

== (loose equality): Compares values after type coercion
=== (strict equality): Compares values without type coercion

Examples:
"5" == 5 // true (string converted to number)
"5" === 5 // false (different types)

null == undefined // true
null === undefined // false

0 == false // true
0 === false // false

Best practice: Always use === unless you specifically need type coercion.

Question:
Explain async/await in JavaScript and how it differs from Promises.
Answer:

async/await is syntactic sugar over Promises, making asynchronous code look more like synchronous code.

Async function:
async function fetchData() {
try {
const response = await fetch("/api/data");
const data = await response.json();
return data;
} catch (error) {
console.error("Error:", error);
}
}

Equivalent with Promises:
function fetchData() {
return fetch("/api/data")
.then(response => response.json())
.catch(error => console.error("Error:", error));
}

Benefits: Better readability, easier error handling with try/catch.

Question:

What is hoisting in JavaScript?

Answer:

Hoisting is JavaScript's behavior of moving variable and function declarations to the top of their scope during compilation.

Variable Hoisting:


console.log(x); // undefined (not error)
var x = 5;

// Equivalent to:
var x;
console.log(x); // undefined
x = 5;

Function Hoisting:


sayHello(); // "Hello!" - works

function sayHello() {
console.log("Hello!");
}

let/const Hoisting:


console.log(y); // ReferenceError
let y = 10;

let and const are hoisted but not initialized, creating a "temporal dead zone".

Question:

What are JavaScript functions?

Answer:

JavaScript functions can be defined in several ways:

1. Function Declaration:


function greet(name) {
return "Hello " + name;
}

2. Function Expression:


const greet = function(name) {
return "Hello " + name;
};

3. Arrow Function (ES6):


const greet = (name) => {
return "Hello " + name;
};
// Or shorter:
const greet = name => "Hello " + name;

4. Constructor Function:


const greet = new Function("name", "return 'Hello ' + name");

Functions are first-class objects in JavaScript, meaning they can be assigned to variables, passed as arguments, and returned from other functions.

Question:

What is the difference between == and === operators?

Answer:

== (Loose Equality):
- Performs type coercion before comparison
- Converts operands to same type, then compares

=== (Strict Equality):
- No type coercion
- Compares both value and type

Examples:


5 == "5" // true (string converted to number)
5 === "5" // false (different types)

true == 1 // true (boolean converted to number)
true === 1 // false (different types)

null == undefined // true (special case)
null === undefined // false (different types)

0 == false // true (both convert to 0)
0 === false // false (different types)

Best practice: Use === for predictable comparisons.

Question:

What is the this keyword in JavaScript?

Answer:

The this keyword refers to the object that is executing the current function. Its value depends on how the function is called:

1. Global Context:


console.log(this); // Window object (browser) or global (Node.js)

2. Object Method:


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

3. Constructor Function:


function Person(name) {
this.name = name; // refers to new instance
}

4. Arrow Functions:


const obj = {
name: "John",
greet: () => {
console.log(this.name); // undefined (inherits from enclosing scope)
}
};

5. Explicit Binding:


function greet() {
console.log(this.name);
}
greet.call({name: "John"}); // "John"

Question:

What are JavaScript arrays and their methods?

Answer:

Arrays are ordered collections of elements in JavaScript.

Creating Arrays:


const arr1 = [1, 2, 3];
const arr2 = new Array(1, 2, 3);

Common Methods:

Mutating methods:
- push() - add to end
- pop() - remove from end
- shift() - remove from start
- unshift() - add to start
- splice() - add/remove elements
- sort() - sort elements
- reverse() - reverse order

Non-mutating methods:
- concat() - join arrays
- slice() - extract portion
- indexOf() - find index
- includes() - check existence

Iteration methods:
- forEach() - execute function for each
- map() - transform elements
- filter() - filter elements
- reduce() - reduce to single value
- find() - find first match
- some() - test if any match
- every() - test if all match

Question:

What is event delegation in JavaScript?

Answer:

Event delegation is a technique where you attach a single event listener to a parent element to handle events for multiple child elements, using event bubbling.

Example:


// Instead of adding listeners to each button
document.getElementById("parent").addEventListener("click", function(e) {
if (e.target.tagName === "BUTTON") {
console.log("Button clicked:", e.target.textContent);
}
});

Benefits:
1. Performance - Fewer event listeners
2. Memory efficiency - Less memory usage
3. Dynamic elements - Works with elements added later
4. Cleaner code - Single event handler

Use cases:
- Lists with many items
- Dynamically generated content
- Tables with many rows
- Navigation menus

Event object properties:
- e.target - element that triggered event
- e.currentTarget - element with event listener
- e.stopPropagation() - stop bubbling

Question:

What are JavaScript objects and prototypes?

Answer:

JavaScript is a prototype-based language where objects can inherit directly from other objects.

Creating Objects:


// Object literal
const obj = { name: "John", age: 30 };

// Constructor function
function Person(name) {
this.name = name;
}
const person = new Person("John");

// Object.create()
const obj = Object.create(prototype);

Prototype:
Every function has a prototype property, and every object has a __proto__ property.


function Person(name) {
this.name = name;
}

Person.prototype.greet = function() {
return "Hello, " + this.name;
};

const john = new Person("John");
console.log(john.greet()); // "Hello, John"

Prototype Chain:
When accessing a property, JavaScript looks:
1. On the object itself
2. On the object's prototype
3. Up the prototype chain until Object.prototype
4. Returns undefined if not found

Question:

What are Promises and async/await?

Answer:

Promises represent the eventual completion or failure of an asynchronous operation.

Promise States:
- Pending - initial state
- Fulfilled - operation completed successfully
- Rejected - operation failed

Creating Promises:


const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
}, 1000);
});

Using Promises:


promise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log("Done"));

Async/Await (ES2017):


async function fetchData() {
try {
const result = await promise;
console.log(result);
} catch (error) {
console.error(error);
}
}

Benefits:
- Cleaner than callbacks
- Better error handling
- Avoids callback hell
- More readable asynchronous code

Question:

What is the Event Loop in JavaScript?

Answer:

The Event Loop is the mechanism that handles asynchronous operations in JavaScript's single-threaded environment.

Components:
1. Call Stack - executes functions (LIFO)
2. Web APIs - browser APIs (setTimeout, DOM events, etc.)
3. Callback Queue - completed async operations (FIFO)
4. Event Loop - moves callbacks from queue to stack

Process:


console.log("1");
setTimeout(() => console.log("2"), 0);
console.log("3");
// Output: 1, 3, 2

Execution Order:
1. Synchronous code executes first
2. Async operations go to Web APIs
3. Completed operations go to Callback Queue
4. Event Loop moves callbacks to Call Stack when empty

Microtasks vs Macrotasks:
- Microtasks (higher priority): Promises, queueMicrotask
- Macrotasks: setTimeout, setInterval, DOM events

Microtasks execute before macrotasks in each loop iteration.

Question:

What are JavaScript modules?

Answer:

Modules allow you to split code into separate files and import/export functionality.

ES6 Modules (ESM):

Exporting:


// math.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}

// Default export
export default function multiply(a, b) {
return a * b;
}

Importing:


// main.js
import multiply, { PI, add } from "./math.js";
import * as math from "./math.js";

console.log(PI); // 3.14159
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20

CommonJS (Node.js):


// Exporting
module.exports = { add, PI };

// Importing
const { add, PI } = require("./math");

Benefits:
- Code organization
- Reusability
- Namespace management
- Dependency management
- Tree shaking (dead code elimination)

Question:

What are JavaScript Design Patterns?

Answer:

Design patterns are reusable solutions to common programming problems.

1. Module Pattern:


const Module = (function() {
let privateVar = 0;

return {
increment() {
privateVar++;
},
getCount() {
return privateVar;
}
};
})();

2. Singleton Pattern:


class Singleton {
constructor() {
if (Singleton.instance) {
return Singleton.instance;
}
Singleton.instance = this;
}
}

3. Observer Pattern:


class EventEmitter {
constructor() {
this.events = {};
}

on(event, callback) {
if (!this.events[event]) {
this.events[event] = [];
}
this.events[event].push(callback);
}

emit(event, data) {
if (this.events[event]) {
this.events[event].forEach(callback => callback(data));
}
}
}

4. Factory Pattern:


class CarFactory {
createCar(type) {
switch(type) {
case "sedan": return new Sedan();
case "suv": return new SUV();
}
}
}

Question:

What is memory management in JavaScript?

Answer:

JavaScript automatically manages memory through garbage collection.

Memory Lifecycle:
1. Allocation - memory is allocated when variables are created
2. Usage - reading/writing to allocated memory
3. Release - memory is freed when no longer needed

Garbage Collection Algorithms:

1. Reference Counting:


let obj1 = { name: "John" }; // Reference count: 1
let obj2 = obj1; // Reference count: 2
obj1 = null; // Reference count: 1
obj2 = null; // Reference count: 0, eligible for GC

Problem - Circular References:


function createCircular() {
let obj1 = {};
let obj2 = {};
obj1.ref = obj2;
obj2.ref = obj1; // Circular reference
return "done";
}

2. Mark-and-Sweep (Modern approach):
- Marks all reachable objects from root
- Sweeps unmarked objects
- Handles circular references

Memory Leaks Prevention:
- Remove event listeners
- Clear timers
- Avoid global variables
- Break circular references
- Use WeakMap/WeakSet for weak references

Question:

What are Web Workers in JavaScript?

Answer:

Web Workers allow running JavaScript in background threads, separate from the main UI thread.

Creating a Web Worker:

worker.js:


// Heavy computation
self.onmessage = function(e) {
const { numbers } = e.data;
const result = numbers.reduce((sum, num) => sum + num, 0);

// Send result back
self.postMessage({ result });
};

main.js:


const worker = new Worker("worker.js");

// Send data to worker
worker.postMessage({ numbers: [1, 2, 3, 4, 5] });

// Receive result
worker.onmessage = function(e) {
console.log("Result:", e.data.result);
};

// Handle errors
worker.onerror = function(error) {
console.error("Worker error:", error);
};

// Terminate worker
worker.terminate();

Types of Workers:
1. Dedicated Workers - single script
2. Shared Workers - multiple scripts
3. Service Workers - network proxy

Benefits:
- Non-blocking operations
- CPU-intensive tasks
- Parallel processing
- Better user experience

Limitations:
- No DOM access
- Limited API access
- Communication overhead

Question:

What are JavaScript Generators and Iterators?

Answer:

Generators are functions that can pause and resume execution, producing a sequence of values.

Generator Function:


function* numberGenerator() {
yield 1;
yield 2;
yield 3;
return "done";
}

const gen = numberGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
console.log(gen.next()); // { value: 3, done: false }
console.log(gen.next()); // { value: "done", done: true }

Infinite Sequences:


function* fibonacci() {
let a = 0, b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}

const fib = fibonacci();
console.log(fib.next().value); // 0
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1

Iterator Protocol:


const iterable = {
[Symbol.iterator]() {
let count = 0;
return {
next() {
if (count < 3) {
return { value: count++, done: false };
}
return { done: true };
}
};
}
};

for (const value of iterable) {
console.log(value); // 0, 1, 2
}

Use Cases:
- Lazy evaluation
- Memory-efficient sequences
- Async iteration
- State machines
- Custom iterables

Question:

What is functional programming in JavaScript?

Answer:

Functional programming treats computation as evaluation of mathematical functions, avoiding state changes and mutable data.

Core Principles:
1. Pure Functions - same input, same output, no side effects
2. Immutability - data doesn't change
3. Higher-order Functions - functions that take/return functions
4. Function Composition - combining simple functions

Pure Functions:


// Pure
const add = (a, b) => a + b;

// Impure (side effect)
let count = 0;
const increment = () => ++count;

Immutability:


// Instead of mutating
const addItem = (arr, item) => [...arr, item];

// Instead of changing object
const updateUser = (user, updates) => ({ ...user, ...updates });

Higher-order Functions:


const numbers = [1, 2, 3, 4, 5];

// map, filter, reduce are higher-order functions
const doubled = numbers.map(x => x * 2);
const evens = numbers.filter(x => x % 2 === 0);
const sum = numbers.reduce((acc, x) => acc + x, 0);

Function Composition:


const compose = (f, g) => x => f(g(x));

const addOne = x => x + 1;
const double = x => x * 2;

const addOneThenDouble = compose(double, addOne);
console.log(addOneThenDouble(3)); // 8

Benefits:
- Predictable code
- Easier testing
- Better debugging
- Parallel processing
- Code reusability

Question:

What is closure in JavaScript?

Answer:

A closure is a function that has access to variables in its outer (enclosing) scope even after the outer function has returned. It gives you access to an outer function's scope from an inner function.

Example:
function outerFunction(x) {
return function innerFunction(y) {
return x + y;
};
}

const addFive = outerFunction(5);
console.log(addFive(3)); // 8

Here, innerFunction has access to the variable x from outerFunction even after outerFunction has finished executing.

Question:

What is the difference between let, const, and var?

Answer:

var: Function-scoped, can be redeclared and updated, hoisted with undefined initialization.

let: Block-scoped, cannot be redeclared in same scope, can be updated, hoisted but not initialized (temporal dead zone).

const: Block-scoped, cannot be redeclared or updated, must be initialized at declaration, hoisted but not initialized.

Example:
var a = 1; // function scoped
let b = 2; // block scoped
const c = 3; // block scoped, immutable

Question:

What is event delegation?

Answer:

Event delegation is a technique where you attach a single event listener to a parent element to handle events for multiple child elements. It leverages event bubbling.

Benefits:
- Better performance (fewer event listeners)
- Works with dynamically added elements
- Cleaner code

Example:
document.getElementById('parent').addEventListener('click', function(e) {
if (e.target.classList.contains('child')) {
console.log('Child clicked!');
}
});

Question:

What is the difference between == and ===?

Answer:

== (loose equality): Compares values after type coercion
=== (strict equality): Compares values without type coercion

Examples:
"5" == 5 // true (string converted to number)
"5" === 5 // false (different types)

null == undefined // true
null === undefined // false

0 == false // true
0 === false // false

Best practice: Always use === unless you specifically need type coercion.

Question:

What is async/await?

Answer:

async/await is syntactic sugar over Promises, making asynchronous code look more like synchronous code.

Async function:
async function fetchData() {
try {
const response = await fetch("/api/data");
const data = await response.json();
return data;
} catch (error) {
console.error("Error:", error);
}
}

Equivalent with Promises:
function fetchData() {
return fetch("/api/data")
.then(response => response.json())
.catch(error => console.error("Error:", error));
}

Benefits: Better readability, easier error handling with try/catch.

Question:

What is JavaScript?

Answer:

JavaScript is a high-level, interpreted programming language that is primarily used for web development. Key characteristics:

1. Dynamic typing
2. Prototype-based object-oriented programming
3. First-class functions
4. Event-driven programming
5. Client-side and server-side execution
6. Interpreted language (no compilation needed)
7. Case-sensitive
8. Supports functional, object-oriented, and procedural programming paradigms

Question:

What are JavaScript data types?

Answer:

JavaScript has 8 data types:

Primitive types:
1. Number - integers and floating-point numbers
2. String - text data
3. Boolean - true/false values
4. Undefined - declared but not assigned
5. Null - intentional absence of value
6. Symbol - unique identifiers (ES6)
7. BigInt - large integers (ES2020)

Non-primitive type:
8. Object - collections of key-value pairs, including arrays, functions, dates, etc.

Question:

What is the difference between var, let, and const?

Answer:

Key differences:

var:
- Function-scoped or globally-scoped
- Can be redeclared and updated
- Hoisted and initialized with undefined

let:
- Block-scoped
- Can be updated but not redeclared in same scope
- Hoisted but not initialized (temporal dead zone)

const:
- Block-scoped
- Cannot be updated or redeclared
- Must be initialized at declaration
- Hoisted but not initialized (temporal dead zone)

Example:
function example() {
var a = 1;
let b = 2;
const c = 3;

if (true) {
var a = 4; // Same variable
let b = 5; // Different variable
// const c = 6; // Error: already declared
}
}

Study Tips
  • Read each question carefully
  • Try to answer before viewing the solution
  • Practice explaining concepts out loud
  • Review regularly to reinforce learning
Share & Practice

Found this helpful? Share with others!

Feedback