Top 50 JavaScript Interview Questions and Answers (2026 Guide)

Over the past couple of months, I have taken quite a few JavaScript interviews, even in this AI-dominated era. And you might be wondering: where do interviewers actually get their questions from? Do they use a specific website, a book, or just come up with them on the spot?

Well, here’s the truth is most of us simply search the internet, pick a mix of popular but underrated questions, throw in some fundamental ones for beginners, and save them on our phones. Then we keep asking the same set of questions again and again, at least that’s what my colleagues and I usually do.

So I thought, why not share my own top 50 JavaScript interview questions with my readers? Maybe it will help you get that next job!

And no, I am not leaking any secret questions. These are the core concepts of JavaScript itself. If you truly understand each of them, you can crack almost any JavaScript interview out there.

So take this seriously, go through each question carefully, and keep them fresh in your mind. Who knows you might end up facing me in your next interview. 😉 Good luck!

JavaScript Fundamentals

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

We use these three keywords to create, or declare, variables. Their main differences are scope, reassignment, and hoisting.

var is the old way. It is “function-scoped”, which means it can be seen anywhere inside a function, even outside of if blocks. This can sometimes be confusing.

let and const are the modern way. They are “block-scoped”. This means they only exist inside the curly braces {} they were created in. This is much easier to predict.

We can change the value of a var or let variable later.

We cannot change the value of a const variable. We must also give it a value when we first declare it.

A very important point is that const does not make an object or array “immutable”. We can still change the properties inside a const object. We just cannot reassign the variable to a new object.

Featurevarletconst
ScopeFunctionBlockBlock
Can We Reassign?YesYesNo
Hoisted?Yes (value is undefined)Yes (in TDZ)Yes (in TDZ)

2. What are the primitive data types in JavaScript?

JavaScript has seven primitive data types. A primitive is a simple value that is not an object.

  1. string: Used for text, like “hello”.
  2. number: Used for all numbers, like 5 or 5.5.
  3. bigint: Used for very large numbers.
  4. boolean: Used for true or false values.
  5. undefined: Used when a variable is declared but not given a value.
  6. symbol: Used to create unique values.
  7. null: Used to show an intentional empty value.

Everything else is an Object.

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

These are both used to compare two values.

=== (Triple Equals) is called “strict equality”. It checks if the value and the type are the same. We should almost always use this one. For example, 5 === '5' is false because one is a number and one is a string.

== (Double Equals) is called “loose equality”. It tries to be helpful by converting the types before it compares. This is called type coercion. For example, 5 == '5' is true because it converts the string to a number first. This “help” can create confusing bugs.

4. What is the difference between null and undefined?

Both mean “no value”, but they are different.

undefined is what JavaScript gives us automatically. It means a variable was declared, but no value was ever assigned to it. It is an accidental empty value.

null is what we, the developers, give intentionally. It is a purposeful “this is empty” value.

A simple way to think about it: undefined is like a “404 Not Found” error. null is like a “blank page” that was loaded on purpose.

When using JSON.stringify, properties with a null value are kept. Properties with an undefined value are removed.

5. What is hoisting in JavaScript?

Hoisting is a JavaScript behavior where it moves all variable and function declarations to the top of their scope before it runs the code.

For var, the variable is moved up and given the value undefined. This is why we can log a var before we declare it and see undefined.

let and const are also hoisted, but they are not given a value. They are in a “Temporal Dead Zone” (TDZ). This just means we must declare them before we try to use them. If we do not, we get a ReferenceError. This is a good thing that prevents bugs.

6. What is scope in javascript?

Scope is the “context” or “area” where our variables are visible and can be used. We can think of our code as a town.

Global Scope: This is the “public square” of the town. Variables declared here (outside all functions) can be seen from anywhere. We should avoid this because it can cause conflicts.

Function Scope: This is like a “private house”. Variables created inside a function can only be seen inside that function.

Block Scope: This is like a “private room” inside the house (like an if statement or a for loop {}). Variables created with let and const only exist inside that one room.

7. What is a strict mode in javascript?

This is a special “safety mode” we can turn on in JavaScript. We turn it on by writing "use strict"; at the very top of our file or a function.

