120+ JavaScript Interview Questions and Answers for 2026

Javascript Interview Questions and Answers

JavaScript interviews test more than familiarity with syntax. Candidates are often asked to predict code output, explain how functions handle scope and references, and identify why a particular expression produces an unexpected result. These questions appear in frontend, full-stack and Node.js interviews, although the depth varies by role.

This collection of 120+ JavaScript interview questions and answers covers language fundamentals, objects, prototypes, asynchronous execution, browser APIs, performance and coding problems. Examples use modern JavaScript syntax, with explanations of older features such as var where they remain relevant to interviews and existing codebases.

Start with the fundamentals if you’re preparing for an entry-level interview. Developers with experience can move directly to the sections on the event loop, Promises, object behaviour and debugging code output.

Key Highlights

  • For freshers: Data types, variables, equality, coercion, hoisting, scope and functions.
  • For experienced developers: Closures, prototypes, this, asynchronous execution, performance and memory management.
  • Code-based preparation: JavaScript snippets with expected results and explanations of the underlying behaviour.
  • Browser topics: DOM manipulation, event handling, browser storage and Web APIs.
  • Interview practice: Array operations, string problems, debugging and common output-based questions.
  • Technical scope: JavaScript language behaviour is distinguished from browser and runtime-specific features.

JavaScript Interview Questions for Freshers

The first 20 questions cover language behaviour that interviewers expect candidates to understand before discussing frameworks or application architecture. Pay attention to the distinction between what JavaScript guarantees and what a particular runtime provides.

1. What is JavaScript?

JavaScript is a programming language used to build interactive websites, web applications and server-side software. Browsers execute JavaScript to handle user interactions and update page content. Runtimes such as Node.js also allow JavaScript to run outside a browser.

The language is dynamically typed and supports several programming styles, including functional and object-oriented programming. JavaScript uses a prototype-based object model, although modern code can also express object-oriented structures through class syntax.

2. Is JavaScript compiled or interpreted?

Modern JavaScript engines commonly use both interpretation and compilation techniques. An engine parses JavaScript source code, produces an internal representation and executes it using an implementation-specific strategy.

For example, Google’s V8 engine uses compilation and optimisation techniques, including just-in-time compilation, to improve execution speed. The ECMAScript specification defines language behaviour rather than requiring every engine to use the same execution strategy.

3. Is JavaScript statically typed or dynamically typed?

JavaScript is dynamically typed. A variable can refer to values of different types during program execution, and the runtime evaluates operations according to the types of the values involved.

let value = 10;
value = "hello";
value = true;

console.log(typeof value); // "boolean"

Here, the same variable first holds a number, then a string and finally a boolean. TypeScript can add static type checking during development, but that does not change JavaScript’s runtime type system.

4. What are the primitive data types in JavaScript?

JavaScript has seven primitive types: string, number, bigint, boolean, undefined, symbol and null.

TypeExample
string"JavaScript"
number42, 3.14
bigint9007199254740993n
booleantrue, false
undefinedundefined
symbolSymbol("id")
nullnull

Objects are non-primitive values. Arrays and functions are also objects, although callable functions receive a special result from the typeof operator.

5. What is the difference between primitive values and objects?

Primitive values are immutable. An object can contain properties whose values may be changed, subject to the object’s configuration.

let first = 10;
let second = first;

second = 20;

console.log(first); // 10

const user =  ;
const copy = user;

copy.score = 20;

console.log(user.score); // 20

The number assigned to second is independent of first. By contrast, user and copy refer to the same object. Changing that object’s score property is visible through either variable.

JavaScript arguments are passed by value. When the value is an object reference, a function can modify the referenced object’s properties, but reassigning the parameter does not replace the caller’s variable.

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

Featurevarletconst
ScopeFunction or global scopeBlock scopeBlock scope
ReassignmentAllowedAllowedNot allowed
Redeclaration in the same scopeGenerally allowedNot allowedNot allowed
Access before declarationTypically undefined for an uninitialised bindingReferenceError during the temporal dead zoneReferenceError during the temporal dead zone
Initialiser requiredNoNoYes, for ordinary declarations

const prevents reassignment of the binding. It does not freeze an object stored in that binding.

const settings =  ;

settings.theme = "dark"; // Allowed

// settings = ; // TypeError if executed

In new code, use const when a binding will not be reassigned and let when reassignment is required. Understanding var remains important when reading older JavaScript.

7. What is the difference between == and === in JavaScript?

== uses abstract equality comparison and can convert values before comparing them. === uses strict equality without converting values between types.

5 == "5";       // true
5 === "5";      // false

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

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

Strict equality is generally the clearer default. The behaviour of == is defined by the language and is useful to understand when analysing legacy code or deliberate nullish comparisons.

8. What is type coercion in JavaScript?

Type coercion occurs when JavaScript converts a value to another type during an operation. The conversion may be implicit or requested explicitly by the programmer.

"5" + 2;       // "52"
"5" - 2;       // 3
true + 1;      // 2

Number("5");   // 5
String(10);    // "10"

The addition operator can concatenate strings, whereas subtraction performs numeric conversion. This distinction explains why similar-looking expressions may produce different types of results.

9. What is NaN in JavaScript?

NaN stands for Not-a-Number. It is a special numeric value used for certain invalid or unrepresentable numeric results.

Number("abc");       // NaN
typeof NaN;          // "number"
NaN === NaN;         // false

Number.isNaN(NaN);   // true
Number.isNaN("abc"); // false

A particularly important detail is that NaN is not equal to itself under strict equality. Number.isNaN() checks whether a value is actually the numeric NaN value without first coercing it.

10. What is the difference between null and undefined?

undefined commonly appears when a variable has not been assigned a value, an object property is missing or a function returns without specifying a value. null is typically assigned deliberately to indicate the absence of a value.

let result;

console.log(result); // undefined

const user =  ;

console.log(user.manager); // null
console.log(user.phone);   // undefined

typeof null; // "object"

The typeof null result is a longstanding language behaviour. Despite returning "object", null is a primitive value.

11. What is hoisting in JavaScript?

Hoisting is an informal term for the way declarations are processed when JavaScript prepares an execution context. Declarations are not literally moved within the source file.

sayHello(); // "Hello"

function sayHello()  

console.log(count); // undefined
var count = 5;

Function declarations are available before their position in the source in ordinary cases. A var binding exists before its declaration executes and initially has the value undefined. Accessing a let or const binding before its declaration is evaluated instead causes a ReferenceError.

12. What is the Temporal Dead Zone in JavaScript?

The Temporal Dead Zone (TDZ) is the period during which a lexical binding exists but has not yet been initialised. Reading a let or const binding during that period throws a ReferenceError.

 

The TDZ also applies to class declarations. It helps prevent accidental use of lexical bindings before their initialisation.

13. What is scope in JavaScript?

Scope determines where a binding can be accessed in a program. JavaScript has global, function, block and module scopes.

function example()  

  // console.log(blockValue); // ReferenceError
}

The var binding belongs to the function, while blockValue belongs to the if block. Top-level declarations in an ES module have module scope rather than automatically becoming properties of the global object.

14. What is lexical scope?

Lexical scope means variable access is determined by where a function is defined, not by where another function later calls it.

const message = "outer";

function readMessage()  

function run()  

run(); // "outer"

readMessage() resolves message from the scope in which it was defined. The local variable inside run() does not change that relationship.

15. What is a closure in JavaScript?

A closure is a function together with access to its surrounding lexical environment. That access can remain available after the outer function has returned.

function createCounter()  ;
}

const counter = createCounter();

console.log(counter()); // 1
console.log(counter()); // 2

Each call to createCounter() creates its own count binding. The returned function continues to access that binding across calls. Closures are used in callbacks, function factories and stateful logic.

16. What is an IIFE in JavaScript?

An Immediately Invoked Function Expression (IIFE) is a function expression executed as soon as it is evaluated.

(function ()  )();

IIFEs were widely used to keep variables out of the surrounding scope before block-scoped declarations and ES modules became standard practice. They remain useful when reading older code or when an expression needs an isolated function scope.

17. What are the different types of functions in JavaScript?

JavaScript supports function declarations, function expressions, arrow functions, methods, generators and async functions. They differ in syntax and in behaviour such as this binding, construction and asynchronous results.

// Function declaration
function add(a, b)  

// Function expression
const subtract = function (a, b)  ;

// Arrow function
const multiply = (a, b) => a * b;

// Async function
async function getValue()  

Functions are first-class values: they can be stored in variables, passed to other functions and returned as results. An async function returns a Promise, even when its body returns an ordinary value.

18. What is a higher-order function?

A higher-order function accepts a function as an argument, returns a function, or both. Array methods such as map(), filter() and reduce() are common examples of methods that receive callback functions.

