JavaScript Interview Questions are crucial for anyone working in web development. JavaScript is one of the most widely used programming languages, making it essential to understand its core concepts. Whether you are a beginner learning the basics or an experienced developer refining your skills, having a strong grasp of JavaScript is necessary.
In this guide, we provide 20 important JavaScript interview questions along with detailed yet simplified answers. These questions cover key topics such as promises, closures, event loops, asynchronous programming, and object-oriented principles. Understanding these concepts will help you improve your coding skills, debug efficiently, and write cleaner, optimized code.
1. What is JavaScript?
JavaScript is a popular programming language used to create interactive and dynamic web pages. It runs in web browsers and helps add features like animations, form validation, and pop-ups. JavaScript is also used for building web applications, mobile apps, and even server-side programs. It works with HTML and CSS to improve user experience.
2. What are the Different Data Types in JavaScript?
JavaScript has two main types of data: Primitive and Non-Primitive (Reference) Types.
Primitive Data Types:
Primitive data types are immutable (cannot be modified) and stored by value. They include:
1. String – A sequence of characters used to represent text. It is enclosed in single ('
), double ("
) or backticks (`
).
let name = "John"; console.log(typeof name); // "string"
2. Number – Represents numerical values, including integers and floating-point numbers.
let age = 30;
let price = 19.99;
console.log(typeof price); // "number"
3. Boolean – Represents either true
or false
, used for logical decisions.
let isAvailable = true;
console.log(typeof isAvailable); // "boolean"
4. Undefined – A variable that has been declared but not assigned a value
let x;
console.log(typeof x); // "undefined"
5. Null – Represents the intentional absence of any object value.
let y = null;
console.log(typeof y); // "object" (a known JavaScript bug)
6. Symbol – Introduced in ES6, it is a unique and immutable value used to define object properties.
let sym = Symbol("unique");
console.log(typeof sym); // "symbol"
7. BigInt – Introduced in ES11, it is used to represent integers larger than Number.MAX_SAFE_INTEGER
let bigNum = 9007199254740991n;
console.log(typeof bigNum); // "bigint"
Non-Primitive (Reference) Data Types:
Non-primitive data types are stored by reference in memory. They include:
1. Object – A collection of key-value pairs
let person = { name: "Alice", age: 25 };
console.log(typeof person); // "object"
2. Array – A list of values stored in square brackets
let numbers = [1, 2, 3, 4, 5];
console.log(typeof numbers); // "object"
3. Function – A block of code designed to perform a task.
function greet() {
console.log("Hello!");
}
console.log(typeof greet); // "function"
4. Date – Represents dates and times in JavaScript.
let today = new Date();
console.log(typeof today); // "object"
5. RegExp – A regular expression used for pattern matching.
let pattern = /hello/;
console.log(typeof pattern); // "object"
3. What is the Difference Between null and undefined?
null:
null
is a special value that represents “no value” or “empty value.”- It is explicitly assigned to indicate the absence of a value.
typeof null
incorrectly returns"object"
due to a historical JavaScript bug.
Example:
let a = null;
console.log(typeof a); // "object"
undefined:
undefined
means a variable has been declared but has not been assigned a value.- It is the default value for uninitialized variables.
typeof undefined
correctly returns"undefined"
.
Example:
let b;
console.log(typeof b); // "undefined"
4. What is the Difference Between (==) and (===) in JavaScript?
== (Loose Equality Operator):
- Compares values while allowing type conversion (type coercion).
- Different types are converted before comparison.
Example:
console.log(5 == "5"); // true (string "5" is converted to number 5)
console.log(null == undefined); // true (both are treated as empty values)
=== (Strict Equality Operator):
- Compares both value and type without type conversion.
- If types differ, the comparison returns
false
.
Example:
console.log(5 === "5"); // false (number vs. string)
console.log(0 === false); // false (number vs. boolean)
5. What is the typeof Operator and How Does It Work?
typeof
is a JavaScript operator that returns a string representing the data type of a given value.
Example:
console.log(typeof 42); // "number"
console.log(typeof "Hello"); // "string"
console.log(typeof {}); // "object"
console.log(typeof null); // "object" (a known JavaScript bug)
console.log(typeof undefined); // "undefined"
console.log(typeof function(){}); // "function"
6. What is the Difference Between var, let, and const?
Feature | var | let | const |
Scope | Function-scoped | Block-scoped | Block-scoped |
Hoisting | Hoisted with undefined | Hoisted (uninitialized) | Hoisted (uninitialized) |
Reassignment | Allowed | Allowed | Not Allowed |
Redeclaration | Allowed | Not Allowed | Not Allowed |
Example:
var x = 10; // Function-scoped
let y = 20; // Block-scoped
const z = 30; // Block-scoped
z = 40; // Error: Assignment to constant variable
6. Explain Hoisting in JavaScript.
Hoisting is a JavaScript behavior where variable and function declarations are moved to the top of their scope before code execution.
var
variables are hoisted with an initial value ofundefined
.let
andconst
variables are hoisted but remain uninitialized.- Function declarations are hoisted with their full definition.
Example:
console.log(a); // undefined
var a = 5;
console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 10;
7. What are Closures in JavaScript?
A closure is a function that retains access to its parent function’s variables even after the parent function has finished execution.
Example:
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2
8. What is Event Delegation?
Event delegation is a pattern where a parent element handles events of child elements using event bubbling.
Example:
document.getElementById("parent").addEventListener("click", function(event) {
if (event.target.tagName === "BUTTON") {
console.log("Button Clicked!");
}
});
9. What is ‘this’ in JavaScript?
The this
keyword refers to the execution context in which a function is called.
Example:
const obj = {
name: "Alice",
greet: function() {
console.log(this.name);
}
};
obj.greet(); // "Alice"
10. Explain call()
, apply()
, and bind()
.
call()
invokes a function with a specificthis
value and arguments.apply()
is similar but takes arguments as an array.bind()
returns a new function with a boundthis
.
Example:
const person = { name: "Bob" };
function greet(greeting) {
console.log(`${greeting}, ${this.name}`);
}
greet.call(person, "Hello"); // "Hello, Bob"
greet.apply(person, ["Hi"]); // "Hi, Bob"
const newGreet = greet.bind(person);
newGreet("Hey"); // "Hey, Bob"
11. Explain map(), filter(), and reduce().
JavaScript provides powerful array methods that help in processing data efficiently. Three commonly used methods are map(), filter(), and reduce(). Each method has a specific purpose and helps to manipulate arrays easily.
1. map() Method
The map() method is used to transform each element of an array by applying a function to it. It creates a new array with the modified values while keeping the original array unchanged. This is widely used in React.js.
Syntax
array.map(callbackFunction)
callbackFunction
runs for each element in the array.- Returns a new array with transformed elements.
Example
const numbers = [1, 2, 3, 4];
const doubledNumbers = numbers.map(n => n * 2);
console.log(doubledNumbers); // [2, 4, 6, 8]
Explanation:
- Each number in the array is multiplied by
2
. - The original
numbers
array remains unchanged. - The
map()
method returns a new array[2, 4, 6, 8]
.
2. filter() Method
The filter() method is used to filter elements based on a specific condition. It creates a new array with only the elements that satisfy the condition.
Syntax
array.filter(callbackFunction)
callbackFunction
runs for each element.- Returns a new array with elements that pass the condition.
Example
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = numbers.filter(n => n % 2 === 0);
console.log(evenNumbers); // [2, 4, 6]
Explanation:
- The function checks if a number is even (
n % 2 === 0
). - Only even numbers
[2, 4, 6]
are kept. - The original array remains unchanged.
3. reduce() Method
The reduce() method is used to combine all elements of an array into a single value. It performs a calculation by iterating through the array.
Syntax
array.reduce(callbackFunction, initialValue)
callbackFunction
takes two parameters:accumulator
andcurrentValue
.initialValue
is the starting value of the accumulator.- Returns a single value.
Example
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((accumulator, n) => accumulator + n, 0);
console.log(sum); // 10
Explanation:
- The function adds each number to an
accumulator
, starting from0
. - (0 + 1) → (1 + 2) → (3 + 3) → (6 + 4) = 10
- The final result is
10
.
Key Differences Between map(), filter(), and reduce()
Method | Purpose | Returns | Changes Original Array? |
map() | Transforms each element | New array with modified values | No |
filter() | Selects elements based on a condition | New array with filtered values | No |
reduce() | Combines array into a single value | A single value | No |
Intermediate to Advanced JavaScript interview Questions
12. What is a Promise in JavaScript?
A Promise in JavaScript is an object that represents the eventual completion or failure of an asynchronous operation. It provides a way to handle asynchronous tasks such as API calls, file reading, or timers without blocking the execution of the code.
States of a Promise:
- Pending: The initial state; the operation has not completed yet.
- Fulfilled: The operation was successful and returns a resolved value.
- Rejected: The operation failed and returns an error.
Promises are used with .then()
for handling successful operations and .catch()
for handling errors.
Example:
const myPromise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Success!");
}, 2000);
});
myPromise
.then((data) => console.log(data))
.catch((err) => console.log(err));
13. What is async/await and how does it work?
async/await
is a modern approach to handling asynchronous code in JavaScript. It is syntactic sugar over Promises, making asynchronous code look synchronous, thus improving readability.
How it works:
async
function: Declares a function as asynchronous.await
keyword: Pauses execution until a promise resolves or rejects.
Using async/await
makes it easier to read and maintain asynchronous code, eliminating the need for chaining .then()
and .catch()
methods.
Example:
async function fetchData() {
try {
let response = await fetch("https://jsonplaceholder.typicode.com/todos/1");
let data = await response.json();
console.log(data);
} catch (error) {
console.log("Error:", error);
}
}
fetchData();
14. Explain setTimeout() and setInterval() in JavaScript.
setTimeout()
`setTimeout` is a built-in JavaScript function that allows you to execute a piece of code after a specified delay. It takes two main parameters: a callback function that contains the code you want to run and the delay in milliseconds before the code is executed.
setTimeout(() => console.log("Delayed execution"), 3000);
// Logs "Delayed execution" after 3 seconds
setInterval()
`setInterval` is another built-in JavaScript function that allows you to repeatedly execute a piece of code at specified intervals. It works similarly to `setTimeout`, but instead of running the code just once after a delay, it continues to run the code every specified number of milliseconds until it’s stopped.
let counter = 0;
const interval = setInterval(() => {
console.log("Interval running:", ++counter);
if (counter === 5) clearInterval(interval);
}, 1000);
// Logs a message every second, stops after 5 times.
15. What is the Event Loop in JavaScript?
The Event Loop is a crucial mechanism in JavaScript that ensures asynchronous operations (such as callbacks, promises, and event listeners) are executed in a non-blocking manner.
JavaScript executes code in a single-threaded manner, meaning it can handle only one operation at a time. However, asynchronous operations (like setTimeout
, fetch
, and event handlers) are managed using the Event Loop.
How it works:
- Call Stack: Executes synchronous code first.
- Web APIs: Handles asynchronous tasks like
setTimeout
andfetch
. - Task Queue: Holds completed asynchronous operations, waiting for execution.
- Event Loop: Moves tasks from the task queue to the call stack when it’s empty.
Example:
console.log("Start");
setTimeout(() => console.log("Async Task"), 0);
console.log("End");
// Output:
// "Start"
// "End"
// "Async Task"
16. What is Prototypal Inheritance?
Prototypal inheritance is a feature in JavaScript that allows objects to inherit properties and methods from another object, known as the prototype. Unlike class-based inheritance found in other languages, JavaScript uses prototype-based inheritance, where each object has an internal reference (__proto__
) to another object (the prototype).
Example:
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function () {
console.log(`Hello, I'm ${this.name}`);
};
const person1 = new Person("Alice");
person1.sayHello(); // "Hello, I'm Alice"
17. What is Object.create()?
Object.create()
is a method that allows you to create a new object with a specified prototype, enabling inheritance without using constructors.
Example:
const parent = { greet: function () { console.log("Hello!"); } };
const child = Object.create(parent);
child.greet(); // "Hello!"
18. What is Closure in JavaScript?
A closure is a function that retains access to its outer function’s variables even after the outer function has executed. Closures are commonly used in JavaScript for data encapsulation and maintaining state.
Example:
function outer() {
let count = 0;
return function inner() {
count++;
console.log(count);
};
}
const counter = outer();
counter(); // 1
counter(); // 2
19. What is Memoization in JavaScript?
Memoization is a technique for optimizing functions by caching previously computed results to avoid redundant calculations.
Example:
function memoizedAdd() {
let cache = {};
return function (num) {
if (num in cache) {
return cache[num]; // Return cached result
} else {
console.log("Calculating...");
cache[num] = num + 10;
return cache[num];
}
};
}
const add10 = memoizedAdd();
console.log(add10(5)); // Calculating... 15
console.log(add10(5)); // Cached result: 15
20. What is Deep Copy vs Shallow Copy?
When copying objects in JavaScript, it’s important to understand the difference between shallow copy and deep copy, as they impact how data is stored and modified.
Shallow Copy
A shallow copy creates a new object with a copied reference to nested objects. This means that while the top-level properties are cloned, any nested objects still reference the same memory location as the original object.
Example:
const obj = {
name: "Alice",
address: { city: "New York" }
};
// Create a shallow copy using spread operator
const shallowCopy = { ...obj };
shallowCopy.address.city = "Los Angeles";
console.log(obj.address.city); // "Los Angeles" (Mutated!)
Deep Copy
A deep copy creates a completely independent copy of an object, including all nested objects. This ensures that modifying the copied object does not affect the original.
Example:
const obj = {
name: "Alice",
address: { city: "New York" }
};
// Create a deep copy using JSON methods
const deepCopy = JSON.parse(JSON.stringify(obj));
deepCopy.address.city = "San Francisco";
console.log(obj.address.city); // "New York" (Unchanged)
Comparison Table: Shallow Copy vs Deep Copy
Feature | Shallow Copy | Deep Copy |
Copies primitive values | ✅ Yes | ✅ Yes |
Copies object references | ✅ Yes | ❌ No (creates new objects) |
Nested object independence | ❌ No | ✅ Yes |
Mutating copied object affects original? | ✅ Yes | ❌ No |
Performance | ✅ Faster | ❌ Slower |
Preserves functions? | ✅ Yes | ❌ JSON method loses functions |
21. What is the Difference Between map(), forEach(), and reduce()?
JavaScript provides several methods to iterate over arrays, including map()
, forEach()
, and reduce()
. These methods are useful for transforming, iterating, and reducing array data, but they work in different ways.
1. map()
map()
is used to transform each element in an array and return a new array with the transformed values. It does not modify the original array.
Syntax:
array.map((element, index, array) => {
// Return transformed element
});
element
: Current array item.index
(optional):Position of the element in the array.array
(optional): The original array.
Example 1: Doubling Numbers in an Array
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(num => num * 2);
console.log(doubled); // [2, 4, 6, 8]
console.log(numbers); // [1, 2, 3, 4] (original array unchanged)
2. forEach()
forEach()
iterates over an array and executes a function for each element. However, unlike map()
, it does not return a new array—it simply executes the callback function.
Syntax:
array.forEach((element, index, array) => {
// Perform action on each element
});
element
: Current array item.index
(optional): Position of the element in the array.array
(optional): The original array.
Example 1: Logging Each Element
const numbers = [1, 2, 3, 4];
numbers.forEach(num => console.log(num * 2));
// Output:
// 2
// 4
// 6
// 8
Example 2: Modifying an External Variable
jsCopyEditconst numbers = [1, 2, 3, 4];
let sum = 0;
numbers.forEach(num => sum += num);
console.log(sum); // 10
3. reduce()
reduce()
is used to accumulate all array elements into a single value (e.g., sum, product, object, or another structure).
Syntax:
array.reduce((accumulator, element, index, array) => {
// Return updated accumulator
}, initialValue);
accumulator
: The running total or accumulated result.element
: Current array item.index
(optional): Position of the element in the array.array
(optional): The original array.initialValue
(optional): The starting value for the accumulator.
Example 1: Summing an Array
const numbers = [1, 2, 3, 4];
const sum = numbers.reduce((acc, num) => acc + num, 0);
console.log(sum); // 10
How does it work?
acc = 0
,num = 1
→acc + num = 1
acc = 1
,num = 2
→acc + num = 3
acc = 3
,num = 3
→acc + num = 6
acc = 6
,num = 4
→acc + num = 10
Example 2: Finding the Maximum Value in an Array
jsCopyEditconst numbers = [10, 5, 20, 8];
const max = numbers.reduce((acc, num) => (num > acc ? num : acc), numbers[0]);
console.log(max); // 20
Comparison Table: map()
vs forEach()
vs reduce()
Feature | map() | forEach() | reduce() |
---|---|---|---|
Returns a new array? | ✅ Yes | ❌ No | ❌ No (returns single value) |
Modifies the original array? | ❌ No | ❌ No | ❌ No |
Transforms each element? | ✅ Yes | ❌ No (only iterates) | ✅ Yes (but accumulates result) |
Used for computations? | ✅ Yes | ❌ No | ✅ Yes |
Best use case | Transforming data | Performing actions | Aggregating values |
Choosing the Right Method
Scenario | Best Method |
---|---|
You want a new array with transformed values | map() |
You need to iterate over elements but don’t need a new array | forEach() |
You need a single result (sum, max, etc.) | reduce() |