96 JavaScript Interview Questions and Answers (2026)

Blog / 96 JavaScript Interview Questions and Answers (2026)
JavaScript interview questions and answers

JavaScript is the language of the web, and increasingly everything else. It runs every browser on earth, powers servers, tooling, and mobile apps, and remains one of the most in-demand skills in tech. Interviewers expect real fluency, not memorized trivia: walk in shaky on closures, the event loop, or prototypes and you will lose the offer to someone who is not.

This is 96 questions with concise, interview-ready answers and code where it helps. They're worked Junior to Mid to Senior, so you build from variables and hoisting up to engine internals and memory. Work through them and you'll walk in ready to ace it.

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

Junior

They differ in scope, hoisting behavior, and reassignment: var is function-scoped and legacy, while let and const are block-scoped with a Temporal Dead Zone.

  • Scope:

    • var is function-scoped (ignores block boundaries like if or for).

    • let and const are block-scoped ({ } limits them).

  • Hoisting:

    • var is hoisted and initialized to undefined.

    • let/const are hoisted but stay in the TDZ until declared.

  • Reassignment / redeclaration:

    • var can be redeclared and reassigned.

    • let can be reassigned but not redeclared in the same scope.

    • const cannot be reassigned (the binding is fixed, though object contents can still mutate).

  • Rule of thumb: default to const, use let when you must reassign, avoid var.

Q2.
Explain the difference between Global Scope, Function Scope, and Block Scope.

Junior

These are the three levels of variable visibility: global scope is accessible everywhere, function scope is limited to a function body, and block scope is limited to a { } block.

  • Global scope:

    • Declared outside any function/block; visible everywhere.

    • In browsers, var globals attach to window; let/const do not.

  • Function scope: Variables declared inside a function exist only within it; this applies to var, let, and const.

  • Block scope:

    • Created by any { } (if, for, bare blocks); only let and const respect it.

    • var ignores blocks and "leaks" to the enclosing function.

javascript