const prices = [100, 200, 300];

const discounted = prices.map(
  price => price * 0.9
);

console.log(discounted);
// [90, 180, 270]

Here, map() receives a function and calls it for each array element, returning a new array of results.

19. What is a callback function?

A callback is a function supplied to another function for later invocation or for use during that function’s execution. Callbacks are not necessarily asynchronous.

function calculate(a, b, operation)  

const result = calculate(
  4,
  5,
  (a, b) => a + b
);

console.log(result); // 9

The callback runs synchronously in this example. Event listeners, timers and some I/O APIs also use callbacks, but their timing is determined by the particular API.

20. How are arrow functions different from regular functions?

Arrow functions have concise syntax and capture this from the surrounding lexical scope. Regular functions can receive different this values depending on how they are called.

const user =  ,

  arrow: () => this.name
};

console.log(user.regular()); // "Aman"

The arrow property does not bind this to user. Its result depends on the surrounding this, which differs between environments and execution contexts.

BehaviourRegular FunctionArrow Function
thisDetermined by the invocation and function contextInherited lexically
Own arguments bindingAvailable in ordinary non-arrow functionsNot created
Use with newPossible for constructible regular functionsNot allowed
Use as an object methodSuitable when dynamic this is requiredSuitable when lexical this is intended

Arrow functions also cannot be generator functions. They are useful for callbacks and short expressions, but regular methods remain appropriate when code needs the receiving object’s this.

JavaScript Objects, Prototypes and Arrays Interview Questions

Questions 21–50 cover how JavaScript stores and accesses object properties, shares behaviour through prototypes and works with arrays and collections. Several questions involve predicting what happens when two variables reference the same object or when a method is called with a different this value.

21. What is an object in JavaScript?

An object is a collection of properties identified by string or Symbol keys. A property can contain a primitive value, another object or a function. When a function is accessed as an object’s property, it is commonly called a method.

const employee =   works in $ `;
  }
};

console.log(employee.name); // "Aman"
console.log(employee.introduce());
// "Aman works in Engineering"

Objects are used for application data, configuration, API responses and instances with associated behaviour. Most ordinary objects also inherit properties through a prototype chain.

22. What are the different ways to create objects in JavaScript?

Object literals are the most common choice. Constructor functions, classes and Object.create() provide alternatives when object creation requires a particular prototype or reusable behaviour.

// Object literal
const first =  ;

// Object.create()
const second = Object.create(null);
second.name = "Riya";

// Constructor function
function Employee(name)  

const third = new Employee("Neha");

// Class
class User  
}

const fourth = new User("Rahul");

Object.create(null) creates an object with a null prototype, so it does not inherit ordinary Object.prototype methods. Classes and constructor functions normally create instances connected to their respective prototypes.

23. What is a prototype in JavaScript?

A prototype is an object that another object can inherit properties from. Each ordinary JavaScript object has an internal [[Prototype]] link, which can also be null.

const animal =  ;

const dog = Object.create(animal);

console.log(dog.eats); // true
console.log(Object.getPrototypeOf(dog) === animal);
// true

The property eats is not stored directly on dog. JavaScript finds it on animal, which is dog‘s prototype.

24. What is prototype chaining?

Prototype chaining is the process of looking for a property on an object and then, if necessary, following its prototype links. The search ends when the property is found or the chain reaches null.

const vehicle =  ;

const car = Object.create(vehicle);
car.wheels = 4;

const taxi = Object.create(car);

console.log(taxi.wheels); // 4
console.log(taxi.moves);  // true
console.log(taxi.color);  // undefined

Here, wheels comes from car, while moves comes from vehicle. A property on the object itself takes precedence over a property with the same name further up the chain.

25. What is the difference between __proto__ and prototype?

prototype is a property of constructible functions that normally determines the prototype of instances created with new. __proto__ is a legacy accessor inherited from Object.prototype that exposes or changes an object’s internal prototype in applicable cases.

function Person(name)  

const person = new Person("Aman");

console.log(
  Object.getPrototypeOf(person) === Person.prototype
); // true

Prefer Object.getPrototypeOf() when inspecting prototypes. Changing an object’s prototype at runtime is generally best avoided because it can complicate program behaviour and optimisation.

26. How does inheritance work in JavaScript?

JavaScript uses prototype-based inheritance. An object can access methods inherited through its prototype chain. The extends keyword provides class syntax for establishing an inheritance relationship.

class Employee  

  introduce()  `;
  }
}

class Developer extends Employee  
}

const developer = new Developer("Riya");

console.log(developer.introduce());
// "I am Riya"

console.log(developer.writeCode());
// "Writing JavaScript"

Developer inherits the instance method introduce() through the class prototype relationship. JavaScript classes provide familiar syntax, but they do not replace the language’s underlying prototype model.

27. What does the new keyword do in JavaScript?

When used with a constructible function, new creates an instance, connects it to the constructor’s prototype, invokes the constructor with the new instance as this and returns the appropriate result.

function Product(name, price)  

const laptop = new Product("Laptop", 50000);

console.log(laptop.name); // "Laptop"
console.log(laptop instanceof Product); // true

If an ordinary constructor explicitly returns an object, that object can become the result of new. If it returns a primitive, the created instance is generally returned instead. Arrow functions cannot be called with new.

28. What is the this keyword in JavaScript?

this refers to a value determined by the function’s invocation and execution context. For an ordinary method call, it typically refers to the object through which the method was called.

const employee =  
};

console.log(employee.getName()); // "Aman"

const detached = employee.getName;

// In strict mode:
// detached(); // TypeError

The detached function is no longer invoked as a method of employee. In strict mode, its this value is undefined, so trying to read this.name throws a TypeError. Arrow functions behave differently because they inherit this lexically.

29. What is the difference between call(), apply() and bind()?

MethodWhat It DoesArguments
call()Invokes the function immediatelyPassed separately
apply()Invokes the function immediatelyPassed as an array or array-like object
bind()Returns a new bound function for later invocationCan preset individual arguments
function greet(greeting, punctuation)  , $ $ `;
}

const employee =  ;

greet.call(employee, "Hello", "!");
// "Hello, Aman!"

greet.apply(employee, ["Hi", "."]);
// "Hi, Aman."

const boundGreet = greet.bind(employee, "Welcome");

console.log(boundGreet("!"));
// "Welcome, Aman!"

These methods are useful when a function needs an explicit receiver. They cannot replace the lexical this of an arrow function.

30. What is a factory function?

A factory function creates and returns an object without requiring the caller to use new. It can produce objects with methods, configurable properties or private state captured through closures.

function createEmployee(name, department)   works in $ `;
    }
  };
}

const employee = createEmployee("Neha", "Finance");

console.log(employee.describe());
// "Neha works in Finance"

Factory functions are useful when object creation does not need a class hierarchy or constructor-based instance checks.

31. What is a constructor function?

A constructor function is a function intended to initialise objects created with new. Shared methods can be placed on the function’s prototype rather than recreated inside every instance.

function Employee(name)  

