JavaScript Advanced Interview Questions
28 questions with detailed answers
Question:
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:
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:
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:
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:
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!" - worksfunction 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
}
}