function demo() { if (true) { var a = 1; // function-scoped, leaks out let b = 2; // block-scoped } console.log(a); // 1 console.log(b); // ReferenceError }

Q3.
What is variable shadowing?

Junior

Variable shadowing happens when a variable declared in an inner scope has the same name as one in an outer scope, so the inner one "shadows" (temporarily hides) the outer variable within that scope.

  • Inner scope wins: References to the name inside the inner block resolve to the inner declaration, not the outer one.

  • The outer variable is untouched: Once the inner scope ends, the outer variable is visible again with its original value.

  • Scope rules differ by keyword:

    • let and const are block-scoped, so they can shadow inside any {} block.

    • Illegal shadowing: a let cannot be shadowed by a var in a nested block if it would conflict with the same binding.

  • Caution: shadowing can mask bugs and reduce readability, so reuse names deliberately.

javascript

let x = 1; { let x = 2; // shadows the outer x console.log(x); // 2 } console.log(x); // 1

Q4.
What is the difference between null and undefined? When would you intentionally use one over the other?

Junior

Both represent "no value," but undefined means a variable exists but hasn't been assigned, while null is an explicit, intentional "empty" you assign yourself.

  • undefined is the default absence:

    • Given automatically to uninitialized variables, missing function arguments, and missing object properties.

    • typeof undefined is "undefined".

  • null is a deliberate empty value:

    • You assign it to signal "intentionally nothing here."

    • typeof null is "object" (a long-standing bug).

  • Equality differences: null == undefined is true, but null === undefined is false.

  • When to use which:

    • Use null to explicitly clear or reset a value (e.g. user = null).

    • Let undefined occur naturally; rarely assign it manually.

Q5.
How does the typeof operator behave with null and arrays, and why is typeof null returning 'object' a historical bug?

Junior

typeof returns "object" for both null and arrays, which is unhelpful: the null result is a bug from the very first JavaScript implementation that can never be fixed for backward-compatibility reasons.

  • typeof null returns "object":

    • In the original engine, values carried a type tag in their low bits; the object tag was 0, and null was represented as a null pointer (all zeros), so it read as an object.

    • A proposal to fix it to "null" was rejected because too much code relies on the old behavior.

  • typeof [] returns "object": Arrays are specialized objects, so typeof can't distinguish them.

  • Reliable checks instead:

    • For null: value === null.

    • For arrays: Array.isArray(value).

Q6.
What are the primitive data types in JavaScript?

Junior

JavaScript has seven primitive types: values that are immutable and compared by value, not by reference. Everything that isn't a primitive is an object.

  • string: textual data, e.g. "hello".

  • number: double-precision floats, including integers, Infinity, and NaN.

  • bigint: arbitrary-precision integers, e.g. 10n.

  • boolean: true or false.

  • undefined: a declared but unassigned value.

  • symbol: unique, immutable identifiers.

  • null: intentional absence of a value (note: typeof null wrongly reports "object").

  • Key trait: immutability:

    • Primitives can't be mutated; operations produce new values, and they're copied by value when assigned or passed.

    • Everything else (objects, arrays, functions) is a reference type.

Q7.
Why does 0.1 + 0.2 not equal 0.3 in JavaScript?

Junior

Because JavaScript numbers are IEEE 754 double-precision binary floats, and 0.1 and 0.2 can't be represented exactly in binary, their sum is a tiny bit off, giving 0.30000000000000004.

  • The root cause: binary fractions: Just as 1/3 can't be written exactly in decimal, 0.1 is a repeating fraction in base 2, so it's stored as the nearest representable value.

  • Errors accumulate: Adding two rounded values produces a result that rounds to something slightly different from 0.3.

  • How to handle it:

    • Compare with a tolerance: Math.abs(a - b) < Number.EPSILON.

    • For display, use (0.1 + 0.2).toFixed(2).

    • For money, work in integer cents or use a decimal library.

Q8.
What is type coercion, and why is === generally preferred over ==? Are there cases where == is actually useful?

Junior

Type coercion is JavaScript automatically converting a value from one type to another. === is preferred because it compares value and type without coercion, avoiding surprising conversions; == applies coercion rules that are hard to predict.

  • What coercion is: Converting between types, e.g. "5" * 2 becomes 10, or 1 == "1" being true.

  • Why === is preferred:

    • It checks type and value, so results are explicit and predictable.

    • Avoids quirks like 0 == "", false == [], or null == undefined being true.

  • Where == is genuinely useful: Checking for both null and undefined at once: x == null is true for both and nothing else.

javascript

if (x == null) { // true when x is null OR undefined } 0 === "0"; // false (no coercion) 0 == "0"; // true (coerced)

Q9.
What is a higher-order function? Provide examples from the built-in Array.prototype.

Junior

A higher-order function is a function that takes another function as an argument, returns a function, or both. They enable abstraction and reuse of behavior.

  • Two qualifying traits:

    • Accepts a function (a callback), e.g. map's mapper.

    • Or returns a function, e.g. a curried or factory function.

  • Built-in Array.prototype examples:

    • map(): transforms each element into a new array.

    • filter(): keeps elements where the predicate returns truthy.

    • reduce(): folds the array into a single value via an accumulator.

    • forEach(), some(), every(), sort(): all take a callback.

  • Why they matter: they let you express what to do without writing manual loops, improving readability and composition.

javascript

const nums = [1, 2, 3, 4]; nums.filter(n => n % 2 === 0) // [2, 4] .map(n => n * 10) // [20, 40] .reduce((a, b) => a + b, 0); // 60

Q10.
What is the difference between an arrow function and a regular function regarding this?

Junior

A regular function gets its own this determined by how it's called, while an arrow function has no own this: it lexically inherits this from the enclosing scope at definition time.

  • Regular function: dynamic this:

    • Bound at call time by the call site: method call, plain call, new, or explicit call/apply/bind.

    • A standalone call gives undefined (strict mode) or the global object.

  • Arrow function: lexical this:

    • Captures this from the surrounding scope; ignores how it's called.

    • Can't be rebound: call/apply/bind won't change its this.

    • Also has no arguments object and can't be used as a constructor (no new).

  • Practical use: arrows are ideal for callbacks (e.g. inside setTimeout or array methods) where you want the outer this; use regular functions for object methods.

javascript

const obj = { name: "JS", regular() { return this.name; }, // 'JS' (this = obj) arrow: () => this.name, // undefined (this = outer scope) delayed() { setTimeout(() => console.log(this.name), 0); // 'JS' (lexical this) } };

Q11.
What is the difference between a function declaration and a function expression?

Junior

A function declaration is a standalone statement that is fully hoisted (name and body), while a function expression assigns a function to a variable and is only available after that line runs.

  • Function declaration:

    • Starts with the function keyword as a statement: function foo() {}.

    • Hoisted entirely, so you can call it before its definition appears in the code.

  • Function expression:

    • A function used as a value: const foo = function() {} (can be named or anonymous).

    • Only the variable is hoisted, not the assignment, so calling it before the line throws (TypeError or ReferenceError with const/let).

  • Key takeaway: hoisting behavior is the practical difference; declarations are available throughout their scope, expressions only from their evaluation onward.

javascript

sayHi(); // works: declaration is hoisted function sayHi() { console.log("hi"); } sayBye(); // TypeError: sayBye is not a function var sayBye = function() { console.log("bye"); };

Q12.
What is the difference between map, forEach, filter, and reduce?

Junior

All four iterate an array, but they differ in what they return: map transforms into a new array, filter selects a subset, reduce collapses to a single value, and forEach just runs a side effect and returns nothing.

  • map: Returns a new array of the same length, each element transformed by the callback.

  • filter: Returns a new array containing only elements for which the callback returns truthy.

  • reduce: Accumulates elements into a single result (number, object, array) using an accumulator and an initial value.

  • forEach: Runs the callback for each element purely for side effects; returns undefined and can't be chained.

  • Key distinction: map/filter/reduce are non-mutating and return values (chainable); forEach is for effects only.

javascript

const nums = [1, 2, 3, 4]; nums.map(n => n * 2); // [2, 4, 6, 8] nums.filter(n => n % 2 === 0); // [2, 4] nums.reduce((sum, n) => sum + n, 0); // 10 nums.forEach(n => console.log(n)); // logs each, returns undefined

Q13.
What are the three states of a Promise?

Junior

A Promise is always in exactly one of three states, and once it leaves pending it is settled and can never change again.

  • pending: The initial state: the async operation hasn't completed; no value or reason yet.

  • fulfilled: Completed successfully via resolve(value); the .then() success handler receives the value.

  • rejected: Failed via reject(reason) or a thrown error; handled by .catch() or the second .then() argument.

  • Key rule: immutability: Fulfilled and rejected are collectively called settled; transitions are one-way and final, so a Promise resolves at most once.

Q14.
What does preventDefault() do, and how does it differ from stopPropagation()?

Junior

preventDefault() stops the browser's default action for an event (like following a link or submitting a form), while stopPropagation() stops the event from traveling further through the DOM to other handlers. They address two independent concerns.

  • preventDefault() cancels default behavior:

    • Examples: stop a form submit from reloading, stop an anchor from navigating, stop a checkbox from toggling.

    • Does NOT stop the event from reaching other listeners.

  • stopPropagation() halts event flow:

    • Prevents the event from bubbling up (or capturing down) to parent/ancestor handlers.

    • Does NOT cancel the default action.

    • stopImmediatePropagation() additionally blocks other listeners on the same element.

  • They are orthogonal: you can call neither, one, or both depending on whether you want to suppress the default action, the propagation, or both.

Q15.
How can you use closures to create private variables?

Junior

A closure lets an inner function keep access to its outer function's variables after that function returns, so those variables stay alive but unreachable from outside: that gives you true private state exposed only through the methods you return.

  • The variable lives in the enclosing scope: It is not a property of the returned object, so there is no way to read or write it directly from outside.

  • Returned functions form the public API: Only the closures you expose (getters/setters/methods) can touch the private value, letting you enforce rules.

  • Each call creates a fresh, independent scope: Calling the factory twice gives two separate private states, unlike a shared module-level variable.

  • Modern alternative: class fields prefixed with # provide native privacy without closures.

javascript

function createCounter() { let count = 0; // private return { increment() { count++; }, get() { return count; }, }; } const c = createCounter(); c.increment(); c.get(); // 1 c.count; // undefined (no direct access)

Q16.
Explain the difference between passing by value and passing by reference in JavaScript.

Junior

JavaScript is always pass-by-value, but the value of an object is a reference (a pointer): primitives copy their data, while objects copy the reference, so both variables point at the same underlying object.

  • Primitives are copied by value: Numbers, strings, booleans, null, undefined, symbol, bigint: reassigning a parameter never affects the caller.

  • Objects pass a copy of the reference: Mutating the object (obj.x = 1, arr.push()) is visible to the caller because both names point to the same object.

  • Reassigning the parameter breaks the link: Setting obj = {} inside the function only repoints the local copy of the reference, not the caller's variable: proof it is not true pass-by-reference.

javascript

function mutate(o) { o.x = 99; } // affects caller function reassign(o) { o = {}; } // does NOT affect caller const a = { x: 1 }; mutate(a); // a.x === 99 reassign(a); // a still { x: 99 }

Q17.
What is the Nullish Coalescing operator (??) and how does it differ from the Logical OR operator?

Junior

The nullish coalescing operator ?? returns its right-hand value only when the left side is null or undefined, whereas || falls back on any falsy value. That makes ?? the safe choice when 0, '', or false are valid values.

  • || checks for falsy: Triggers the fallback for 0, '', NaN, false, null, undefined.

  • ?? checks only for nullish: Triggers the fallback only for null and undefined, preserving other falsy values.

  • Syntax restriction: You cannot mix ?? directly with || or && without parentheses: a deliberate guard against ambiguity.

javascript

const count = 0; count || 10; // 10 (0 is falsy) count ?? 10; // 0 (0 is not nullish)

Q18.
What is 'Optional Chaining' (?.) and where does it short-circuit?

Junior

Optional chaining ?. safely accesses a property, index, or method on a value that might be null or undefined: if the part before ?. is nullish, the whole expression short-circuits to undefined instead of throwing.

  • Three forms: obj?.prop for properties, obj?.[key] for dynamic keys, fn?.() for calling a maybe-missing function.

  • Where it short-circuits: The moment the operand to the left of ?. is null or undefined, evaluation stops and the entire chain (including later calls/accesses) yields undefined.

  • Pairs well with ??: a?.b ?? 'default' supplies a fallback when the chain is nullish.

  • Caveat: Only guards against null/undefined, not other errors, and should not be overused to hide genuine bugs.

javascript

const user = { profile: null }; user.profile?.name; // undefined (no throw) user.profile.name; // TypeError user.getName?.(); // undefined (method missing)

Q19.
What is the difference between the spread operator and rest parameters, and how are they used?

Junior

They share the ... syntax but do opposite things: spread expands an iterable or object into individual elements, while rest collects multiple individual elements into a single array (or object). Context (where it appears) decides which one it is.

  • Spread expands:

    • Used in array/object literals and function calls to unpack values: [...arr], {...obj}, fn(...args).

    • Great for shallow copies and merging.

  • Rest collects:

    • Used in function parameters and destructuring to gather the remainder: function f(...args), const [a, ...rest] = arr.

    • A rest parameter must be the last parameter.

  • Rule of thumb: On the right side / in a call it spreads; on the left side / in a parameter list it collects.

javascript

const merged = [...[1, 2], ...[3, 4]]; // spread -> [1,2,3,4] function sum(...nums) { // rest -> nums is [1,2,3] return nums.reduce((a, b) => a + b, 0); } sum(1, 2, 3); // 6

Q20.
What is destructuring assignment, and how does it work for objects and arrays?

Junior

Destructuring is syntax that unpacks values from arrays or properties from objects into distinct variables in a single statement. Arrays destructure by position, objects by key name, and both support defaults, renaming, and nesting.

  • Array destructuring is positional: const [a, b] = arr; skip elements with commas ([, second]) and gather the tail with rest ([first, ...rest]).

  • Object destructuring is by key: const { name } = obj; rename with { name: n } and collect remaining keys with { ...others }.

  • Defaults and nesting: const { x = 5 } = obj applies a default when the value is undefined; you can destructure nested structures in one expression.

  • Common uses: Extracting function parameters (function f({ id, name })), swapping variables, and importing pieces of a return value.

javascript

const [first, ...rest] = [1, 2, 3]; // first=1, rest=[2,3] const { name, age = 0 } = { name: 'Ada' }; // name='Ada', age=0 [a, b] = [b, a]; // swap

Q21.
What is the difference between for...in and for...of loops?

Junior

for...in iterates enumerable string keys (including inherited ones), while for...of iterates the values of any iterable (arrays, strings, Map, Set).

  • for...in loops over keys/properties:

    • Yields property names (strings) and walks the prototype chain, so inherited enumerable props show up too.

    • Best for plain objects; order is not guaranteed for integer-like keys.

    • On arrays it yields index strings ("0","1"), which is usually not what you want.

  • for...of loops over values:

    • Works on anything implementing the iterable protocol (Symbol.iterator).

    • Does not iterate plain objects (they aren't iterable) unless you use Object.entries().

  • Rule of thumb: for...of for arrays/iterables, for...in (with hasOwnProperty) for object keys.

javascript

const arr = ['a', 'b']; for (const i in arr) console.log(i); // "0", "1" (keys) for (const v of arr) console.log(v); // "a", "b" (values)

Q22.
What is the Temporal Dead Zone (TDZ), and why can't let and const variables be accessed before their declaration even though they are hoisted?

Mid

The TDZ is the period between when a let/const binding is created (at the top of its block) and when its declaration line actually executes; accessing it during that window throws a ReferenceError. They are hoisted, but unlike var they are not initialized to undefined.

  • Hoisted but uninitialized: The engine reserves the binding in the scope during the creation phase, but leaves it in an "uninitialized" state until evaluation reaches the declaration.

  • The TDZ is the gap: From block entry until the declaration runs, any read or write throws.

  • Why this exists:

    • It catches use-before-declaration bugs that var silently hides by returning undefined.

    • It makes const safe: a constant can never be observed before its single assignment.

javascript

console.log(x); // ReferenceError (TDZ) let x = 5; console.log(y); // undefined (var hoisted + initialized) var y = 5;

Q23.
How does the JavaScript engine handle nested scopes when looking up a variable?

Mid

The engine resolves a variable by walking outward through a chain of nested scopes (the scope chain): it checks the current scope first, then each enclosing scope, up to the global scope, stopping at the first match.

  • The scope chain: Each scope holds a reference to its parent (lexical) scope, forming a chain that mirrors how the code is nested.

  • Lookup direction:

    • Always inside-out: innermost scope first, then outward. It never searches into child or sibling scopes.

    • The first match wins, which is how inner variables shadow outer ones of the same name.

  • If nothing matches: A read of an undeclared name throws a ReferenceError (in strict mode an assignment does too).

  • Determined at definition time: the chain follows lexical nesting, not the call stack.

Q24.
Why can you access a variable defined with var before its declaration, but not one defined with let?

Mid

Both are hoisted, but they are initialized differently: var is set to undefined during the creation phase, so reading it early just gives undefined, whereas let stays uninitialized in the TDZ and throws on early access.

  • var: hoisted + initialized: The binding exists and holds undefined before its line, so no error occurs.

  • let: hoisted, not initialized: The binding exists but is in the TDZ until the declaration runs; reading it throws ReferenceError.

  • The distinction is intentional: it surfaces use-before-declaration mistakes instead of silently yielding undefined.

Q25.
What are the tradeoffs of using global scope, and how do ES Modules help mitigate these issues?

Mid

Global scope makes variables convenient to reach but couples code together: it risks naming collisions, accidental mutation, and unclear dependencies. ES Modules fix this by giving each file its own scope and requiring explicit imports/exports.

  • Tradeoffs of global scope:

    • Naming collisions: two scripts defining the same global silently overwrite each other.

    • Hidden coupling: any code can read or mutate globals, making bugs hard to trace.

    • Pollution: globals live for the page's lifetime and aren't garbage collected.

    • Hard to test and reason about because dependencies are implicit.

  • How ES Modules help:

    • Each module has its own top-level scope, so declarations don't leak to the global object.

    • Dependencies are explicit via import / export, making the dependency graph clear.

    • Modules run in strict mode by default and are singletons (evaluated once, shared).

javascript

// utils.js export const PI = 3.14159; // scoped to the module, not global // main.js import { PI } from "./utils.js"; // explicit dependency

Q26.
What are 'truthy' and 'falsy' values? Why is [] == false true, but [] itself is truthy?

Mid

Truthy and falsy describe how a value coerces to a boolean in a boolean context. There are exactly a handful of falsy values; everything else is truthy. [] == false is true because of how loose equality coerces, while [] on its own is truthy because it's an object reference.

  • The falsy values (memorize these):

    • false, 0, -0, 0n, "", null, undefined, NaN.

    • Everything else, including all objects and arrays, is truthy.

  • Why [] is truthy: In a boolean context (if ([])), the value is converted with ToBoolean, and every object reference is truthy regardless of contents.

  • Why [] == false is true:

    • == coerces both sides to numbers, not booleans. false becomes 0.

    • [] converts to a primitive: [].toString() is "", which becomes 0. So 0 == 0 is true.

  • Lesson: boolean-context truthiness and == coercion are different algorithms; prefer === to avoid surprises.

Q27.
What is NaN, and why is typeof NaN a 'number'?

Mid

NaN means "Not-a-Number": it represents an invalid or unrepresentable result of a numeric operation. It's a "number" because it's defined by the IEEE 754 floating-point standard as a special numeric value, not a separate type.

  • How you get it:

    • Invalid math like 0/0 or Math.sqrt(-1).

    • Failed coercion like Number("abc") or parseInt("x").

  • Why typeof NaN is "number": NaN lives within the numeric type as a defined floating-point bit pattern, so the type is correctly "number".

  • It is not equal to itself: NaN === NaN is false, so test with Number.isNaN(x) (avoid the looser global isNaN, which coerces).

Q28.
What is a Symbol in JavaScript, and what are some practical use cases for it?

Mid

A Symbol is a primitive type whose every value is guaranteed unique and immutable, even if two symbols share the same description. They're mainly used as collision-proof object keys and for hooking into language behavior.

  • Creating them:

    • Symbol("desc") always returns a new unique value; the description is just a label.

    • Symbol.for("key") looks up/creates a shared symbol in a global registry.

  • Practical use cases:

    • Unique object keys that won't clash with other code's properties.

    • "Hidden" metadata: symbol keys are skipped by for...in and JSON.stringify.

    • Well-known symbols to customize language behavior, e.g. Symbol.iterator makes an object iterable.

  • Note: not fully private (reachable via Object.getOwnPropertySymbols), but effectively non-enumerable.

javascript

const id = Symbol("id"); const user = { name: "Ana", [id]: 123 }; user[id]; // 123 Object.keys(user); // ["name"] -- symbol key hidden

Q29.
Explain implicit type coercion in JavaScript.

Mid

Implicit coercion is when JavaScript converts types automatically during an operation you didn't explicitly ask to convert, driven by the operator and the operand types.

  • To string: The + operator concatenates if either operand is a string: 1 + "2" is "12".

  • To number: Arithmetic and comparison operators (other than + with a string) coerce to number: "5" - 1 is 4.

  • To boolean: Conditions and logical operators coerce via truthiness; falsy values are false, 0, "", null, undefined, NaN.

  • Objects use toPrimitive: Objects convert via Symbol.toPrimitive, then valueOf() / toString(), which explains odd results with arrays and {}.

Q30.
What is the difference between Object.is() and the strict equality operator (===)?

Mid

Object.is() behaves almost identically to ===, but it differs in two edge cases: NaN and signed zeros.

  • NaN comparison: NaN === NaN is false, but Object.is(NaN, NaN) is true.

  • Signed zeros: 0 === -0 is true, but Object.is(0, -0) is false.

  • Everything else matches: Neither does type coercion; for all other values the two agree.

  • When to use: Prefer === normally; reach for Object.is() only when NaN or -0 semantics matter.

Q31.
How is the value of this determined in different contexts (e.g., arrow functions, regular functions, methods, and the new keyword)?

Mid

For regular functions this is determined dynamically by how the function is called; arrow functions are the exception, capturing this lexically from where they're defined.

  • Method call: obj.method(): this is the object left of the dot (obj).

  • Plain function call: this is the global object (window) in sloppy mode, or undefined in strict mode / modules.

  • new keyword: this is the freshly created instance bound to the constructor.

  • Explicit binding: call(), apply(), and bind() set this explicitly.

  • Arrow functions: Have no own this; they inherit it from the enclosing lexical scope, so call/apply/bind can't change it. Ideal for callbacks inside methods.

javascript

const obj = { name: "A", regular() { return this.name; }, // "A" (caller is obj) arrow: () => this?.name, // outer this, not obj }; const f = obj.regular; f(); // undefined/throws: lost binding when called plain

Q32.
Explain 'Function Currying' and why you might use it.

Mid

Currying transforms a function that takes multiple arguments into a sequence of functions that each take one argument, returning a new function until all arguments are supplied.

  • The transformation: f(a, b, c) becomes f(a)(b)(c), each call returning a function closing over prior arguments.

  • Why use it:

    • Partial application: fix some arguments now and reuse the specialized function later.

    • Reusability and composition: small, single-argument functions compose cleanly in functional pipelines.

    • Cleaner configuration of behaviors, e.g. a logger pre-set to a level.

  • Mechanism: it relies on closures to remember earlier arguments.

javascript

const multiply = a => b => a * b; const double = multiply(2); // partially applied double(5); // 10

Q33.
What is the difference between .call(), .apply(), and .bind()? When would you use one over the others?

Mid

All three set this for a function. call() and apply() invoke immediately (differing only in how arguments are passed), while bind() returns a new function to call later.

  • call(thisArg, arg1, arg2, ...): Invokes now; arguments passed individually.

  • apply(thisArg, [args]): Invokes now; arguments passed as an array. Handy when args are already in an array.

  • bind(thisArg, ...args): Returns a new function with this permanently bound; does not invoke. Supports partial application.

  • When to use each:

    • call: borrow a method and run it immediately with known args.

    • apply: same, but args live in an array (less needed now with spread).

    • bind: fix this for a callback or event handler used later.

javascript

function greet(greeting) { return `${greeting}, ${this.name}`; } const user = { name: "Sam" }; greet.call(user, "Hi"); // "Hi, Sam" greet.apply(user, ["Hi"]); // "Hi, Sam" const bound = greet.bind(user); bound("Hi"); // "Hi, Sam" (called later)

Q34.
What is an IIFE (Immediately Invoked Function Expression), and why was it commonly used?

Mid

An IIFE is a function expression that runs immediately upon definition, wrapped in parentheses and invoked with (). It was the classic way to create a private scope before block-scoped declarations and modules existed.

  • Syntax: Wrap the function in parentheses to make it an expression, then call it: (function(){ ... })().

  • Why it was used:

    • Privacy: variables inside don't leak to the global scope, avoiding name collisions.

    • In the var era it was the main tool for scoping, since only function scope existed (no let/const blocks).

    • Module pattern: return an object exposing only chosen members, keeping the rest private.

  • Today: ES modules and block scoping (let/const) largely replace IIFEs, but they still appear in bundled/legacy code.

javascript

const counter = (function() { let count = 0; // private return { inc: () => ++count }; })(); counter.inc(); // 1

Q35.
What is the difference between __proto__ and prototype?

Mid

They're two sides of the same mechanism: prototype is a property on constructor functions that becomes the prototype of instances, while __proto__ is the actual reference on an object pointing to its prototype.

  • prototype:

    • A property that exists only on functions (constructors).

    • Its value is the object that will be assigned as the prototype of any instance created with new.

  • __proto__:

    • An accessor present on every object that points to its internal [[Prototype]].

    • It's the link the engine follows when resolving properties up the chain.

    • Prefer Object.getPrototypeOf() over the legacy __proto__.

  • Relationship: for an instance, instance.__proto__ === Constructor.prototype.

javascript

function Dog() {} const d = new Dog(); d.__proto__ === Dog.prototype; // true Object.getPrototypeOf(d) === Dog.prototype; // true

Q36.
What is prototypal inheritance, and how does it differ from classical inheritance found in languages like Java or C++?

Mid

Prototypal inheritance means objects inherit directly from other objects through a live prototype link, rather than from classes that act as static blueprints as in classical inheritance.

  • Prototypal (JavaScript):

    • An object delegates to another object (its prototype); lookups fall back up the chain at runtime.

    • It's dynamic: changing a prototype affects all objects linked to it, even existing ones.

  • Classical (Java, C++):

    • Classes are blueprints compiled ahead of time; objects are instances created from them.

    • Inheritance is a copy of structure fixed at class-definition time, not a live link.

  • The class keyword caveat: ES6 class is syntactic sugar over prototypes, not true classical inheritance.

Q37.
Explain the prototype chain. What happens when you try to access a property that doesn't exist on an object?

Mid

The prototype chain is the series of linked objects the engine walks when looking up a property: if it's not on the object itself, it follows [[Prototype]] upward until it finds it or reaches null.

  • Lookup process:

    1. Check the object's own properties first.

    2. If not found, follow its prototype (__proto__) and check there.

    3. Repeat up the chain until found.

  • Reaching the end:

    • The chain typically ends at Object.prototype, whose prototype is null.

    • If the property isn't found anywhere, the access returns undefined (it does not throw).

  • Performance note: deep chains make lookups slower, since each level is checked in turn.

javascript

const obj = {}; obj.toString; // found on Object.prototype, not own obj.missing; // undefined: walked whole chain, not there

Q38.
What happens under the hood when you call a function with the new keyword?

Mid

Calling a function with new creates a fresh object, links it to the constructor's prototype, runs the function with this bound to that object, and returns it automatically.

  • The four steps:

    1. A new empty object is created.

    2. Its [[Prototype]] is set to the constructor's prototype property.

    3. The constructor runs with this bound to the new object.

    4. It returns this implicitly, unless the constructor explicitly returns its own object.

  • The return rule:

    • If the function returns a non-object (or nothing), the new object is used.

    • If it returns an object, that object replaces the new instance.

javascript

function Person(name) { // this = {}, linked to Person.prototype this.name = name; // implicitly: return this; } const p = new Person("Ada"); p.name; // 'Ada' Object.getPrototypeOf(p) === Person.prototype; // true

Q39.
Why are ES6 classes called syntactic sugar?

Mid

They are called syntactic sugar because ES6 classes don't add a new object model: they are a cleaner syntax over JavaScript's existing prototype-based inheritance.

  • Under the hood it's still prototypes:

    • A class creates a constructor function, and methods are added to its prototype object, exactly as you'd do manually.

    • typeof MyClass returns "function", confirming there's no new primitive type.

  • extends wires the prototype chain: It sets up the same prototype linkage you'd build with Object.create, and super delegates to the parent.

  • It's not purely cosmetic, though:

    • Class bodies run in strict mode, declarations aren't hoisted for use, and the constructor can't be called without new.

    • Some features (true private fields with #, subclassing built-ins) are hard or impossible to replicate exactly with old syntax.

javascript

class Animal { speak() { return "..."; } } // roughly equivalent to: function Animal() {} Animal.prototype.speak = function () { return "..."; };

Q40.
How does the instanceof operator work, and how does it relate to the prototype chain?

Mid

obj instanceof Ctor checks whether Ctor.prototype appears anywhere in obj's prototype chain, so it tests prototype linkage, not the actual constructor that built the object.

  • The lookup: It walks Object.getPrototypeOf(obj) repeatedly, comparing each link against Ctor.prototype; true if a match is found before the chain ends at null.

  • Consequences of being chain-based:

    • A subclass instance is instanceof both the subclass and its parents.

    • Reassigning Ctor.prototype changes the result for objects made afterward.

  • Customizable and not realm-safe:

    • It actually invokes Ctor[Symbol.hasInstance], which a class can override.

    • It fails across realms (e.g. an array from an iframe): use Array.isArray instead.

Q41.
Why would you use async/await over raw Promises? Are there any performance trade-offs?

Mid

You use async/await mainly for readability: it lets asynchronous code read top-to-bottom like synchronous code, with normal try/catch error handling. It's built on Promises, so it doesn't replace them so much as consume them more cleanly.

  • Readability and control flow:

    • Avoids .then() chains and nested callbacks; loops, conditionals, and try/catch all work naturally.

    • Cleaner error handling: one try/catch instead of scattered .catch() handlers.

  • The sequencing trap: Awaiting independent tasks one after another serializes them needlessly; run them in parallel with Promise.all.

  • Performance trade-offs:

    • Negligible in practice: async functions still resolve via the microtask queue, same as raw Promises.

    • The real cost is logical, not CPU: accidental sequential awaits hurt latency far more than any engine overhead.

javascript

// Bad: serialized const a = await getA(); const b = await getB(); // Good: concurrent const [a, b] = await Promise.all([getA(), getB()]);

Q42.
What is the difference between Promise.all, Promise.allSettled, Promise.any, and Promise.race, and when would you choose one over the others?

Mid

All four combine multiple Promises but differ in what counts as done and how they treat failures: choose based on whether you need every result, the first result, or tolerance for partial failure.

  • Promise.all:

    • Resolves with an array of all values once every Promise fulfills; rejects immediately if any one rejects (fail-fast).

    • Use when you need all results and any failure should abort.

  • Promise.allSettled:

    • Never rejects: waits for all and returns objects of shape {status, value/reason}.

    • Use when you want every outcome regardless of failures (e.g. batch jobs).

  • Promise.any:

    • Resolves with the first fulfilled value; rejects only if all reject (with an AggregateError).

    • Use for redundancy: first successful source wins.

  • Promise.race:

    • Settles as soon as any Promise settles, whether fulfilled or rejected.

    • Use for timeouts: race a task against a rejecting timer.

Q43.
How does the fetch API handle HTTP error status codes like 404 or 500?

Mid

fetch does not treat HTTP error statuses as failures: the returned Promise only rejects on network-level errors, so a 404 or 500 still resolves successfully. You must inspect the response yourself.

  • What rejects vs what resolves:

    • Rejects on network failure, DNS error, CORS block, or aborted request.

    • Resolves for any completed HTTP exchange, including 4xx and 5xx.

  • How to detect HTTP errors:

    • Check response.ok (true for 200–299) or read response.status directly.

    • Throw manually so a single catch handles both network and HTTP errors.

javascript

const res = await fetch(url); if (!res.ok) { throw new Error(`HTTP ${res.status}`); // 404/500 land here } const data = await res.json();

Q44.
When would you use Promise.allSettled instead of Promise.all?

Mid

Use Promise.allSettled when you want every promise to run to completion and need each individual outcome, even if some reject; use Promise.all when any failure should abort the whole batch.

  • Promise.all is fail-fast:

    • Rejects as soon as one promise rejects, discarding the other results; the rejection reason is whatever rejected first.

    • Best when results are interdependent: if one fails the combined operation is meaningless.

  • Promise.allSettled never rejects:

    • Always resolves to an array of objects shaped { status: 'fulfilled', value } or { status: 'rejected', reason }.

    • Best for independent tasks where partial success is fine (e.g. fetching from several sources, batch saves).

  • Practical signal: choose allSettled when you must report which items succeeded and which failed rather than stopping on the first error.

Q45.
What are the different states of a Promise, and can a Promise be 'cancelled' in native JavaScript?

Mid

A Promise has three states: pending, fulfilled, and rejected. Native Promises have no built-in cancel: once created they run to settlement, so cancellation is simulated with other tools.

  • The three states:

    • pending: initial state, not yet settled.

    • fulfilled: resolved with a value.

    • rejected: failed with a reason.

  • Settled is terminal: Once fulfilled or rejected a Promise is immutable; further resolve/reject calls are ignored.

  • No native cancellation:

    • There is no .cancel(); the underlying work keeps running even if you stop caring about the result.

    • Use AbortController with an AbortSignal to abort operations that support it (like fetch), which rejects with an AbortError.

Q46.
Why does await block the execution of a function but not the entire main thread?

Mid

await pauses only the surrounding async function by suspending it and returning control to the event loop; the rest of the program keeps running because nothing is actually blocked, the function just resumes later via a microtask.

  • await suspends, it does not block:

    • The async function is paused and its continuation is scheduled as a microtask when the awaited promise settles.

    • Control returns to the caller, so other code, timers, and event handlers continue.

  • The main thread stays free: JavaScript is single-threaded; await yields the thread back to the event loop rather than sitting on it.

  • The trap: synchronous blocking is different: A long synchronous loop or await-ing a CPU-bound sync computation still freezes the thread, because only real async work yields.

javascript

async function run() { console.log('A'); await delay(1000); // suspends run(), thread is free console.log('C'); // resumes via microtask later } run(); console.log('B'); // runs immediately -> A, B, C

Q47.
How does error handling work with try/catch/finally, and how do you create custom error types?

Mid

try/catch/finally lets you run risky code, catch thrown errors, and run cleanup that executes regardless of outcome; custom error types are made by extending the built-in Error class.

  • How the blocks work:

    • try: runs code that may throw.

    • catch: receives the thrown value (often an Error) and handles it.

    • finally: always runs, on success, throw, or even return; ideal for cleanup.

  • Works with async code: try/catch catches rejections of awaited promises, but plain .then() chains need .catch().

  • Custom error types: Extend Error, set this.name, and call super(message); lets you branch with instanceof.

javascript

class ValidationError extends Error { constructor(message, field) { super(message); this.name = 'ValidationError'; this.field = field; } } try { throw new ValidationError('Email required', 'email'); } catch (err) { if (err instanceof ValidationError) console.log(err.field); } finally { // cleanup always runs }

Q48.
What is 'Event Delegation' and why is it considered a performance optimization?

Mid

Event delegation is attaching a single listener to a common ancestor and using event bubbling to handle events from many child elements, instead of binding a listener to each child.

  • How it works:

    • The event bubbles up from the target to the ancestor, where one handler inspects event.target to decide what to do.

    • Use event.target.closest(selector) or a class check to match the relevant child.

  • Why it is a performance optimization:

    • One listener uses far less memory than hundreds of individual listeners.

    • It handles dynamically added elements automatically, with no need to rebind.

  • Caveat: Only works for events that bubble; some events (like focus or blur) do not bubble by default.

javascript

document.querySelector('#list').addEventListener('click', (e) => { const item = e.target.closest('li'); if (item) console.log('Clicked', item.dataset.id); });

Q49.
Explain Event Bubbling and Event Capturing. How do you stop an event from propagating?

Mid

Event propagation has two main phases: capturing flows from the root down to the target, and bubbling flows from the target back up to the root. You stop propagation with event.stopPropagation().

  • Capturing phase (top-down): Runs first, from document toward the target; opt in with addEventListener(type, fn, true) or { capture: true }.

  • Bubbling phase (bottom-up): Default behavior: after reaching the target, the event rises back up through ancestors, which is what makes delegation possible.

  • Stopping propagation:

    • event.stopPropagation() halts the event from continuing to other elements in either phase.

    • Note: event.preventDefault() is different, it stops the browser default action, not propagation.

Q50.
What is the difference between stopPropagation() and stopImmediatePropagation()?

Mid

Both stop an event from traveling further, but stopPropagation() still lets other listeners on the same element run, while stopImmediatePropagation() also prevents those remaining same-element listeners from firing.

  • stopPropagation():

    • Prevents the event from reaching ancestor (or descendant, in capture) elements.

    • Other handlers attached to the current element for the same event still execute.

  • stopImmediatePropagation():

    • Does everything stopPropagation() does, plus skips any remaining listeners on the same element.

    • Useful when multiple handlers are bound to one element and one needs the last word.

  • Rule of thumb: use stopImmediatePropagation() only when you specifically need to block sibling listeners on the same node.

Q51.
What is the difference between an attribute and a property in the DOM?

Mid

An attribute is the value written in the HTML markup (always a string), while a property is the value on the live DOM object in JavaScript; they sync at parse time but can diverge afterward.

  • Attributes come from HTML:

    • Accessed via getAttribute() / setAttribute(); values are always strings.

    • Represent the initial/default state as authored in the document.

  • Properties live on the DOM object:

    • Accessed like input.value or input.checked; can be any type (boolean, number, object).

    • Represent the current live state.

  • They can diverge:

    • Typing into a text box changes the value property but the value attribute keeps its original markup value.

    • Some names differ: the class attribute maps to the className property.

javascript

// <input id="x" value="hi"> const el = document.getElementById('x'); el.value = 'bye'; el.value; // 'bye' (property = current state) el.getAttribute('value'); // 'hi' (attribute = original markup)

Q52.
What is requestAnimationFrame, and how does it differ from setTimeout for animations?

Mid

requestAnimationFrame schedules a callback to run right before the browser's next repaint (typically ~60fps), making it the correct tool for animation, whereas setTimeout fires on an arbitrary timer that isn't aligned with the render cycle.

  • Synced to the display refresh:

    • rAF runs once per frame, so movement is smooth and avoids painting frames the user never sees.

    • setTimeout(fn, 16) drifts: timers aren't precise and can fire mid-frame, causing jank or torn frames.

  • Pauses in background tabs: rAF is throttled/paused when the tab is hidden, saving CPU and battery; setTimeout keeps firing.

  • Receives a timestamp: The callback gets a high-resolution time argument, enabling time-based (frame-rate-independent) animation math.

  • You re-schedule each frame: call requestAnimationFrame again inside the callback to continue the loop.

javascript

function step(timestamp) { box.style.left = (timestamp / 10 % 300) + 'px'; requestAnimationFrame(step); // queue the next frame } requestAnimationFrame(step);

Q53.
Explain closures and provide a real-world example of when you would use one.

Mid

A closure is a function bundled with references to the variables from the scope where it was defined, so it can keep accessing those variables even after that outer scope has returned. This lets functions carry private, persistent state.

  • How it works:

    • An inner function captures variables by reference, not by copy, keeping them alive as long as the closure exists.

    • Each call to the outer function creates a fresh, independent scope.

  • Why it's useful:

    • Data privacy: emulate private variables (the module pattern, factory functions).

    • State across calls: counters, memoization caches, debounced/throttled handlers.

    • Partial application / currying: pre-bind some arguments.

  • Real-world example: a counter factory that hides its count from outside code.

javascript

function createCounter() { let count = 0; // private, captured by the closure return () => ++count; // remembers `count` across calls } const next = createCounter(); next(); // 1 next(); // 2 -- count is inaccessible except through next()

Q54.
What is a 'Pure Function' and why are they preferred in many modern architectures?

Mid

A pure function always returns the same output for the same input and produces no side effects (no mutating external state, no I/O, no reliance on outside variables). This predictability makes code easier to reason about, test, and parallelize.

  • Two defining rules:

    • Deterministic: same arguments always yield the same result.

    • No side effects: doesn't modify external variables, the DOM, network, or its input arguments.

  • Why architectures prefer them:

    • Testability: no mocks or setup needed; just assert input/output.

    • Predictability & debugging: behavior depends only on inputs, so bugs are local.

    • Enables optimizations: safe to memoize, cache, reorder, or run concurrently.

    • Foundational to React/Redux: components and reducers are meant to be pure for reliable rendering and time-travel debugging.

javascript

// Pure: depends only on args, mutates nothing const add = (a, b) => a + b; // Impure: reads external state and mutates it let total = 0; const addToTotal = (n) => { total += n; };

Q55.
What is 'Memoization' and how does it relate to closures?

Mid

Memoization is an optimization that caches a function's results keyed by its arguments, so repeated calls with the same inputs return the stored result instead of recomputing. It relies on a closure to keep that cache alive privately between calls.

  • How it works:

    • On each call, check the cache: hit returns instantly, miss computes then stores.

    • Best suited to pure functions: caching only makes sense when output depends solely on input.

  • Relation to closures: The cache (a Map or object) lives in the outer scope and is captured by the returned function, persisting across calls while staying private.

  • Trade-off: trades memory for speed; useful for expensive or repeated computations, less so for cheap or rarely-repeated ones.

javascript

function memoize(fn) { const cache = new Map(); // captured by closure, kept private return (n) => { if (cache.has(n)) return cache.get(n); const result = fn(n); cache.set(n, result); return result; }; }

Q56.
What does Object.freeze() do, and how can you achieve immutability in JavaScript?

Mid

Object.freeze() makes an object's existing properties non-writable and non-configurable and prevents adding/removing properties, but it is shallow: nested objects remain mutable. True immutability requires freezing recursively or treating data as read-only by convention.

  • What Object.freeze() guarantees:

    • Cannot add, delete, or reassign top-level properties; Object.isFrozen() confirms it.

    • Silent failure in non-strict mode, throws in strict mode.

  • It is shallow: A frozen object's nested object/array can still be changed; you need a deep freeze that recurses over properties.

  • Other immutability strategies:

    • Create new copies instead of mutating (spread, map, filter).

    • Use libraries like Immer or persistent data structures for large structures.

javascript

const o = Object.freeze({ a: 1, nested: { b: 2 } }); o.a = 9; // ignored (or throws in strict mode) o.nested.b = 9; // works! freeze is shallow

Q57.
How does JSON.stringify handle things like functions, undefined, and circular references, and what do the replacer and toJSON do?

Mid

JSON.stringify() serializes JSON-compatible values and silently drops or transforms non-JSON ones; circular references throw. The replacer lets you filter or transform values during serialization, and an object's toJSON() method customizes how it represents itself.

  • Functions and undefined: In an object they are omitted entirely; in an array they become null.

  • Special values: NaN and Infinity become null; Date becomes an ISO string (via its toJSON); BigInt throws.

  • Circular references throw: A TypeError: Converting circular structure to JSON is raised.

  • The replacer (2nd arg): A function (key, value) run per entry: return a transformed value or undefined to omit a key; an array acts as a whitelist of keys.

  • toJSON(): If a value defines this method, its return value is serialized instead of the object itself.

javascript

JSON.stringify({ f: () => {}, u: undefined, n: 1 }); // '{"n":1}' JSON.stringify([() => {}, undefined]); // '[null,null]' class User { constructor(n){ this.name=n; this.pw='secret'; } toJSON(){ return { name: this.name }; } } JSON.stringify(new User('Ada')); // '{"name":"Ada"}'

Q58.
Explain the difference between shallow copy and deep copy, and when is structuredClone() preferred over JSON.parse(JSON.stringify())?

Mid

A shallow copy duplicates only the top level (nested objects are still shared references), while a deep copy clones every level recursively. structuredClone() is the preferred deep-copy because it handles more types and circular references that JSON cannot.

  • Shallow copy:

    • Made by {...obj}, Object.assign(), or Array.prototype.slice().

    • Mutating a nested object affects both copies because they share the reference.

  • Deep copy: Fully independent clone; nested mutations don't leak.

  • Why structuredClone() beats JSON.parse(JSON.stringify()):

    • Supports Date, Map, Set, typed arrays, and circular references.

    • The JSON trick drops undefined, functions, and Symbols, turns Date into a string, and throws on cycles.

    • Caveat: structuredClone() cannot clone functions or DOM nodes.

Q59.
What is the difference between Map/Set and WeakMap/WeakSet, and why would you use a weak version for memory management?

Mid

The weak variants hold their keys/values weakly: if nothing else references an object key, it can be garbage collected even while in the collection. This prevents the memory leaks that strong references in Map/Set would cause.

  • Map / Set (strong references):

    • Iterable, have size, and keep entries alive as long as the collection lives.

    • Keys/values can be any type.

  • WeakMap / WeakSet (weak references):

    • Keys must be objects; entries vanish automatically once the key is otherwise unreachable.

    • Not iterable and have no size (you can't enumerate something the GC may reclaim at any time).

  • Why weak for memory management:

    • Ideal for caching or attaching private metadata to objects you don't own (e.g. DOM nodes): when the object dies, its cache entry is cleaned up automatically.

    • With a regular Map, that entry would pin the object in memory forever.

Q60.
What are the trade-offs of using a Map versus a plain Object for storing key-value pairs?

Mid

Use a Map when you need keys of any type, frequent additions/removals, ordered iteration, or a reliable size; use a plain Object for simple, fixed-shape records and JSON interchange.

  • Map advantages:

    • Keys can be any value (objects, functions), not just strings/symbols.

    • Maintains insertion order and is directly iterable (for...of, .entries()).

    • size is O(1); optimized for frequent add/delete.

    • No prototype keys, so no risk of collision with inherited names like toString.

  • Object advantages:

    • Concise literal syntax and works natively with JSON.stringify.

    • Familiar property access and destructuring; good for known, static shapes.

  • Watch-outs:

    • Object keys are coerced to strings and inherit prototype props (use Object.create(null) to avoid that).

    • Map doesn't serialize to JSON automatically.

Q61.
What are the trade-offs between Throttling and Debouncing? When would you use one over the other for a search input vs. a window resize event?

Mid

Both limit how often a function runs, but debouncing waits until activity stops before firing once, while throttling fires at a steady maximum rate during continuous activity. Debounce a search input; throttle a resize/scroll handler.

  • Debounce:

    • Resets a timer on every call and runs only after a quiet period.

    • Good when you only care about the final state: search-as-you-type fires one request after the user stops typing.

  • Throttle:

    • Guarantees the function runs at most once per interval, regardless of how many events fire.

    • Good when you want regular updates during the action: resize or scroll handlers that should refresh layout smoothly without running on every pixel.

  • Choosing between them:

    • Search input: debounce, because you don't want a request per keystroke, only after typing settles.

    • Window resize: throttle, because you want periodic recalculation while resizing, not just one at the end.

Q62.
Explain the concept of 'Tree Shaking' and how static import/export statements enable it.

Mid

Tree shaking is the elimination of unused ("dead") exports during bundling. It works because ES Modules are static: imports and exports are declared at the top level and analyzed without running code, so a bundler can prove which exports are never used and drop them.

  • What it does: Removes exports that no module imports, shrinking the final bundle.

  • Why static import/export enable it:

    • Bindings are resolvable at compile time, so the dependency graph is known before execution.

    • Contrast with CommonJS require(), which can be dynamic/conditional, making usage undecidable statically.

  • What can defeat it:

    • Modules with side effects (mark them via sideEffects in package.json).

    • Dynamic access or re-exporting everything can prevent safe removal.

javascript

// utils.js export function used() {} export function unused() {} // dropped if never imported // app.js import { used } from './utils.js'; used();

Q63.
What are Generator functions, and how do they differ from standard functions in terms of execution control?

Mid

Generator functions (function*) can pause and resume execution: each yield suspends the function and hands a value back to the caller, who decides when to continue. Unlike a normal function that runs to completion in one go, a generator runs incrementally and is driven by its caller.

  • How they execute:

    • Calling a generator returns an iterator object; the body doesn't run yet.

    • Each .next() runs until the next yield, then pauses, preserving local state.

    • You can pass a value back in via .next(value), making it two-way communication.

  • How they differ from standard functions:

    • Standard functions run to completion and return once; generators can yield many times.

    • They retain state across pauses without closures or external variables.

  • Use cases: Lazy/infinite sequences, custom iterables (Symbol.iterator), and historically the basis for async flow before async/await.

javascript

function* idGen() { let id = 1; while (true) yield id++; // pauses here each call } const g = idGen(); g.next().value; // 1 g.next().value; // 2

Q64.
What is 'Strict Mode' (use strict) and what specific errors does it prevent?

Mid

Strict mode is an opt-in restricted variant of JavaScript, enabled with the "use strict" directive, that turns silent mistakes into thrown errors and disables error-prone or unsafe features.

  • How to enable it: Put "use strict"; at the top of a script or a function body. ES modules and class bodies are strict automatically.

  • Errors and behaviors it prevents:

    • Accidental globals: assigning to an undeclared variable throws instead of creating a global.

    • Silent assignment failures throw: writing to read-only or non-writable properties, getters-only, or non-extensible objects.

    • Duplicate parameter names are a syntax error.

    • this is undefined in a plain function call instead of defaulting to the global object, preventing accidental global mutation.

    • Deleting variables, functions, or non-configurable properties throws.

    • Reserved words like implements and interface are protected for future use.

  • Why it matters: It surfaces bugs early and enables engine optimizations, which is why modules adopt it by default.

Q65.
What are private class fields (using the # prefix), and how do they differ from the convention of using underscores?

Mid

Private class fields, prefixed with #, are true hard-private members enforced by the language: they are only accessible inside the class body, unlike the underscore convention which is merely a naming hint that anyone can ignore.

  • The underscore convention (_name):

    • Just a social agreement: the property is fully public and accessible/writable from outside.

    • Shows up in Object.keys(), for...in, and JSON serialization.

  • Private fields (#name):

    • Enforced by the engine: accessing #x outside the class is a syntax error, not a runtime lookup.

    • Not enumerable, not in Object.keys(), and invisible to JSON.

    • Must be declared in the class body; can't be added dynamically.

    • Enables a true brand check: #x in obj tests whether an instance belongs to the class.

  • Key difference: # gives real encapsulation guaranteed by the runtime; _ gives only documentation.

javascript

class Counter { #count = 0; // truly private increment() { this.#count++; } get value() { return this.#count; } } const c = new Counter(); c.increment(); console.log(c.value); // 1 // console.log(c.#count); // SyntaxError

Q66.
What is Object.groupBy(), and how does it differ conceptually from using reduce for grouping?

Mid

Object.groupBy() is a built-in that groups an iterable's items into a plain object keyed by the return value of a callback. It is a declarative, purpose-built replacement for the boilerplate you'd otherwise write with reduce.

  • What it does:

    • Calls the callback per element, uses the returned value as a key, and pushes the element into an array under that key.

    • Returns an object with null prototype (no inherited keys); Map.groupBy() exists for non-string keys.

  • Conceptual difference from reduce:

    • reduce is a general-purpose fold: you manually init the accumulator, check if a key exists, create the array, and push, which is verbose and error-prone.

    • Object.groupBy() is intent-revealing: one callback that just answers "which group?", with grouping mechanics handled internally.

    • It's specialized (only grouping), whereas reduce can compute anything (sums, lookups, etc.).

javascript

const nums = [1, 2, 3, 4, 5]; // Declarative Object.groupBy(nums, n => n % 2 ? 'odd' : 'even'); // { odd: [1,3,5], even: [2,4] } // Equivalent with reduce (more boilerplate) nums.reduce((acc, n) => { const k = n % 2 ? 'odd' : 'even'; (acc[k] ||= []).push(n); return acc; }, {});

Q67.
Compare localStorage, sessionStorage, and Cookies. What are the security and storage-limit trade-offs of each?

Mid

All three persist client-side data, but they differ in lifetime, capacity, and whether they're sent to the server: localStorage persists indefinitely, sessionStorage lasts for one tab session, and cookies are small and travel with every HTTP request.

  • localStorage:

    • ~5-10MB, persists until explicitly cleared, scoped per origin.

    • Not sent to the server; JS-only access.

    • Security: readable by any script on the origin, so vulnerable to XSS, never store tokens or secrets here naively.

  • sessionStorage:

    • ~5MB, cleared when the tab closes; not shared across tabs.

    • Same XSS exposure as localStorage; good for transient per-tab state.

  • Cookies:

    • Tiny (~4KB each) and automatically attached to every request to the domain, adding bandwidth overhead.

    • Can be hardened: HttpOnly hides them from JS (blocks XSS theft), Secure restricts to HTTPS, SameSite mitigates CSRF.

    • Best for auth/session tokens precisely because of HttpOnly.

  • Trade-off summary: Need server to see it and security: cookies. Need larger client-only storage: localStorage/sessionStorage, but guard against XSS.

Q68.
Explain the role of an AbortController and how it is used to cancel a fetch request or remove multiple event listeners.

Mid

An AbortController is a generic cancellation mechanism: it exposes a signal you pass to async APIs and an abort() method that, when called, signals all consumers of that signal to stop.

  • The two pieces:

    • controller.signal: an AbortSignal object you hand to APIs that support cancellation.

    • controller.abort(): fires the signal's abort event and sets signal.aborted to true.

  • Cancelling fetch:

    • Pass { signal } to fetch; calling abort() rejects the promise with a DOMException named AbortError.

    • Common for timeouts and cancelling stale requests (e.g. type-ahead search).

  • Removing many listeners at once: Pass { signal } as an option to addEventListener; one abort() detaches every listener registered with that signal, no need to keep references for removeEventListener.

  • One signal can be reused across multiple operations, so a single abort() cleans up an entire group at once.

javascript

const controller = new AbortController(); const { signal } = controller; fetch('/data', { signal }) .catch(err => { if (err.name === 'AbortError') console.log('cancelled'); }); window.addEventListener('resize', onResize, { signal }); window.addEventListener('scroll', onScroll, { signal }); // Cancels the fetch AND removes both listeners: controller.abort();

Q69.
What is the difference between a Web Worker and a Service Worker, and when would you use one over the other?

Mid

Both run scripts off the main thread, but a Web Worker offloads CPU-heavy computation tied to a page, while a Service Worker is a network proxy that lives independently of any page to enable caching, offline support, and push notifications.

  • Web Worker:

    • A background thread for parallel computation: keeps the UI responsive during heavy work.

    • Communicates via postMessage; no DOM access; lives only while its page does.

  • Service Worker:

    • Sits between the app and network, intercepting fetch events to serve cached responses.

    • Event-driven and persistent: can wake up without an open page (push, background sync), but can't run continuous CPU work.

    • Requires HTTPS and is the foundation of PWAs.

  • When to choose:

    • Heavy parsing/calculation: Web Worker.

    • Caching, offline, intercepting requests, push: Service Worker.

Q70.
Explain the JavaScript event loop and the relationship between the call stack, Web APIs, the callback queue, and the microtask queue.

Mid

The event loop coordinates a single-threaded call stack with asynchronous work: synchronous code runs on the call stack, the browser's Web APIs handle async operations off-thread, completed callbacks land in queues, and the loop pushes them onto the stack only when it's empty.

  • Call stack: Where function frames execute, one at a time (LIFO). JS only does one thing at a moment.

  • Web APIs: Browser-provided features (timers, fetch, DOM events) that run outside the engine and report back when done.

  • Callback (task) queue: Holds macrotask callbacks like timer and event handlers, processed one per loop turn.

  • Microtask queue: Holds promise callbacks; fully drained after each task and before rendering.

  • The loop's rule: When the stack is empty: drain all microtasks, then take one macrotask, repeat.

Q71.
Why does setTimeout with 0 milliseconds not necessarily execute in 0 milliseconds?

Mid

setTimeout(fn, 0) sets the minimum delay before the callback becomes eligible, not the actual run time: it's queued as a macrotask and can only run after the current code finishes and all microtasks drain.

  • It's a minimum, not a guarantee: The callback waits until the call stack is empty; any long-running synchronous code delays it.

  • Microtasks run first: Pending promise callbacks are processed before the timer callback, pushing it back further.

  • Browser clamping:

    • The HTML spec clamps nested timers to a minimum of about 4ms after several levels.

    • Background/inactive tabs may throttle timers further to save resources.

Q72.
How does the JavaScript event loop handle a single thread while performing non-blocking I/O?

Mid

JavaScript itself is single-threaded, but it delegates I/O to the host environment (browser Web APIs or Node's libuv), which performs the waiting off-thread; the event loop then queues the completion callback so the single thread is never blocked idling.

  • Delegation, not waiting: When you call fetch or read a file, the engine hands it to the platform and immediately continues executing other code.

  • Callbacks bridge back: When the I/O finishes, its callback (or resolved promise) is placed in a queue rather than interrupting running code.

  • The loop schedules execution: Once the call stack is clear, the event loop pulls queued callbacks onto it, so concurrency is achieved without extra JS threads.

  • The caveat: This only works for asynchronous I/O; a synchronous/CPU-heavy operation still blocks the single thread.

Q73.
Explain the new Set methods in ES2025 (union, intersection, difference) and when you'd use them.

Mid
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q74.
What is the difference between Lexical Scope and Dynamic Scope?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q75.
Why does hoisting happen in JavaScript? Explain how the engine handles function declarations vs. variable declarations during the creation phase.

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q76.
Why does [] + [] result in an empty string?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q77.
When would you use Object.create(null) instead of a standard object literal?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q78.
Why does a Promise resolve before a setTimeout(0)?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q79.
What happens if a Promise is never resolved or rejected, and how does the engine handle this hanging state?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q80.
What is the difference between the DOM, the Virtual DOM, and the Shadow DOM?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q81.
What is structuredClone and when would you use it over JSON.parse(JSON.stringify())?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q82.
Explain the difference between ES Modules (import/export) and CommonJS (require/module.exports). Why did the industry move toward ESM?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q83.
Explain the difference between Short Polling, Long Polling, and WebSockets. When is each appropriate?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q84.
What is the iterable and iterator protocol in JavaScript?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q85.
Explain the Critical Rendering Path. How does JavaScript execution affect the parsing of HTML and CSS?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q86.
How does the Event Loop decide when to perform a UI re-render in the browser?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q87.
What is the difference between a reflow and a repaint? Which one is more expensive, and how can you minimize them?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q88.
Explain the difference between microtasks and macrotasks. Which has priority, and why does it matter for UI responsiveness?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q89.
What happens to the Call Stack when an await keyword is encountered in an async function?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q90.
What happens if a microtask recursively schedules another microtask, and what is starvation?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q91.
What is a 'Memory Leak' in JavaScript, and how can a closure or an event listener cause one?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q92.
How does JavaScript's garbage collection (mark-and-sweep) work?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q93.
What are deoptimizations in a JS engine, and what kind of code patterns usually trigger them?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q94.
What is a JavaScript Proxy, and what are some practical use cases for it (e.g., validation, logging)?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q95.
What are the new features in ES2025/ES2026 that you find most impactful?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.

Q96.
What is Just-In-Time (JIT) compilation in engines like V8?

Senior
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Nemo enim ipsam voluptatem quia voluptas sit aspernatur aut odit aut fugit, sed quia consequuntur magni dolores eos qui ratione voluptatem sequi nesciunt. Neque porro quisquam est, qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit, sed quia non numquam eius modi tempora incidunt ut labore et dolore magnam aliquam quaerat voluptatem.