Employee.prototype.greet = function ()  `;
};

const first = new Employee("Aman");
const second = new Employee("Riya");

console.log(first.greet()); // "Hello, Aman"

console.log(first.greet === second.greet);
// true

Both instances share the same greet function through the prototype. Constructor functions remain important for understanding older JavaScript code and class internals.

32. What is the difference between Object.freeze() and Object.seal()?

BehaviourObject.freeze()Object.seal()
Add new propertiesNot allowedNot allowed
Delete existing propertiesNot allowedNot allowed
Change existing writable data valuesNot allowedAllowed
Change property configurationRestrictedRestricted
Automatically affect nested objectsNoNo
const sealed = Object.seal( );
sealed.score = 20;

console.log(sealed.score); // 20

const frozen = Object.freeze( 
});

frozen.profile.score = 20;

console.log(frozen.profile.score); // 20

Both operations are shallow. Freezing the outer object does not freeze a nested object. Also, Object.freeze() does not disable the execution of existing accessor setters merely because the object is frozen.

33. What is the difference between a shallow copy and a deep copy?

A shallow copy creates a new outer object but retains references to the same nested objects. A deep copy duplicates supported nested structures so changes to the copied nested data do not affect the original.

const original =  
};

const shallow =  ;

shallow.employee.name = "Riya";

console.log(original.employee.name);
// "Riya"

Object spread and Object.assign() copy property values at the top level. Neither recursively duplicates nested objects. Deep-copy methods have their own limitations, particularly for functions, custom prototypes and specialised data types.

34. What is structuredClone() in JavaScript?

structuredClone() creates a deep clone of values supported by the structured clone algorithm. It handles many built-in structures, including arrays, plain objects, Maps, Sets and Dates.

const original =  ,
  joined: new Date("2025-01-15")
};

const copied = structuredClone(original);

copied.employee.name = "Neha";

console.log(original.employee.name);
// "Aman"

console.log(copied.joined instanceof Date);
// true

It cannot clone functions and does not preserve every property descriptor or custom prototype relationship. For application-specific class instances, it may be necessary to implement a different copying strategy.

35. What is an array in JavaScript?

An array is an ordered, zero-indexed collection whose length and contents can change during execution. JavaScript arrays can store values of different types and may contain empty slots.

const values = [10, "hello", true];

console.log(values[0]); // 10
console.log(values.length); // 3

values.push(25);

console.log(values.length); // 4

console.log(typeof values); // "object"
console.log(Array.isArray(values)); // true

Arrays are specialised objects. Use Array.isArray() rather than typeof when checking whether a value is an array.

36. What is the difference between map(), filter() and reduce()?

MethodPrimary PurposeReturn Value
map()Transform array elementsA new array of callback results
filter()Select elements matching a conditionA new array of matching elements
reduce()Accumulate values through a callbackThe final accumulator, which can be any value type
const numbers = [1, 2, 3, 4];

const doubled = numbers.map(n => n * 2);
// [2, 4, 6, 8]

const even = numbers.filter(n => n % 2 === 0);
// [2, 4]

const total = numbers.reduce(
  (sum, n) => sum + n,
  0
);
// 10

These methods do not inherently mutate the original array, although callback code can modify referenced objects or other state. Supplying an initial accumulator to reduce() is especially useful when the input array may be empty.

37. What is the difference between map() and forEach()?

map() returns a new array containing the callback results. forEach() invokes a callback for each visited element and returns undefined.

const numbers = [1, 2, 3];

const doubled = numbers.map(n => n * 2);

const logged = numbers.forEach(n =>  );

console.log(doubled); // [2, 4, 6]
console.log(logged);  // undefined

Use map() when the returned array is needed. Use forEach() for actions such as logging or updating external state. Neither method waits for asynchronous callbacks to finish simply because the callback is declared async.

38. What is the difference between slice() and splice()?

slice() returns a portion of an array without changing the original array. splice() changes the array by removing, inserting or replacing elements and returns an array of removed elements.

const first = [10, 20, 30, 40];

const selected = first.slice(1, 3);

console.log(selected); // [20, 30]
console.log(first); // [10, 20, 30, 40]

const second = [10, 20, 30, 40];

const removed = second.splice(1, 2);

console.log(removed); // [20, 30]
console.log(second);  // [10, 40]

Both use a starting index, but the second argument has a different meaning: slice(start, end) uses an exclusive end index, while splice(start, deleteCount) specifies how many elements to remove.

39. What is destructuring in JavaScript?

Destructuring extracts values from arrays or properties from objects using a compact assignment pattern. It also supports defaults, renamed variables and nested patterns.

const employee =  ;

const   = employee;

console.log(name);     // "Aman"
console.log(jobTitle); // "Developer"

const scores = [80, 90, 95];

const [first, second] = scores;

console.log(first);  // 80
console.log(second); // 90

Object destructuring matches property names rather than property order. Array destructuring reads values through the iterable protocol, usually in sequence.

40. What is the difference between spread and rest syntax?

Both use ..., but spread expands a value into another expression, while rest collects remaining values into a new array or object, depending on context.

// Spread
const first = [1, 2];
const combined = [...first, 3, 4];

console.log(combined); // [1, 2, 3, 4]

// Rest parameter
function addAll(...numbers)  

console.log(addAll(2, 3, 5)); // 10

// Object rest
const user =  ;

const   = user;

console.log(remaining); //  

Spread can be used in function calls, array literals and object literals. Rest syntax appears in function parameters and destructuring patterns. Object spread and object rest perform shallow operations.

41. What is a Set in JavaScript?

A Set stores unique values and preserves insertion order during iteration. Duplicate values are identified using SameValueZero comparison, under which NaN is treated as equal to NaN.

const values = new Set([1, 2, 2, 3, NaN, NaN]);

console.log([...values]);
// [1, 2, 3, NaN]

console.log(values.has(2)); // true
console.log(values.size);   // 4

Sets are useful for membership checks and removing duplicates from arrays of primitive values. Two distinct objects with identical properties remain different Set entries because their references differ.

42. What is a Map in JavaScript?

A Map stores key-value pairs in insertion order. Unlike ordinary object property keys, Map keys can be values of any JavaScript type, including object references.

const employee =  ;

const permissions = new Map();

permissions.set(employee, "admin");
permissions.set("guest", "read-only");

console.log(permissions.get(employee));
// "admin"

console.log(permissions.size); // 2

Map is useful when keys are dynamic, when non-string keys matter or when the collection needs direct iteration and a size property.

43. What is the difference between Map and Object?

FeatureMapObject
Key typesAny JavaScript valueString and Symbol property keys
Entry countsizeCan use Object.keys() or related methods
IterationDirectly iterableUsually requires an extraction method
Prototype inheritanceCollection entries are separate from ordinary object propertiesObjects can inherit properties through prototypes
Typical useDynamic key-value collectionStructured records and objects with behaviour

A Map is not automatically faster for every operation. Choose based on the data model, expected access patterns and the need for arbitrary key types.

44. What are WeakMap and WeakSet?

WeakMap stores key-value associations without keeping eligible keys alive solely because they appear in the collection. WeakSet stores eligible values weakly. Modern JavaScript permits objects and non-registered Symbols as WeakMap keys and WeakSet values.

const metadata = new WeakMap();

let employee =  ;

metadata.set(employee,  );

console.log(metadata.get(employee));
//  

employee = null;

After the reference is removed, the object may become eligible for garbage collection if no other strong references remain. WeakMap and WeakSet do not expose ordinary collection iteration or a size property because their contents depend on garbage collection.

45. What is optional chaining in JavaScript?

The optional chaining operator ?. stops a property access, element access or optional call when the value on its left is null or undefined, returning undefined rather than throwing for that access.

const employee =  
};

console.log(employee.profile?.name);
// "Aman"

console.log(employee.contact?.email);
// undefined

Optional chaining does not hide every programming error. For example, calling a property that exists but is not a function can still throw a TypeError, even when optional-call syntax is used.

46. What is nullish coalescing?

The nullish coalescing operator ?? returns the right-hand operand only when the left-hand value is null or undefined. Unlike ||, it preserves values such as 0, false and an empty string.

const count = 0;
const title = "";

console.log(count ?? 10); // 0
console.log(count || 10); // 10

console.log(title ?? "Untitled"); // ""
console.log(title || "Untitled"); // "Untitled"

Use ?? when a fallback should apply only to missing or nullish values. Use || when other falsy values should also trigger the fallback.

47. What are template literals?

Template literals are strings written with backticks. They support interpolation through $ and can span multiple lines without manually inserting newline escape sequences.

const name = "Aman";
const score = 85;

const message = `$  scored $  marks`;

console.log(message);
// "Aman scored 85 marks"

Expressions inside $ are evaluated when the template literal runs. Template literals are useful for readable string construction, but interpolation alone does not make inserted content safe for HTML rendering.

48. What are tagged template literals?

A tagged template passes a template literal’s string segments and interpolated values to a function. The function decides how to process them and what value to return.

function emphasise(strings, value)  $ $ `;
}

const name = "aman";

const result = emphasise`Hello, $ !`;

console.log(result);
// "Hello, AMAN!"

The first argument is an array-like collection of string segments, followed by the interpolation values. Tagged templates are used in formatting, internationalisation and libraries that process embedded expressions. Security-related uses still require correct escaping for the target context.

49. What is a Symbol in JavaScript?

A Symbol is a primitive type whose values can be used as unique property keys. Every call to Symbol() creates a new unique Symbol, even when two calls use the same description.

const first = Symbol("id");
const second = Symbol("id");

console.log(first === second); // false

const employee =  ;

console.log(employee[first]); // 101

Symbol.for() behaves differently: it accesses a shared Symbol registry, allowing calls with the same registry key to obtain the same Symbol. Symbols are useful for avoiding property-name collisions and for implementing language protocols such as Symbol.iterator.

50. What are private fields in JavaScript classes?

Private class fields use names beginning with #. They can be accessed only from code within the class body that declares them, including its methods.

class BankAccount  

    this.#balance += amount;
  }

  getBalance()  
}

const account = new BankAccount();

account.deposit(500);

console.log(account.getBalance()); // 500

// account.#balance; // SyntaxError

Private fields are enforced by JavaScript rather than by naming convention. They are different from an ordinary property named _balance, which remains externally accessible. Private members are also not accessible directly through subclass bodies merely because the subclass extends the declaring class.

