A comprehensive list of important JavaScript Interview Questions and Answers for Beginners with a detailed explanation of the applied JavaScript concept for in-depth understanding.
Anuj Sharma
Last Updated Jul 18, 2025
Advertisement
Practising JavaScript questions is essential to Ace the frontend JavaScript interview round. This comprehensive guide will help you go through important JavaScript interview questions and answers with explanations to solidify your understanding of the core concepts behind these JavaScript interview questions.
Here is the list of JavaScript questions and answers, along with the explanation
Jump directly to the questions
There are 5 major ways to create an object in JavaScript
{ }
to create an object and add key-value properties. This Internally {}
is an instance of Object
only.const person = {
name: "Anuj",
age: 33
};
console.log(person.name); // Output: Anuj
console.log({} instanceof Object) // true
Using new Object() - An Object can be created using the Object class. A new object can be created using by instantiating of Object class.
const person = new Object();
person.name = "Anuj";
person.age = 30;
console.log(person.age); // Output: 30
function Person(name, age) {
this.name = name;
this.age = age;
}
const person1 = new Person("Anuj", 33);
console.log(person1.name); // Output: Anuj
const animal = {
eats: true
};
const cat = Object.create(animal);
cat.sound = "maoww";
console.log(cat.eats); // Output: true (inherited)
console.log(dog.sound); // Output: "maoww"
class Car {
constructor(brand) {
this.brand = brand;
}
}
const myCar = new Car("BMW");
console.log(myCar.brand); // Output: BMW
Here is the difference between DOM and BOM based on purpose & use case.
DOM - Document Object Modal
BOM - Browser Object Modal
In simple terms, Hoisting
is JavaScript’s behavior of moving declarations
to the top (In simple terms to understand) of the current scope before code execution. Here are the examples for variable and function hoisting in JavaScript,
sayHello
even before its definition.sayHello(); // Output: Hello!
function sayHello() {
console.log("Hello!");
}
var
- Similar to JavaScript functions, the JavaScript engine adds the declaration (with undefined) of the var
on top of the scope while interpretation, and that's why the JavaScript engine already found the variable a in the scope with value - undefined, and that's why it printed undefined.console.log(a); // Output: undefined
var a = 10;
let
& const
- Technically let
and const
are hoisted, but they are in a "temporal dead zone" and can't be accessed before they are defined.console.log(b); // ReferenceError: b is not defined
let b = 5;
💡Learn more about hoisting
Declaration using var
function demoVar() {
console.log(x); // undefined, hoisted
var x = 10;
console.log(x); // 10
}
demoVar();
Declaration using let
{}
) where it is defined.function demoLet() {
console.log(y); // ReferenceError
let y = 20;
console.log(y); // 20
}
demoLet();
Declaration using const
let
.const z = 30;
z = 40; // Error: Assignment to constant variable
console.log(z); // 30
JavaScript is single-threaded, but can handle asynchronous tasks using the event loop. Event loop is the part of the javascript engine which continously loop through to move tasks from Microtask(Promises) and MacroTask(setTimeout, setInterval) queues to the Call Stack for the execution.
Note: Immediately after every macrotask, the event loop move all tasks from microtask queue to the javascript call stack for execution, prior to running any other macrotasks or rendering or anything else.
👇 Here's how it works:
JavaScript Engine has a Call Stack to execute the code instructions. from LIFO (last In, First Out) fashion.
Browser's Web APIs handle things like setTimeout
, AJAX, etc.
There are MicroTask and MacroTask Queues which handles promises and WebAPIs. It waits to push tasks to the call stack when empty.
The Event Loop keeps checking if the stack is empty — if so, it takes tasks from the queue and runs them.
console.log("Start");
setTimeout(() => {
console.log("Timeout");
}, 0);
console.log("End");
// Output
Start
End
Timeout
Note: Even though setTimeout
has 0ms
delay, it goes to the task queue and runs after the synchronous code finishes.
"JavaScript is Single-Threaded", meaning it has one call stack, and it can only execute one code instructions at a time. JavaScript can support asynchronus tasks becuase of the event loop and browser APIs.
A closure is when a function remembers the variables from its outer scope, even after that outer function has finished running.
function outer() {
let count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
const counter = outer(); // outer runs and returns inner
counter(); // 1
counter(); // 2
counter(); // 3
Even though outer()
is done executing, the inner()
function still remembers the variable count
. That’s a closure!
Why Closures are Useful:
Currying is a technique of transforming a function with multiple arguments into a sequence of functions, each taking a single argument. Currying is use-ful to provide partial application where some of the application already build but new functionalities can be build on top of the existing applicaiton.
Use case: Primary use case of the Currying is implementation of "Partial application" which can be run independently or along with the other independent other applications.
// Normal function
function add(a, b) {
return a + b;
}
// Curried version
function curryAdd(a) {
return function(b) {
return a + b;
};
}
console.log(curryAdd(2)(3)); // 5
// Use case: create partial function
const add5 = curryAdd(5);
console.log(add5(10)); // 15
Answer:
Feature | setTimeout |
setInterval |
---|---|---|
Runs | Run once after the input delay | Runs repeatedly on given Interval |
Usage | Delayed execution | Repeated execution at intervals |
setTimeout(() => {
console.log("Runs once after 1s");
}, 1000);
setInterval(() => {
console.log("Runs every 1s");
}, 1000);
this
refers to the object that is executing the current function. Its value depends on the context.
// Global context (browser)
console.log(this); // window
// Object method
const user = {
name: "Anuj",
greet() {
console.log("Hello", this.name); // 'this' refers to user
}
};
user.greet(); // Hello Anuj
// Arrow function (lexical `this`)
const obj = {
value: 10,
show: () => {
console.log(this.value); // undefined (arrow doesn't bind `this`)
}
};
obj.show();
More references
A Promise is a JavaScript object that represents the future result of an asynchronous operation, before promise code requires the callback hell in order to execute the callback code.
✅ What are the benifits of using Promises?
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("Data received");
}, 1000);
});
};
fetchData()
.then((data) => console.log(data)) // "Data received"
.catch((err) => console.error(err));
Async-Await can also be used for the asynchornousn task handling which has been developed on top of the promise to provide a functionality where async code can be executed similar to the synchronos code, execution halts untill await function returns the result.
async function fetchUserData() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const user = await response.json();
console.log("User:", user.name);
} catch (error) {
console.error("Error fetching user:", error);
}
}
fetchUserData();
Bubbling and capturing both are phases in the DOM event propagation model. In the capturing phase, event propogation happens from child to parent, but in capturing phase event propogation happened from Parent to Child elements.
Feature | Bubbling | Capturing |
---|---|---|
Direction | Child → Parent | Parent → Child |
Default Behavior | ✅ Yes | ❌ Only with { capture: true } In addEventListener function. |
// Bubbling
document.getElementById("parent").addEventListener("click", () => {
console.log("Parent bubbling");
});
// Capturing
document.getElementById("parent").addEventListener("click", () => {
console.log("Parent capturing");
}, true);
Event delegation is when a parent element handles events for its child elements using a single event listener.
✅ Why use it?
<ul id="todo-list">
<li>Buy milk</li>
<li>Walk dog</li>
</ul>
<button id="add">Add New Item</button>
const list = document.getElementById("todo-list");
const addBtn = document.getElementById("add");
// Event Delegation: single listener on parent
list.addEventListener("click", (event) => {
if (event.target.tagName === "LI") {
alert(`You clicked: ${event.target.textContent}`);
}
});
// Dynamically add new items
addBtn.addEventListener("click", () => {
const newItem = document.createElement("li");
newItem.textContent = "New Task " + Math.floor(Math.random() * 100);
list.appendChild(newItem);
});
Method | Purpose |
---|---|
stopPropagation() |
Stops event from bubbling/capturing |
preventDefault() |
Stops the default action of the element |
document.querySelector("a").addEventListener("click", function (e) {
e.preventDefault(); // stops link navigation
e.stopPropagation(); // stops event bubbling
console.log("Click handled");
});
Feature | Object.freeze() |
Object.seal() |
---|---|---|
Add properties | ❌ No | ❌ No |
Modify values | ❌ No | ✅ Yes |
Delete props | ❌ No | ❌ No |
Configurable | ❌ No | ✅ No |
const frozen = Object.freeze({ a: 1 });
frozen.a = 2; // ❌ fails silently
const sealed = Object.seal({ a: 1 });
sealed.a = 2; // ✅ works
delete sealed.a; // ❌ fails
Operator | Name | Checks |
---|---|---|
== |
Loose equality | Values after type coercion |
=== |
Strict equality | Values and types both |
console.log(5 == "5"); // true (coerced)
console.log(5 === "5"); // false (different types)
Note: Prefer ===
in real-world code for type safety.
Prototypal inheritance is a feature in JavaScript where objects can inherit properties and methods from their parent object using the [[Prototype]]
chain. Every JavaScript object has an internal link to its parent object called its prototype, and it can delegate behavior (methods/properties) to that prototype. This allows reusability and shared behaviour across objects. Here is the example
const animal = {
eats: true,
walk() {
console.log("Animal walks");
}
};
const dog = Object.create(animal); // dog inherits from animal
dog.barks = true;
console.log(dog.eats); // true (inherited)
dog.walk(); // Animal walks
Inheritance in JavaScript using Constructor Function (ES5)
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
console.log(`${this.name} makes a noise.`);
};
function Dog(name) {
Animal.call(this, name); // call parent constructor
}
Dog.prototype = Object.create(Animal.prototype); // inherit prototype
Dog.prototype.constructor = Dog;
const dog = new Dog("Moti");
dog.speak(); // Moti makes a noise.
Inheritance in JavaScript using Class (ES6)
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(`${this.name} makes a noise.`);
}
}
class Dog extends Animal {
constructor(name) {
super(name); // call parent constructor
}
}
const dog = new Dog("Moti");
dog.speak(); // Moti makes a noise.
Feature | Arrow Function | Normal Function |
---|---|---|
this Scope |
Lexical scope (inherits from parent scope) |
Dynamic Scoping (depends on how called) |
Constructor usage | ❌ Can't be used as constructor | ✅ Can use new keyword |
arguments object | ❌ Not available | ✅ Available |
Here is the example
const obj = {
value: 10,
regularFn: function () {
console.log("Regular:", this.value);
},
arrowFn: () => {
console.log("Arrow:", this.value); // this -> Parent Laxical scope
}
};
obj.regularFn(); // Regular: 10
obj.arrowFn(); // Arrow: undefined
Here are the ways to create Shallow and Deep clone in JavaScript :
Shallow Clone in JavaScript
const original = { a: 1, b: 2 };
const clone = Object.assign({}, original);
const original = {name: 'Anuj', lastname: 'Sharma'}
const clone = { ...original };
Deep clone in JavaScript
const original = {
name: 'Anuj',
lastname: 'Sharma',
address: {
pin: 411057
}
}
const deepClone = structuredClone(original);
Functions can be used in the most versatile ways in JavaScript, and all the constructs can be defined as functions, for example
Method | Calls function immediately | Arguments passed | Returns |
---|---|---|---|
call Fn.call(a,b,c) |
✅ Yes | Individually like general parameter | Return value of function |
apply Fn.apply([a,b,c]) |
✅ Yes | Array | Return value of function |
bind Fn.bind(context) |
❌ No (returns a new function) | Individually like general parameter | New function, bounded with context passed. |
Examples
function greet(greeting, lastname) {
console.log(`${greeting}, ${this.name} ${lastname}`);
}
const person = { name: "Anuj" };
// Call
greet.call(person, "Hello", "Sharma"); // Hello, Anuj Sharma
// Apply
greet.apply(person, ["Hi", "Sharma"]); // Hi, Anuj Sharma
// Bind
const boundGreet = greet.bind(person, "Hey", " Sharma");
boundGreet(); // Hey, Anuj Sharma
Checkout polyfills to learn more
Prototype chaining is a way JavaScript enables inheritance. Every object has an internal link (__proto__
) to its prototype, forming a chain. When you try to access a property, JavaScript looks up the parent chain until it finds it or hits null
.
const animal = {
eats: true
};
const dog = {
barks: true
// __proto__: animal <- This can be assigned like this
};
// Prototype chain
Object.setPrototypeOf(dog, animal)
console.log(dog.barks); // true
console.log(dog.eats); // true (inherited from animal)
Browser provides localstorage & sessionstorage to store the key-values.
Feature | localStorage |
sessionStorage |
---|---|---|
Lifespan | Until manually cleared | Until browser/tab is closed |
Scope | Shared across tabs/windows | Only in current tab/window |
Capacity | ~5–10MB | ~5MB |
Here is the example
localStorage.setItem("token", "abc123");
sessionStorage.setItem("user", "Anuj");
console.log(localStorage.getItem("token")); // "abc123"
console.log(sessionStorage.getItem("user")); // "Anuj"
<script />
, <script async />
and <script defer />
?Tag Type | Blocks HTML parsing? | When script runs? | Execution Order |
---|---|---|---|
<script> |
✅ Yes | Immediately after download | In order |
<script async> |
❌ No | As soon as downloaded (out of order) | ❌ No guarantee |
<script defer> |
❌ No | After HTML is fully parsed | ✅ In order |
Example
<script src="sync.js"></script>
<script async src="async_script.js"></script>
<script defer src="defer_script.js"></script>
Here are the 2 ways to merge objects
const obj1 = { a: 1 };
const obj2 = { b: 2 };
const merged = Object.assign({}, obj1, obj2);
console.log(merged); // { a: 1, b: 2 }
const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = { ...obj1, ...obj2 };
console.log(merged); // { a: 1, b: 3, c: 4 }
Note: Since both the above options provide shallow merging, if there is a specific requirement to merge complex objects, we can either create a custom recursive solution or use the lodash merge function.
Advertisement
Advertisement
Advertisement
Alok Kumar Giri
Last Updated Jun 2, 2025
Code snippet examples which will help to grasp the concept of Hoisting in JavaScript, with solutions to understand how it works behind the scene.
Anuj Sharma
Last Updated Jun 13, 2025
A comprehensive cheat sheet for the Frontend Machine Coding Interview Round, which helps to revise all the important machine coding & UI design concepts before the interview.
Anuj Sharma
Last Updated Jun 27, 2025
A detailed list of 20+ most asked Frontend Machine Coding Interview Questions and resources both in JavaScript & React. Also covers expected functional/Non-functional requirements in this Interview.
Anuj Sharma
Last Updated Jul 15, 2025
Understand what all steps are involved in the Critical Rendering Path (CRP) and how optimization of different steps can improve the overall web-vitals of a web application
Anuj Sharma
Last Updated Jan 29, 2025
Understand the difference between HTTP/2 vs HTTP/1.1 based on the various parameters, which helps to understand the improvement areas of HTTP/2 over HTTP 1.1
Akash Deep Chitransh
Last Updated May 26, 2025
Learn how to build and publish your own NPM package with Rollup, testing, and troubleshooting. Stay tuned for part 2: building a React state management library!
© 2024 FrontendGeek. All rights reserved