Its main job is to change “silent errors” into real errors. For example, in normal JavaScript, if we use a variable without declaring it, JavaScript creates a global variable for us. This is very bad.

In strict mode, this is a ReferenceError. It forces us to write cleaner, safer code. We often do not need to write this ourselves because modern features like ES6 Modules automatically use strict mode.

Functions and the ‘this’ Keyword

8. What are closures?

A closure is when a function remembers the variables from the place where it was created, even after the parent function has finished running.

For example, if we have an outer function that creates a variable x and returns a new inner function, that inner function will always have access to x.

The most common use for this is to create “private variables”. We can hide a variable inside the parent function and only allow it to be changed by the inner function.

9. What is the purpose of the this keyword in JavaScript?

The this keyword is a special variable that refers to the “owner” of a function call. Its value changes depending on how a function is called.

Here are the simple rules:

  1. Global: When used alone, this is the global window object.
  2. Object Method: When a function is called as a method on an object (like person.sayHello()), this is the person object.
  3. Constructor: When we use the new keyword (like new Person()), this is the new empty object being created.
  4. Event Handler: In a DOM event, this is the HTML element that the event happened on.

10. What are the differences between arrow functions and regular functions?

Arrow functions (=>) were added in ES6. They are different from regular function keywords in three main ways:

  1. No this binding: This is the most important difference. Arrow functions do not get their own this. They “borrow” the this from their parent scope. This is very useful for callbacks like setTimeout or .map().
  2. No arguments object: Arrow functions do not have the special arguments object. This is fine, because we can use the modern ...rest operator instead.
  3. Cannot be constructors: We can never use the new keyword with an arrow function.

11. What is an IIFE (Immediately Invoked Function Expression)?

An IIFE is a function that we run immediately after we define it.

We write it by wrapping a normal function in parentheses, and then adding another set of parentheses at the end to call it, like this: (function() {... })();.

In the past, we used this to create a private scope. Before let and const, any variable outside a function was global. An IIFE created a “private world” for a library so it did not “pollute” the global scope. We see it less today, but it is important to recognize.

12. What is the Difference Between call , apply , and bind?

All three of these methods let us control what the this keyword is inside a function.

call(): Sets this and runs the function immediately. It takes any other arguments one by one, separated by commas.

apply(): Sets this and runs the function immediately. It is just like call, but it takes the arguments as a single array. (A good way to remember: Apply = Array).

bind(): Sets this but does not run the function. It returns a new function that is permanently “bound” to that this. (A good way to remember: Bind = Bound function).

MethodRuns Immediately?Argument Format
callYesList of arguments
applyYesSingle array
bindNo (returns function)List of arguments

13. What are the differences between pure and impure functions?

This is a concept about how predictable a function is.

Pure Function has two rules: 1. It always returns the same output if we give it the same inputs. 2. It has no “side effects”, meaning it does not change anything outside of itself (like a global variable).

An Impure Function is the opposite. It might change something (like console.log or a network request) or return a different value each time (like Math.random()).

We prefer pure functions because they are very easy to test and debug.

Asynchronous JavaScript (The Event Loop)

14. What is a callback function?

A callback is a function that we pass into another function as an argument.

We are telling the other function, “Do your job… and when you are done, call this function back.”

The most common example is setTimeout(myFunction, 1000)myFunction is the callback. We give it to setTimeout, which will “call it back” after one second. This is the foundation of asynchronous JavaScript.

15. What is a callback hell?

Callback hell is what happens when we need to do many asynchronous tasks in order.

For example: First, get the user. Then, get their posts. Then, get their comments. This makes us nest callbacks inside other callbacks, inside other callbacks.

The code starts to look like a sideways pyramid, which is why it is also called the “Pyramid of Doom”. This code is very hard to read and debug. Callback hell is the problem that Promises were created to solve.

16. What is a promise?

A Promise is an object that represents the future result of an asynchronous task.

It is like a “subscription”. Instead of nesting, we chain methods. A Promise gives us two methods: .then() for a successful result and .catch() for a failure.