Asynchronous JavaScript Interview Questions

Questions 51–70 deal with execution order and asynchronous operations. Interviewers may ask why a Promise callback runs before a timer, what happens when one request fails, or whether await blocks JavaScript execution. The examples below use browser-compatible JavaScript unless stated otherwise.

51. What is asynchronous programming in JavaScript?

Asynchronous programming allows an operation to be initiated without forcing the rest of the program to wait for its result. JavaScript can continue processing other work while the host environment handles operations such as network requests or timers.

console.log("First");

setTimeout(() =>  , 1000);

console.log("Second");

// First
// Second
// Third

The timer schedules a callback rather than stopping execution for one second. The callback becomes eligible to run after its delay, subject to the runtime’s scheduling and any work already in progress.

52. What is the JavaScript call stack?

The call stack records active function calls. Each function invocation adds an execution context to the stack. When that call finishes, its context is removed and execution returns to the caller.

function calculateTotal()  

function addTax(amount)  

console.log(calculateTotal()); // 118

calculateTotal() calls addTax(), so the second function runs before the first returns. Excessive synchronous recursion can exhaust the available call stack and cause an error.

53. How does the JavaScript event loop work?

The event loop is part of the host environment’s execution model. In browsers, it coordinates tasks, microtasks and rendering opportunities while JavaScript runs on an associated execution thread.

When a task runs, its JavaScript executes until it finishes or otherwise yields according to the applicable execution mechanism. At a microtask checkpoint, pending microtasks are processed before the event loop proceeds to another task. Browser rendering may occur at appropriate points between tasks.

A busy synchronous function can therefore delay timer callbacks, user interactions and rendering. The event loop does not make CPU-intensive synchronous JavaScript run in parallel on the same thread.

Reference: MDN explains the execution model in its JavaScript execution model documentation.

54. What are Web APIs, and how do they support asynchronous JavaScript?

Web APIs are browser-provided interfaces that JavaScript can use to work with browser features. They include the DOM, Fetch API, timers, storage APIs and Web Workers. These interfaces are separate from the ECMAScript language specification.

For example, setTimeout() is supplied by the host environment. JavaScript calls it to request timer scheduling; the callback is subsequently handled according to the environment’s event-loop rules.

const timerId = setTimeout(() =>  , 500);

clearTimeout(timerId);

In this example, clearTimeout() cancels the pending timer before its callback executes, assuming the callback has not already begun. Node.js provides its own host APIs and scheduling mechanisms, so browser-specific event-loop explanations should not automatically be applied to Node.js.

55. What is the difference between a task and a microtask?

In a browser, timer callbacks are examples of work scheduled as tasks. Promise reactions and callbacks passed to queueMicrotask() are scheduled as microtasks.

FeatureTaskMicrotask
Typical examplesTimer callbacks and certain event-dispatch workPromise reactions and queueMicrotask()
SchedulingProcessed through the event loop’s task schedulingProcessed at microtask checkpoints
Execution orderA later task waits until the current task and its relevant microtasks finishPending microtasks are drained before the next task begins
Potential problemLong tasks can delay responsivenessContinually adding microtasks can delay subsequent tasks and rendering

A Promise callback does not interrupt the synchronous code currently running. It executes at a microtask checkpoint, after the current execution has completed.

56. What is the output of this event-loop code?

console.log("A");

setTimeout(() =>  , 0);

Promise.resolve().then(() =>  );

console.log("D");

Output:

A
D
C
B

A and D print synchronously. The resolved Promise schedules a reaction as a microtask, so C prints after the synchronous statements. The timer callback runs as a subsequent task and prints B.

A zero-millisecond timer delay does not mean immediate execution. It requests scheduling with a minimum delay subject to browser rules and the state of the event loop.

57. What is a Promise in JavaScript?

A Promise represents the eventual result of an operation. Its state is initially pending and can become fulfilled with a value or rejected with a reason. Once settled, a Promise cannot change to another state.

const result = new Promise((resolve) =>  );

result.then(value =>  );

The function passed to the Promise constructor runs synchronously when the Promise is created. However, callbacks registered through then() run asynchronously as Promise reactions, even when the Promise is already fulfilled.

58. What is Promise chaining?

Promise chaining connects operations using then(). Each call to then() returns a new Promise. If its callback returns another Promise, the next link waits for that Promise to settle.

Promise.resolve(5)
  .then(value => value * 2)
  .then(value => value + 3)
  .then(result =>  )
  .catch(error =>  );

Returning the result from a then() callback is important. If a callback starts an asynchronous operation but does not return its Promise, subsequent links may proceed without waiting for it.

59. What is the difference between then(), catch() and finally()?

MethodBehaviour
then()Registers fulfilment handling and optionally rejection handling
catch()Registers rejection handling for a Promise chain
finally()Registers a callback that runs after settlement, regardless of fulfilment or rejection
Promise.resolve("Saved")
  .then(value =>  )
  .catch(error =>  )
  .finally(() =>  );

// Saved
// Finished

finally() does not receive the Promise’s fulfilment value or rejection reason as an argument. It normally preserves the previous outcome, but a thrown error or rejected Promise returned from its callback can replace that outcome.

60. What is async/await in JavaScript?

async declares a function that returns a Promise. Inside an async function, await suspends that function’s execution until the awaited value is resolved or rejected, then resumes execution through the Promise mechanism.

async function calculate()  

calculate().then(result =>  );

await does not block the entire JavaScript thread while waiting for a Promise. Other scheduled work can run after the current synchronous execution completes. An async function returns a Promise even when its return expression is an ordinary value.

61. What is the difference between Promises and async/await?

async/await is syntax built on Promises, not a separate asynchronous execution system. Both handle the same underlying Promise behaviour, but the control flow is expressed differently.

// Promise chain
function getTotal()  

// async/await
async function getTotalAsync()  

Both functions return Promises that fulfil with 120. Promise chains can be convenient for composition, while async/await often reads more naturally when later operations depend on earlier results.

There is also a performance consideration in how code is structured: sequentially awaiting independent operations can increase total waiting time. Where appropriate, independent Promises can be started together and awaited using Promise.all().

62. How do you handle errors with async/await?

Use try...catch to handle exceptions or rejected Promises inside an async function. A rejected Promise encountered through await causes an exception at that point in the function.

async function loadUser()  `);
    }

    return await response.json();
  } catch (error)  
}

The explicit response.ok check matters because fetch() normally fulfils when an HTTP response arrives, including responses with status codes such as 404 or 500. It rejects for failures such as certain network errors.

The catch block above logs and rethrows the error, allowing the caller to handle it. Returning a fallback value instead would cause the async function to fulfil unless another error occurred.

63. What is Promise.all(), and when should you use it?

Promise.all() returns a Promise that fulfils when every input fulfils. The result is an array in input order, regardless of which individual Promise finishes first. If an input rejects, the combined Promise rejects with that reason.

async function loadDashboard()  ;
}

The two fetch operations are independent, so starting them together avoids waiting for the first response before initiating the second. In production code, each response should also be checked for unsuccessful HTTP statuses where needed.

Interview detail: Rejection of the combined Promise does not automatically cancel the other operations. They may continue running unless cancellation is implemented separately.

64. What is Promise.allSettled()?

Promise.allSettled() waits until all input Promises settle and returns a result object for each one. Each result has a status of "fulfilled" or "rejected", along with a value or reason.

const results = await Promise.allSettled([
  Promise.resolve("Profile loaded"),
  Promise.reject(new Error("Orders unavailable"))
]);

console.log(results[0].status); // "fulfilled"
console.log(results[0].value);  // "Profile loaded"

console.log(results[1].status); // "rejected"
console.log(results[1].reason.message);
// "Orders unavailable"

Choose allSettled() when failures must be reported individually, such as a dashboard loading several independent sections. Unlike Promise.all(), one rejection does not cause the overall operation to reject immediately.

65. What is Promise.race()?

Promise.race() returns a Promise that settles according to the first input to settle. That input may fulfil or reject.

const fast = new Promise(resolve =>  );

const slow = new Promise(resolve =>  );

Promise.race([fast, slow]).then(result =>  );

In an ordinarily running environment, the shorter timer settles first. The example relies on relative timer scheduling and should not be interpreted as an exact timing guarantee.

Important distinction: Promise.race() does not cancel losing Promises. A timeout implemented with race() may stop waiting for a request while the underlying request continues. Use an applicable cancellation mechanism, such as AbortController with Fetch, when actual cancellation is required.

66. How is Promise.any() different from Promise.race()?

Promise.any() fulfils with the first fulfilled input, ignoring individual rejections unless every input rejects. Promise.race() settles as soon as any input settles, even if that first outcome is a rejection.

const first = Promise.reject("Server A failed");
const second = Promise.resolve("Server B responded");

Promise.any([first, second]).then(result =>  );

If every input rejects, Promise.any() rejects with an AggregateError containing the rejection reasons. An empty iterable also causes Promise.any() to reject, whereas Promise.race([]) remains pending.

67. What is callback hell, and how can it be avoided?

Callback hell describes deeply nested callback code in which control flow and error handling become difficult to follow. The underlying problem is the dependency structure and nesting, rather than callbacks themselves.

// Nested callback pattern
getUser(userId, user =>  );
  });
});

When equivalent Promise-returning functions are available, the sequence can be expressed with async/await:

async function createReport(userId)  

The second example assumes Promise-based versions of the functions. Adding await to a callback-only API does not automatically convert it into a Promise-based API. Breaking complex operations into named functions also improves readability regardless of the asynchronous mechanism used.

68. What does queueMicrotask() do?

queueMicrotask() schedules a callback to run at a microtask checkpoint after the current synchronous execution finishes. It is useful when code must defer an operation without scheduling a separate timer task.

console.log("Start");

queueMicrotask(() =>  );

console.log("End");

// Start
// End
// Microtask

Microtasks can schedule additional microtasks. If code continuously adds new microtasks without allowing the queue to drain, later tasks and browser rendering may be delayed.

Unlike a Promise reaction, an exception thrown directly from a queueMicrotask() callback is reported through the host’s ordinary exception-reporting mechanism rather than becoming a rejected Promise.

69. What is a generator function in JavaScript?

A generator function uses function* and can suspend execution at a yield expression. Calling the generator returns a generator object; its body begins executing when iteration advances.

function* generateNumbers()  

const iterator = generateNumbers();

console.log(iterator.next());
//  

console.log(iterator.next());
//  

console.log(iterator.next());
//  

The iterator’s next() method resumes execution until the next yield, return or completion. Generators support the iteration protocol and can produce values lazily without building an entire result array in advance.

70. What are async iterators and for await…of?

An async iterator delivers iteration results asynchronously. The for await...of statement consumes values from an async iterable, awaiting each iteration result before continuing.

async function* generateValues()  

async function readValues()  
}

readValues();

// 10
// 20

Async generators combine async function* with yield. They are suitable for asynchronous sequences, including streams and paginated data sources where later values may not be available immediately.

Interview distinction: A normal for...of loop consumes synchronous iterables. for await...of can consume asynchronous iterables and can also work with synchronous iterables, with the additional awaiting behaviour defined by the language.

DOM and Browser JavaScript Interview Questions

Browser-based interviews often move from JavaScript language rules to DOM events, network requests and storage. The distinction matters: document, localStorage and fetch() are provided by browser environments, not by the ECMAScript language itself. Questions 71–94 cover these APIs alongside modules and other language features.

71. What is the DOM in JavaScript?

The Document Object Model (DOM) represents an HTML or XML document as a tree of nodes. Browser APIs allow JavaScript to inspect that tree, change elements, update text and respond to events.

const heading = document.querySelector("h1");

if (heading)  

The code selects the first h1 element and replaces its text if the element exists. The null check prevents a property-access error when no matching element is found. DOM APIs are not automatically available in a standard Node.js environment.

72. What is the difference between getElementById() and querySelector()?

document.getElementById() looks up an element by its ID. document.querySelector() accepts a CSS selector and returns the first matching element, or null when no match is found.

const profile = document.getElementById("profile");

const card = document.querySelector(".profile-card");

const button = document.querySelector(
  "#profile button"
);

The ID passed to getElementById() is written without #. A CSS ID selector passed to querySelector() requires it. For multiple CSS-selector matches, use querySelectorAll(), which returns a static NodeList.

73. What is the difference between innerHTML, innerText and textContent?

PropertyBehaviourImportant Detail
innerHTMLReads or writes HTML markup inside an elementUnsafe handling of untrusted HTML can lead to injection vulnerabilities
innerTextRepresents rendered textIts result depends on rendering and styling
textContentReads or replaces text contentDoes not parse supplied text as HTML markup
const message = document.querySelector("#message");

if (message)  

For ordinary user-supplied text, textContent is generally safer because it does not interpret the value as HTML. If an application must render HTML from an untrusted source, it needs a suitable sanitisation strategy. Assigning arbitrary user input to innerHTML can introduce cross-site scripting vulnerabilities.

74. What is event bubbling in JavaScript?

Event bubbling is the phase in which a bubbling event travels from its target towards ancestor nodes. A click on a button nested inside a container can therefore invoke listeners attached to both the button and the container.

// HTML:
// <div id="parent">
//   <button id="child">Click</button>
// </div>

document.querySelector("#parent")
  .addEventListener("click", () =>  );

document.querySelector("#child")
  .addEventListener("click", () =>  );

// Clicking the button:
// Child
// Parent

The listeners above use the default non-capturing configuration. Not every DOM event bubbles, so event propagation behaviour should be checked for the particular event type.

75. What is event capturing?

During event capturing, an event travels through the relevant ancestors towards its target. A listener can be registered for this phase by passing to addEventListener().

const parent = document.querySelector("#parent");
const child = document.querySelector("#child");

parent.addEventListener("click", () =>  ,  );

child.addEventListener("click", () =>  );

// Clicking the child:
// Parent capture
// Child target

DOM event dispatch includes capturing, target and bubbling phases where applicable. The capture option controls when a listener participates; it does not change the event’s original target.

76. What is event delegation?

Event delegation uses a listener on a common ancestor to handle events from descendant elements. It avoids registering a separate listener on every item and is particularly useful when list entries are added dynamically.

const list = document.querySelector("#task-list");

list.addEventListener("click", event =>  

  const button = event.target.closest("button[data-id]");

  if (!button || !list.contains(button))  

  console.log(button.dataset.id);
});

The use of closest() handles clicks on elements nested inside a matching button. The containment check prevents an unintended match outside the delegated list. The approach depends on an event that propagates through the ancestor; it cannot be assumed to work identically for every event type.

77. What is the difference between event.target and event.currentTarget?

event.target identifies the event’s dispatch target. event.currentTarget identifies the object whose listener is currently executing.

const list = document.querySelector("#task-list");

list.addEventListener("click", event =>  );

When the user clicks a button inside #task-list, event.target may identify the button or an element inside it, while event.currentTarget is the list during that listener’s execution. This distinction is central to event delegation. In Shadow DOM, event retargeting can also affect what a listener observes as target.

78. What is the difference between preventDefault() and stopPropagation()?

event.preventDefault() requests cancellation of an event’s default action when the event is cancelable. event.stopPropagation() stops the event from proceeding further along its propagation path.

const form = document.querySelector("#contact-form");

form.addEventListener("submit", event =>  );

Preventing a form submission does not automatically stop the event from propagating to other listeners. Similarly, stopping propagation does not automatically cancel the browser’s default action. stopImmediatePropagation() additionally prevents other listeners for the same event on the same target from being invoked after the call.

79. What is debouncing in JavaScript?

Debouncing postpones a function call until a specified interval has passed without another triggering call. A typical use is an autocomplete input: rather than requesting suggestions for every keystroke, the application waits briefly after typing stops.

function debounce(fn, delay)  , delay);
  };
}

const search = debounce(query =>  , 300);

search("ja");
search("java");
search("javascript");

// After the delay, only "javascript" is logged.

This is a trailing-edge implementation: it invokes the latest call after the delay. Production implementations may also support leading-edge execution, cancellation, a maximum waiting time or forwarding return values.

80. What is throttling in JavaScript?

Throttling limits how frequently a function executes while events continue. It is commonly applied to scrolling, resizing and pointer-movement handlers where repeated updates are useful but executing on every event would be excessive.

function throttle(fn, interval)  
  };
}

const reportScroll = throttle(() =>  , 200);

window.addEventListener("scroll", reportScroll);

This implementation runs on the leading edge and discards calls received during the interval. It does not schedule a final trailing call. For visual updates tied to browser repainting, requestAnimationFrame() may be a more appropriate scheduling tool than a time-based throttle.

81. What is the difference between debouncing and throttling?

AspectDebouncingThrottling
Execution patternWaits for a quiet periodLimits execution frequency
When events continueA trailing-edge call keeps being postponedCalls can occur at controlled intervals
Typical exampleSearch suggestions after typing stopsPeriodic updates during scrolling
Implementation detailOften resets a timerOften tracks time or schedules pending execution

Neither technique is universally better. Choose debouncing when only the latest value after a burst matters. Choose throttling when intermediate updates are needed during sustained activity. Both techniques can have leading and trailing variants.

82. What is localStorage in JavaScript?

localStorage is a browser Web Storage interface for storing string key-value pairs associated with an origin. Stored values generally remain available across browsing sessions until they are cleared, subject to browser and privacy settings.

localStorage.setItem("theme", "dark");

const theme = localStorage.getItem("theme");

console.log(theme); // "dark"

localStorage.removeItem("theme");

Web Storage operations are synchronous, and storage access can fail in certain environments or privacy configurations. Avoid using localStorage as a default location for session credentials or other highly sensitive information. Scripts executing in the same origin can generally access its stored values.

83. What is sessionStorage in JavaScript?

sessionStorage stores string key-value pairs for an origin within a particular page session. It usually remains available during reloads in the same tab and is cleared when that tab’s page session ends.

sessionStorage.setItem("currentStep", "2");

console.log(sessionStorage.getItem("currentStep"));
// "2"

Unlike localStorage, sessionStorage is partitioned by both origin and top-level browsing context. Certain newly opened tabs may initially receive a copy of the opener’s session storage, after which the stores are separate. It should not be treated as an automatically secure place for authentication secrets.

84. What is the difference between cookies, localStorage and sessionStorage?

FeatureCookieslocalStoragesessionStorage
Typical useSession management and other HTTP-related statePersistent client-side preferencesTemporary state for a page session
PersistenceControlled by expiry and cookie attributesUsually persists across sessionsUsually ends with the page session
HTTP requestsEligible cookies may be sent automaticallyNot automatically sentNot automatically sent
JavaScript accessDepends on attributes such as HttpOnlyAvailable to permitted same-origin scriptsAvailable to permitted same-origin scripts in the relevant page session

A properly configured HttpOnly cookie is not accessible through document.cookie, although the browser can still send it with eligible requests. Cookie attributes such as Secure and SameSite influence transmission and cross-site behaviour. No storage mechanism removes the need for a sound application security design.

85. What is JSON?

JSON (JavaScript Object Notation) is a text-based format for exchanging structured data. It supports objects, arrays, strings, numbers, booleans and null. JSON does not support JavaScript functions, comments or undefined as ordinary JSON values.

 

The example is valid JSON. Property names must use double-quoted strings, and trailing commas are not allowed. JSON resembles JavaScript object-literal syntax but follows its own grammar and is used across many programming languages.

86. What is the difference between JSON.parse() and JSON.stringify()?

JSON.parse() converts valid JSON text into a JavaScript value. JSON.stringify() serialises supported JavaScript values into JSON text.

const text = ' ';

const employee = JSON.parse(text);

console.log(employee.name); // "Aman"

const result = JSON.stringify(employee);

console.log(result);
// ' '

JSON.parse() throws a SyntaxError when the input is invalid JSON. Serialization also has limitations: unsupported object-property values such as functions and undefined may be omitted, and serialising a BigInt without suitable custom handling throws a TypeError.

87. What is a Web Worker?

A Web Worker runs JavaScript in a separate worker execution context from the main browser page. Dedicated workers are useful for CPU-intensive processing that would otherwise occupy the main thread and delay interface updates.

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

worker.postMessage(10);

worker.addEventListener("message", event =>  );

// worker.js
self.addEventListener("message", event =>  );

// Main thread receives: 20

Workers communicate through message passing and cannot directly manipulate the page DOM. Worker code runs in a separate global context and is subject to applicable browser security and resource restrictions. Creating additional workers also consumes resources, so they should be used for appropriate workloads.

88. What is a Service Worker?

A Service Worker is an event-driven browser worker associated with a registered scope. It can intercept eligible network requests, coordinate caching and support features such as offline operation and push notifications where browser support and permissions permit.

if ("serviceWorker" in navigator)  )
    .catch(error =>  );
}

Service Workers have a distinct installation, activation and event-handling lifecycle. They generally require a secure context, such as HTTPS, with browser-specific exceptions for local development. A registered worker does not necessarily control the page immediately, and it cannot directly access the page DOM.

89. What is the difference between a Web Worker and a Service Worker?

FeatureDedicated Web WorkerService Worker
Main purposeRun appropriate work off the page’s main threadHandle scoped events, network interception and offline-related capabilities
CreationCreated through new Worker()Registered through navigator.serviceWorker.register()
LifetimeGenerally associated with its owning execution contextEvent-driven; may be stopped and restarted independently
CommunicationMessage passingEvents, messaging and browser-provided interfaces
Direct DOM accessNoNo

A Web Worker is a reasonable option for calculations such as data processing. A Service Worker is more suitable for request handling, caching and supported background web functionality. Neither should be confused with an unrestricted background process that runs continuously.

90. What are JavaScript modules?

JavaScript modules allow source files to expose selected values through export and use values from other modules through import. ES modules have their own scope and are evaluated under strict-mode semantics.

// math.js
export function add(a, b)  

// app.js
import   from "./math.js";

console.log(add(4, 6)); // 10

In a browser, module scripts can be loaded using <script type="module">. The module loader handles dependencies and module evaluation. Importing a module does not simply paste the source file into the importing file’s scope.

91. What is the difference between named exports and default exports?

A module can expose multiple named exports, each imported using its exported name or an explicit alias. A module can have only one default export, which the importing module may give a local name of its choice.

// helpers.js
export const version = "1.0";

export function formatName(name)  

export default function greet(name)  `;
}