This lets us write doSomething().then(doNextThing).then(doAnotherThing). This is much cleaner and “flatter” than callback hell.

17. Explain the three states of promise

A Promise is always in one of three states:

  1. pending: The initial state. The task has started but is not finished yet.
  2. fulfilled: The task finished successfully. The result is available.
  3. rejected: The task failed. An error is available.

A promise starts as pending and can only move to fulfilled or rejected one time. It can never change after that.

18. What is promise.all?

This is a helper function for when we have many promises and we want to wait for all of them to finish.

We give Promise.all an array of promises. It gives us back a new promise.

This new promise will only fulfill when all the promises in the array are fulfilled. If even one promise in the array rejects, the whole Promise.all will reject immediately.

19. What is an async function?

This is the newest and easiest way to work with Promises. It uses two keywords: async and await.

async: When we put async before a function, it does two things: 1. It automatically makes the function return a Promise. 2. It allows us to use the await keyword inside it.

await: This keyword can only be used inside an async function. When we put await in front of a Promise, it pauses the function and waits for the Promise to finish.

This lets us write asynchronous code that looks like normal, synchronous code. We can use a simple try...catch block to handle errors.

20. What is the event loop?

JavaScript can only do one thing at a time. The event loop is the system that lets it look like it is doing many things at once.

It works like this:

  1. Call Stack: This is the “work area”. JavaScript runs one task at a time here.
  2. Background / Web APIs: When we call setTimeout, JavaScript gives that task to the browser to handle. The Call Stack is now free.
  3. Callback Queue: When the browser finishes the timer, it puts our callback function in this “waiting line”.
  4. Event Loop: This is a “manager” that constantly checks one thing: “Is the Call Stack empty?” When it is, the manager takes the first function from the waiting line and puts it on the stack to run.

21. What are microtasks?

This is a special, high-priority “waiting line” for the event loop.

There are two waiting lines:

  1. The Task Queue (or “Macrotask” Queue): This is for setTimeout and click events.
  2. The Microtask Queue: This is only for Promise callbacks (like .then() and .catch()).

The event loop manager always checks the Microtask Queue first. It will run every microtask until that line is empty before it runs even one task from the regular Task Queue. This is why a Promise always runs before a setTimeout.

Modern JavaScript (ES6+ Features)

22. What is destructuring assignment?

This is a shortcut for getting data out of an object or array.

For an object: Instead of writing const name = person.name and const age = person.age, we can just write const { name, age } = person.

For an array: Instead of writing const first = fruits, we can just write const [first] = fruits.

We can also use it to give new variable names or set default values.

23. What are the differences between spread operator and rest parameter?

They both use three dots (...), but they are opposites. It depends on where we use them.

Rest Parameter: We use this inside a function’s parameters, like function myFunc(...args). It “gathers” many arguments into a single array.

Spread Operator: We use this everywhere else, like const newArray = [...oldArray]. It “spreads” an array or object out into individual pieces.

OperatorWhere is it Used?What does it do?
RestInside function parametersGathers items into an array
SpreadIn arrays, objects, function callsExpands items out

24. What are template literals?