// app.js
import greet,   from "./helpers.js";

console.log(greet(formatName(" Aman ")));
// "Hello, Aman"

console.log(version); // "1.0"

Default exports are not inherently faster or more important than named exports. The choice affects how an API is organised and imported, not the runtime priority of the exported value.

92. What is dynamic import in JavaScript?

The import() expression loads a module dynamically and returns a Promise for its module namespace object. It is useful when a feature is only needed after a particular user action or condition.

const button = document.querySelector("#open-editor");

button.addEventListener("click", async () =>   catch (error)  
});

Dynamic imports are frequently used with code splitting. Whether loading a module creates a separate downloadable bundle depends on the build tools and deployment setup. A failed module load rejects the returned Promise and should be handled where appropriate.

93. What is the global object in JavaScript?

The global object provides access to properties and functions available globally within the current JavaScript environment. The standard globalThis property offers a consistent way to refer to that global object.

console.log(globalThis.Math === Math);
// true

console.log(globalThis.JSON === JSON);
// true

In a browser window, window provides access to the window global environment. In Node.js, global is a traditional name for the global object. Top-level declarations in ES modules do not automatically create properties on the global object.

94. What is strict mode in JavaScript?

Strict mode changes certain JavaScript semantics to reject error-prone operations and make some previously silent failures throw exceptions. It can be enabled in scripts or individual functions with the "use strict" directive.

"use strict";

function calculate()  

calculate();

The assignment fails because total was not declared. In a non-strict classic script, assigning to an undeclared identifier can instead create a global property, subject to the surrounding environment.

ES modules and class bodies already follow strict-mode semantics. Strict mode also affects ordinary function this behaviour and certain property assignments, but it is not a replacement for linting, type checking or application security controls.

Technical references: The MDN DOM documentation explains document APIs and events, while the MDN JavaScript modules documentation covers module loading and exports.

Advanced JavaScript Interview Questions and Answers

Questions 95–103 deal with function behaviour and the JavaScript object model. These topics often appear in interviews where candidates are expected to explain why an implementation works, not simply reproduce its syntax.

95. What is currying in JavaScript?

Currying transforms a function that accepts multiple arguments into a series of functions, each taking one argument.

function multiply(a)  ;
}

const double = multiply(2);

console.log(double(5)); // 10
console.log(double(8)); // 16

The returned function retains access to a through a closure. Currying is useful when the same initial argument is reused across several operations. It differs from partial application, which fixes some arguments without necessarily changing a function into a sequence of single-argument functions.

96. What is function composition?

Function composition connects functions so the result of one becomes the input of another. It is commonly used to combine small transformations into a larger operation.

const double = value => value * 2;
const addFive = value => value + 5;

const calculate = value => addFive(double(value));

console.log(calculate(10)); // 25

The execution order matters: double(10) returns 20, then addFive(20) returns 25. Changing the order would produce a different answer.

97. What is a pure function?

A pure function produces the same result for the same inputs and has no observable side effects. It does not change external variables, mutate caller-owned objects or perform operations such as network requests.

function addTax(price, rate)  

console.log(addTax(100, 0.18)); // 118

The calculation depends only on its arguments. Pure functions are generally easier to test because their results do not depend on changing application state. A function that updates a global counter, for example, would not be pure.

98. What is memoization in JavaScript?

Memoization stores the results of previous function calls and reuses them when the same input occurs again. It is most useful for expensive calculations whose results are stable for a given input.

function memoizeSquare()  

    const result = number * number;
    cache.set(number, result);

    return result;
  };
}

const square = memoizeSquare();

console.log(square(6)); // 36
console.log(square(6)); // 36, retrieved from cache

The cache avoids recalculation, but it also retains stored entries. A production implementation needs a suitable cache-key strategy and may need size limits or expiry rules. Memoization is not automatically beneficial for inexpensive functions.

99. What is the difference between deep equality and reference equality?

With objects, === tests whether both operands refer to the same object. It does not compare their properties recursively. Deep equality compares the contents of nested structures according to a chosen set of rules.

const first =  ;
const second =  ;
const third = first;

console.log(first === second); // false
console.log(first === third);  // true

A deep-equality function could consider first and second equivalent, but the result depends on how it handles prototypes, property types, arrays, Maps, Sets and circular references. Converting objects to JSON strings is not a general-purpose deep-equality solution.

100. What are property descriptors in JavaScript?

JavaScript properties have attributes known as property descriptors. A data-property descriptor can specify value, writable, enumerable and configurable. Accessor properties instead use getter and setter functions.

const employee = ;

Object.defineProperty(employee, "id",  );

console.log(employee.id); // 101
console.log(Object.keys(employee)); // ["id"]

Here, the id property cannot be reassigned through an ordinary assignment or reconfigured. An attempted reassignment silently fails in non-strict code and throws a TypeError in strict mode.

101. What are getters and setters in JavaScript?

Getters run when an accessor property is read. Setters run when a value is assigned to that property. They allow an object to expose property syntax while controlling how values are calculated or stored.

const employee =   $ `;
  },

  set fullName(value)  
};

console.log(employee.fullName); // "Aman Shah"

employee.fullName = "Riya Mehta";

console.log(employee.firstName); // "Riya"

This setter assumes a two-part name and would need stronger validation for general use. Getters and setters can also be defined through Object.defineProperty() or inside classes.

102. What is a Proxy in JavaScript?

A Proxy allows certain operations on an object or function to be intercepted. A handler defines traps for operations such as reading properties, assigning values or checking whether a property exists.

const settings =  ;

const proxy = new Proxy(settings,  

    return Reflect.set(
      target,
      property,
      value,
      receiver
    );
  }
});

proxy.theme = "dark";

console.log(settings.theme); // "dark"

Proxies can implement validation, observation and other interception patterns. They must respect language invariants; for example, a trap cannot report arbitrary results that contradict certain non-configurable properties of its target.

103. What is the Reflect API?

Reflect provides static methods for operations involving objects, including property access, assignment, construction and deletion. Several methods correspond to operations that Proxy traps can intercept.

const employee =  ;

console.log(Reflect.get(employee, "name"));
// "Aman"

console.log(Reflect.set(employee, "role", "Developer"));
// true

console.log(employee.role);
// "Developer"

Reflect.set() returns a boolean indicating whether the assignment operation succeeded. Unlike the new operator, Reflect.construct() can also receive an explicit newTarget argument.

JavaScript Performance and Memory Interview Questions

Memory and performance questions are often scenario-based. An interviewer may describe a page that becomes slower after repeated navigation or a search field that sends too many requests. The strongest answer identifies a possible cause, explains how to measure it and proposes an appropriate fix.

104. How does memory management work in JavaScript?

JavaScript engines allocate memory for values and objects as needed. Garbage collection can reclaim memory occupied by objects that are no longer reachable from the program’s active references.

Developers generally do not free ordinary JavaScript objects manually. They are still responsible for avoiding unnecessary references, removing obsolete event listeners and stopping work that no longer serves a purpose. Browser resources such as media streams and network operations may also require explicit cleanup.

105. What is garbage collection in JavaScript?

Garbage collection is the process through which a JavaScript engine identifies memory that can be reclaimed. Modern engines use reachability-based techniques rather than simply counting how many variables point to an object.

let employee =  ;

employee = null;

After reassignment, the original object may become eligible for collection if nothing else references it. Setting a variable to null does not immediately force collection, and the precise collection time is not specified by JavaScript.

106. What is a memory leak in JavaScript?

A memory leak occurs when an application retains memory it no longer needs, often because unnecessary references keep objects reachable.

  • Event listeners retained after their associated interface has been removed.
  • Intervals or timers that continue running unnecessarily.
  • Caches that grow without a size or expiry policy.
  • Long-lived closures that retain large data structures.
  • References to detached DOM elements that are no longer needed.

A practical investigation involves reproducing the behaviour and examining memory allocation or heap snapshots using appropriate developer tools. Growing memory usage alone does not conclusively establish a leak because garbage collection and caching also affect memory measurements.

107. How can closures contribute to memory leaks?

A closure retains access to variables in its lexical environment. If the closure remains reachable, values it continues to reference may also remain in memory.

function createHandler()  ;
}

let handler = createHandler();

console.log(handler()); // 100000

handler = null;

The returned function needs largeData to calculate its result. Once the application no longer retains the handler or another reference to that environment, the associated data may become eligible for garbage collection. A closure is not inherently a memory leak; retaining it unnecessarily is the problem.

108. How can you improve JavaScript performance in a web application?

Begin by measuring the slow operation. Browser performance tools can help identify long-running JavaScript tasks, expensive rendering work, repeated layout calculations and avoidable network activity.

Observed ProblemPossible Response
Expensive synchronous calculationImprove the algorithm or move suitable work to a Web Worker
Repeated DOM updatesReduce unnecessary mutations and measure rendering costs
Too many requests while typingConsider debouncing and cancellation of stale requests
Large initial JavaScript bundleEvaluate code splitting and loading non-essential features later
Memory growth after navigationInvestigate retained listeners, timers, caches and references
Repeated expensive calculationConsider caching when results can safely be reused

Performance work involves trade-offs. A technique that improves one scenario may increase memory use, code complexity or network requests in another. Compare measurements before and after the change.

109. What is lazy loading in JavaScript applications?

Lazy loading delays loading a resource until it is needed. Applications often use it for features, routes, images or modules that are not required during initial rendering.

async function openReports()  

With an appropriate module-loading setup, the reports module can be loaded when openReports() runs. Lazy loading can reduce initial work but introduces a later loading step, so important user-facing features may benefit from preloading or other strategies.

110. What is code splitting?

Code splitting divides application code into separately loadable modules or chunks rather than delivering every feature in one initial bundle. Build tools commonly use dynamic import boundaries or application routes to determine which chunks can be loaded independently.

Code splitting is a packaging and loading strategy; lazy loading describes when resources are fetched or used. The two are often combined. Excessive splitting can also create overhead, so chunk sizes and loading behaviour should be measured.

JavaScript Coding and Output-Based Interview Questions

The following problems test array handling, string manipulation, closures and execution order. For implementation questions, clarify the expected input before writing code. For output questions, explain the sequence of operations rather than guessing from the final values.

111. How do you remove duplicate values from an array?

For an array of primitive values, converting it to a Set and spreading the result into a new array is a concise solution.

function removeDuplicates(values)  

console.log(removeDuplicates([1, 2, 2, 3, 3]));
// [1, 2, 3]

The result preserves the insertion order of the first occurrence of each value. Distinct objects are not merged merely because their properties match; removing duplicate objects requires an explicit criterion, such as an id.

112. How do you reverse a string in JavaScript?

function reverseString(text)  

console.log(reverseString("hello"));
// "olleh"

Spreading a string iterates over Unicode code points, avoiding some problems associated with splitting UTF-16 code units. It does not fully preserve every user-perceived character, such as multi-code-point emoji or letters combined with diacritics. For those cases, grapheme-aware segmentation may be necessary.

113. How do you check whether a string is a palindrome?

A palindrome reads the same forwards and backwards. Before implementing the check, establish whether the comparison should ignore spaces, punctuation and letter case.

function isPalindrome(text)  

console.log(isPalindrome("Race car")); // true
console.log(isPalindrome("JavaScript")); // false

This implementation intentionally supports ASCII letters and digits. It removes other characters, including non-English letters. A multilingual application would need different normalisation and Unicode-aware handling.

114. How do you flatten a nested array?

Array.prototype.flat() creates a new array with nested arrays flattened to the specified depth. Using Infinity requests flattening across all nested levels.

const values = [1, [2, [3, 4]]];

console.log(values.flat(1));
// [1, 2, [3, 4]]

console.log(values.flat(Infinity));
// [1, 2, 3, 4]

flat() does not modify the original array. It also removes empty slots from the levels it flattens. Interviewers may ask for a recursive implementation when they want to assess algorithm design rather than familiarity with the built-in method.

115. How do you count the frequency of values in an array?

A Map can track how often each value appears without converting all keys into strings.

function countValues(values)  

  return counts;
}

const result = countValues(["a", "b", "a"]);

console.log(result.get("a")); // 2
console.log(result.get("b")); // 1

This solution performs one pass through the input array. The Map uses SameValueZero key comparison, so two separate objects with identical properties still count as different keys.

116. What will typeof return for null, an array and a function?

console.log(typeof null);
console.log(typeof []);
console.log(typeof function () );

Output:

object
object
function

typeof null returning "object" is a historical language behaviour. Arrays are objects, while callable functions receive the special "function" result. Use Array.isArray() when specifically checking for arrays.

117. What will JavaScript output when operators trigger type coercion?

console.log(1 + "2");
console.log("5" - 2);
console.log(true + 1);

Output:

12
3
2

The first operation concatenates because one operand becomes a string. Subtraction requires numeric conversion, so "5" becomes 5. In the final expression, true converts to 1 for numeric addition.

118. What will this closure code output?

function createCounter()  

const first = createCounter();
const second = createCounter();

console.log(first());
console.log(first());
console.log(second());

Output:

1
2
1

Each call to createCounter() creates a separate lexical environment. Calling first() twice increments one counter; second() starts with its own counter at zero.

119. Why does a var loop with setTimeout() print the same value?

for (var i = 0; i < 3; i++)  , 0);
}

Output:

3
3
3

var creates one binding shared by the callbacks. The synchronous loop finishes before the timer callbacks execute, leaving i equal to 3.

for (let i = 0; i < 3; i++)  , 0);
}

// 0
// 1
// 2

With let, each iteration receives its own binding. The callbacks therefore retain their respective iteration values.

120. What will this Promise and timer code output?

console.log("start");

Promise.resolve().then(() =>  );

setTimeout(() =>  , 0);

console.log("end");

Output:

start
end
promise
timer

The synchronous statements run first. The Promise callback then runs as a microtask. The timer callback executes in a later task. This order is predictable for the browser-style example because the microtask checkpoint occurs before the next timer task.

Additional JavaScript Interview Questions for 2026

These five questions cover situations developers encounter while maintaining applications: cancelling requests, checking property ownership, handling asynchronous array operations, managing resources and distinguishing JavaScript language features from runtime APIs.

121. How do you cancel a fetch request using AbortController?

AbortController creates a signal that can be passed to compatible asynchronous APIs, including Fetch. Calling abort() requests cancellation of the associated operation.

const controller = new AbortController();

async function loadResults()  );

    if (!response.ok)  `);
    }

    return await response.json();
  } catch (error)  

    throw error;
  }
}