Template literals use backticks (`) instead of quotes. They give us two main benefits:

  1. Embedded Expressions: We can put variables directly into the string using ${...}. For example, `Hello, ${name}`. This is much cleaner than "Hello, " + name + "!".
  2. Multi-line Strings: We can just press “Enter” to make a string that spans multiple lines. We do not need to use \n.

25. What is optional chaining?

This is the ?. operator. It is a “safe” way to access nested properties.

It solves the most common error in JavaScript: “TypeError: Cannot read property ‘x’ of undefined”.

Instead of writing const city = user.address.city, which will crash if user.address does not exist, we write const city = user?.address?.city.

JavaScript will check at each step. If it finds null or undefined, it stops and returns undefined. It does not crash.

26. What is nullish coalescing operator (??)?

This is the ?? operator. It is a “smarter” way to set a default value.

The old way was to use the || (OR) operator, like `const speed = userSpeed |

| 50. This has a bug. If userSpeedis00is a "falsy" value, sospeedwill become50`. This is wrong.

The ?? operator is smarter. It only gives the default value if the left side is null or undefined.

If we write const speed = userSpeed?? 50, and userSpeed is 0speed will correctly be 0.

Working with Arrays

27. What is the difference between slice and splice?

This is a common question about changing arrays.

slice() (with a “c”) Copies a part of an array. It does not change the original array. It gives us a new array.

splice() (with a “p”) Permanently changes the original array. We use it to add or remove elements from the array.

28. What is the difference between map and forEach functions?

Both of these loop over an array, but they have one very important difference.

forEach(): Just loops over the items. It does not return any value (it returns undefined). We use it when we want to do something, like console.log each item.

map(): Loops over the items, runs a function on each one, and returns a new array with the new, transformed values. It does not change the original array.

The simple rule is: If we need a new array, we use map(). If we just need to loop, we use forEach().

29. How do you check if a variable is an array?

We cannot use typeof. If we write typeof, it will say "object", which is not helpful.

The correct, modern way is to use Array.isArray().

For example, Array.isArray(myVariable) will return true if it is an array and false for everything else.

30. How do you empty an array?

There are two common ways.

  1. Re-assignment: myArray =. This is simple, but it creates a new empty array. If another variable was pointing to the original array, it will not see this change.
  2. Setting length: myArray.length = 0. This is usually the better answer. It changes (mutates) the original array. Any other variable pointing to that array will see it is now empty.

The Browser (DOM and Web APIs)

31. What is the DOM?

DOM stands for “Document Object Model”.

A simple way to think about it is that our HTML file is the blueprint for a house. The DOM is the actual house that the browser builds in memory from that blueprint.

JavaScript cannot read our HTML file. It can only talk to the DOM. We use the DOM to find elements, change their style, add new content, or listen for clicks.

32. What is an event delegation?

This is a smart and fast way to handle events.

Imagine we have a list with 100 items. We could add 100 click listeners, one for each item. This is slow.

With event delegation, we add one single click listener to the parent <ul> element.

When we click a list item, the event “bubbles up” to the parent. The parent listener catches it and uses event.target to see which child was actually clicked.

This is faster, and it automatically works for new items we add to the list later.

33. What are the differences between cookie, local storage and session storage?

These are three ways to store data in the browser.

FeatureCookielocalStoragesessionStorage
Storage LimitVery Small (4KB)Larger (5-10MB)Larger (5-10MB)
ExpirationWe set this (e.g. 30 days)Never. Stays forever.When tab closes.
Sent to Server?Yes. On every request.No. Never.No. Never.

We use Cookies for server authentication. We use localStorage for “remember me” settings. We use sessionStorage for data that should be gone when the user closes the tab, like a form.

34. What is JSON?

JSON stands for “JavaScript Object Notation”. It is the most common text format for sending and receiving data from a server.

It looks like a JavaScript object, but it is not. It is a string.

JSON has two main rules: 1. All keys must be in double quotes. 2. It cannot hold functions, only simple data.

35. What is the purpose JSON stringify?

JSON.stringify() is a built-in function that converts a JavaScript Object into a JSON String.

We must do this before we send data to a server.

36. How do you parse JSON string?

JSON.parse() is the opposite. It is a built-in function that converts a JSON String (that we get from a server) into a real JavaScript Object that we can use.

Tricky Questions and Concepts

37. What would be the result of 1+2+’3′?

The result is the string "33".

This is because JavaScript reads from left to right.

First, it sees 1 + 2. Both are numbers, so it does math and gets 3.

Next, it sees 3 + '3'. It cannot add a number and a string.

So, it converts the number 3 to a string "3".

Finally, it adds "3" + "3", and the result is "33".

38. What is NaN property?

NaN stands for “Not a Number”. It is a special value we get when a math operation fails, like 0 / 0.

The tricky part is that NaN is the only value in JavaScript that is not equal to itself. NaN === NaN is false.

Because of this, we cannot check for it with myValue === NaN. We must use the built-in function Number.isNaN(myValue).

39. What is the difference between pass by value and pass by reference?

This is about what happens when we pass a variable to a function.

Pass by Value: This is for Primitives (string, number, boolean). The function gets a copy of the value. If the function changes its copy, the original variable outside is not changed.

Pass by Reference: This is for Objects (and Arrays). The function gets a reference (a pointer) to the same object in memory. If the function changes a property on that object (like myObj.name = 'New'), the original object is also changed.

40. What is a polyfill?

A “polyfill” is a piece of code that adds a new JavaScript feature to old browsers.

For example, if we want to use Array.flat(), but an old browser does not have it, the polyfill will check if the function exists. If it does not, the polyfill will create it for us. This lets us write modern code without breaking old browsers.

41. What is the purpose of the delete operator?

The delete operator is used to remove a property from an object.

For example, delete person.age.

It is important to know that it does not delete variables. It only works on object properties.

42. What is the difference between Shallow and Deep copy?

This is about copying objects.

Shallow Copy: This only copies the top level of an object. An easy way is const newObj = {...oldObj }. If the object has a nested object inside, the shallow copy only copies the reference to the nested object. Both the new and old object point to the same nested object.

Deep Copy: This copies everything, including all nested objects. The most common “hack” for this is JSON.parse(JSON.stringify(oldObj)).

43. What is the output of typeof null?

The answer is "object".

This is a famous, historical bug from the first version of JavaScript. null is a primitive type, but typeof incorrectly reports it as an “object”. It cannot be fixed because changing it would break thousands of websites.

44. What are the possible reasons for memory leaks?

A memory leak is when our program uses memory but forgets to release it, causing it to slow down and crash.

Three common causes are:

  1. Global Variables: Creating variables that live forever.
  2. Forgotten Timers: A setInterval that runs forever and holds a reference to an object.
  3. Detached DOM Elements: Removing an element from the page, but still keeping a variable in JavaScript that points to it.

45. What is debouncing?

This is a technique to control how often a function runs.

Imagine a search bar. We do not want to search on every single keystroke.

Debouncing says: “Wait until the user has stopped typing for 300 milliseconds, and then run the search function only once.”

46. What is throttling?

This is another technique to control a function, but it is different.

Imagine a “scroll” event. Throttling says: “I do not care how many times you are scrolling. I will run the function at most one time every 100 milliseconds.”

Debounce runs after the user stops. Throttle runs during the action, but at a limited rate.

47. What is memoization?

This is a “caching” technique for slow functions.

The first time we run a slow function like calculate(40), we save the result in a cache.

The next time we call calculate(40), we do not run the slow calculation. We just return the saved result from the cache. This only works for pure functions.

48. What are wrapper objects?

This is a “trick” JavaScript does.

A primitive string (like "hello") is not an object and has no methods.

So why can we write "hello".toUpperCase()?

When we use the . on a primitive, JavaScript temporarily “wraps” it in an object (like new String("hello")). It runs the method on that object, gets the result, and then throws the wrapper object away.

49. How do you handle errors in JavaScript?

There are two main ways:

  1. For Synchronous Code: We use a try...catch block. We put the risky code in the try block. If an error happens, the code in the catch block will run.
  2. For Asynchronous Code: If we are using Promises, we chain a .catch() block at the end. If we are using async/await, we use a try...catch block, just like synchronous code.

50. What is the difference between proto and prototype?

This is a very common question. Here is a simple way to remember it.

prototype is a property that only functions have. It is an object. When we use that function as a constructor (with the new keyword), this prototype object is what the new instances will inherit from.

__proto__ is a property that all objects have. It is a pointer or a link. It points to the prototype object of the function that created it.

When we try to find a method on an object, JavaScript looks at the object. If it is not there, it follows the __proto__ link to its constructor’s prototype and looks there. This is the “prototype chain”.

Conclusion

That is all 50 questions. Congratulations on making it to the end. We hope this guide helps you feel much more prepared.

Remember that these JavaScript interview questions are just a way to check your understanding. The most important thing is to keep building, keep learning, and stay curious and believe me, you are on the right path. Good luck!

Aditya Gupta
Aditya Gupta
Articles: 444
Review Your Cart
0
Add Coupon Code
Subtotal