// Start the request.
const pendingRequest = loadResults();

// Request cancellation while it is pending.
controller.abort();

// Handle any errors not caused by cancellation.
pendingRequest.catch(console.error);

Cancellation can prevent an obsolete request from continuing to consume client-side resources, although it does not guarantee that server-side processing has stopped. In a search interface, an application may abort an earlier request when a new search begins.

122. What is the difference between the in operator and Object.hasOwn()?

The in operator checks whether a property exists on an object or anywhere along its prototype chain. Object.hasOwn() checks only the object’s own properties.

const base =  ;
const employee = Object.create(base);

employee.name = "Aman";

console.log("active" in employee); // true

console.log(Object.hasOwn(employee, "active"));
// false

console.log(Object.hasOwn(employee, "name"));
// true

This distinction matters when inspecting data objects that inherit properties. Object.hasOwn() also works with objects that do not inherit hasOwnProperty(), such as objects created with Object.create(null).

123. Why does using async callbacks with forEach() not wait for completion?

forEach() calls its callback for each visited element but does not await Promises returned by those callbacks. The method itself returns undefined.

const values = [1, 2, 3];

async function processValue(value)  

// Sequential processing
async function processSequentially()  
}

// Concurrently started processing
async function processTogether()  

Use for...of with await when each operation should finish before the next begins. Use Promise.all() when independent operations can run concurrently and the caller needs to await their completion. For large workloads, a concurrency limit may be more appropriate than starting every operation simultaneously.

124. What are resource management and the using declaration in modern JavaScript?

Explicit resource management introduces language constructs that allow suitable resources to be cleaned up automatically at the end of a scope. The using declaration works with disposable resources that implement the relevant disposal protocol.

// Requires an environment supporting explicit
// resource management.

 
  };

  console.log("Working");
}

// Working
// Resource released

Disposal takes place when the declared scope is exited. The related await using declaration supports asynchronous resource cleanup. Browser and runtime support for this syntax is not universal. Check compatibility before using it in production, and use suitable build tooling where supported. An environment that does not recognise using will fail to parse the example.

The principle is useful beyond the syntax: resources such as connections, file handles and subscriptions should be released when their work is complete. Ordinary garbage collection does not replace all forms of resource cleanup.

125. Is fetch() part of JavaScript or provided by the runtime?

fetch() is not defined by the ECMAScript language specification. It comes from web platform specifications and is implemented by supporting host environments, including modern browsers and Node.js releases.

async function getStatus(url)  ;
}

The language defines constructs such as Promises, objects and async/await. A runtime provides interfaces for network requests, files, timers and other external operations. This distinction helps explain why the same JavaScript syntax can run in browsers and Node.js even though their available APIs differ.

How to Prepare for a JavaScript Interview

A good preparation session includes three kinds of work: explaining a concept without notes, predicting the output of unfamiliar code and implementing a solution that handles realistic inputs. Reading a definition once is rarely enough to identify mistakes in an asynchronous function or an object-copying operation.

What to Practise for Different Experience Levels

Interview LevelTopics to PrioritiseUseful Practice
Fresher / Entry-levelTypes, variables, functions, arrays, equality, coercion, DOM basicsWrite short functions and explain the output of simple expressions
1–3 years’ experienceClosures, this, prototypes, array methods, event handling, PromisesDebug asynchronous code and solve data-transformation problems
Experienced frontend developerEvent loop, rendering, DOM performance, browser storage, security, modulesInvestigate a slow UI, event-handler bug or unnecessary network request
Backend / Node.js developerPromises, async iteration, error handling, resource management, memoryExplain API failures, concurrency limits and cleanup behaviour

These are preparation priorities, not fixed interview syllabuses. A frontend opening involving React or another framework will also require framework-specific work, while a backend position may involve databases, HTTP, testing and deployment.

How to Approach JavaScript Coding Questions

  1. Clarify the input: Ask whether the function receives strings, numbers, nested arrays or objects, and whether invalid inputs are possible.
  2. State the expected output: Explain what a successful result looks like before choosing an algorithm.
  3. Choose the data structure: Consider arrays, objects, Maps and Sets according to the operations required.
  4. Test boundary cases: Try empty inputs, duplicate values, missing properties and relevant Unicode cases.
  5. Explain complexity: Discuss time and memory use when it materially affects the solution.
  6. Review side effects: Check whether the code mutates an input, starts unawaited work or retains unnecessary references.

For output-based questions, trace synchronous execution first, then Promise reactions, timers and other scheduled callbacks according to the relevant runtime. For object questions, identify whether an operation changes an existing object or creates a new one.

Technical References for JavaScript Interview Preparation

The MDN JavaScript documentation provides explanations and runnable examples of language features. The ECMAScript specification defines the language’s normative behaviour, including type conversion, functions, objects and Promise operations.

For browser-specific questions, use the relevant MDN Web API references rather than assuming that browser behaviour is defined by ECMAScript. For Node.js interviews, check the applicable official Node.js learning documentation for runtime behaviour and supported APIs.

Final Interview Preparation Checklist

Before the interview, make sure you can explain closures and this, distinguish shallow copying from cloning, trace Promise and timer execution, and write array transformations without relying on memorised snippets. Run your examples and check their output, especially when errors, asynchronous operations or object references are involved.

For experienced positions, prepare to discuss a real bug or performance issue you investigated: what went wrong, how you isolated the cause and what changed after the fix. That explanation is often more informative than reciting definitions of advanced JavaScript features.

FAQs

Fresher interviews commonly cover data types, var, let, const, equality operators, hoisting, scope, functions, closures and basic array methods.

Experienced developers should understand closures, prototypes, this, Promises, the event loop, asynchronous error handling, browser APIs and performance debugging.

Yes. Interviews may include array transformations, string manipulation, duplicate removal, closures, Promise handling and output-prediction problems. Requirements vary by role.

ECMAScript is the language standard that defines JavaScript's core behaviour. Browsers and runtimes such as Node.js provide additional APIs.

Practise writing code without notes, predicting outputs, explaining edge cases and debugging mistakes. Prioritise the topics mentioned in the job description.

JavaScript fundamentals are essential, but frontend interviews may also assess HTML, CSS, DOM APIs, browser behaviour and frameworks such as React, depending on the position.

beware-of-scammers-icon Beware of Scammers

We don't charge money for job offers

Know More