Advanced Core


51) What is a closure, and what’s actually being “closed over”?

Answer: A closure is when a function retains access to variables from its lexical scope even after the outer function has returned. It “closes over” bindings (the live variables), not just snapshots of values.


52) Why are closures useful in real systems?

Answer: They enable encapsulation (private state), function factories , memoization, and stable callbacks without global variables—common in React handlers, middleware, event listeners, and libraries.


53) Explain the classic loop + closure problem with var.

Answer: var is function-scoped, so all callbacks share the same i binding, which ends at the final value.

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0); // 3,3,3
}

54) How does let fix that closure issue?

Answer: let creates a new binding per iteration , so each callback captures its own iteration’s i.


55) How can you fix the closure issue without let?

Answer: Use an IIFE (or function factory) to create a new scope per iteration.


56) What is the module pattern and why does it rely on closures?

Answer: It uses an IIFE (or module scope) to create private state and expose a public API.


57) What is garbage collection’s relationship to closures?

Answer: Captured variables stay alive as long as any closure referencing them is reachable. This can cause memory retention if closures keep large objects unintentionally.


58) What’s a practical example of a closure causing a memory leak?

Answer: Adding event listeners with closures that capture big data, then never removing listeners—so the captured data can’t be GC’d.


59) What is the prototype chain?

Answer: Objects can delegate property lookups to another object via [[Prototype]]. If a property isn’t found on the object, JS walks up the chain until null.


60) How does property lookup work under the hood?

Answer: obj.x checks:

  1. own properties of obj

  2. then obj.[[Prototype]]

  3. continues up until found or prototype is null → undefined


61) What’s the difference between __proto__ and prototype?

Answer:

  • __proto__ (accessor) refers to an object’s internal prototype (its parent).

  • prototype is a property on constructor functions , used as the prototype for objects created via new.


62) Why is __proto__ discouraged?

Answer: It’s legacy and can be slower/less safe. Prefer Object.getPrototypeOf() and Object.setPrototypeOf() (still use sparingly) or create with Object.create().


63) What does new do step-by-step?

Answer:

  1. Creates a new empty object

  2. Sets its [[Prototype]] to Constructor.prototype

  3. Calls constructor with this bound to the new object

  4. Returns the object unless constructor returns a non-primitive


64) What happens if a constructor returns an object explicitly?

Answer: That returned object becomes the result of new, overriding the normal this object.


65) What is prototypal inheritance (vs classical)?

Answer: Objects inherit directly from other objects (delegation), not from “classes” in the traditional sense. class syntax in JS is sugar over prototypes.


66) What’s the difference between Object.create(proto) and new C()?

Answer: Object.create(proto) creates an object with a specified prototype without running any constructor logic . new C() sets prototype and runs the constructor.


67) How does instanceof work?

Answer: It checks whether C.prototype exists somewhere in the object’s prototype chain.


68) When can instanceof fail unexpectedly?

Answer: Across realms (iframes) or when prototypes are altered. Also fails if objects come from different globals: arrFromIframe instanceof Array may be false.


69) What is this in JavaScript really?

Answer: this is determined by how a function is called , not where it’s defined (except arrow functions). It’s a runtime binding.


70) What are the main this binding rules?

Answer:

  1. new binding (new fn())

  2. explicit binding (call/apply/bind)

  3. implicit binding (obj.fn())

  4. default binding (global object or undefined in strict mode)


71) What does strict mode change for this?

Answer: In strict mode, default binding sets this to undefined instead of the global object—preventing accidental global mutation.


72) Why do methods lose this when passed as callbacks?

Answer: The call-site changes. obj.method passed to another function becomes a plain function call (method()), losing implicit binding.


73) Fix the lost-this issue in callbacks.

Answer: Bind it, wrap it, or use arrow function at call site.


74) What is bind, and why is it different from call/apply?

Answer: bind returns a new function with this (and optionally args) permanently bound. call/apply invoke immediately with a chosen this.


75) call vs apply—what’s the practical difference?

Answer: Only argument passing:

  • call(thisArg, a, b)

  • apply(thisArg, [a, b]) Use apply when args are already in an array.


76) What’s partial application with bind?

Answer: Pre-filling arguments:


77) Why don’t arrow functions have their own this?

Answer: Arrow functions capture this from the lexical environment (where they’re created). This makes them great for callbacks that should inherit surrounding this.


78) When is arrow function this a bad idea?

Answer: When you need dynamic this (methods meant to be called with different receivers). Arrow methods on prototypes are also memory-inefficient if created per instance.


79) What is the event loop in one “how it works” explanation?

Answer: JS runs on a single thread executing call stack tasks. The event loop pulls tasks from queues (macrotasks) and runs them when the stack is empty, while also draining microtasks at specific points.


80) What’s the difference between macrotasks and microtasks?

Answer:

  • Macrotasks: setTimeout, setInterval, DOM events, I/O callbacks

  • Microtasks: Promise.then/catch/finally, queueMicrotask, MutationObserver Microtasks run after the current stack but before the next macrotask.


81) Why do microtasks “win” over setTimeout(..., 0)?

Answer: Because after each macrotask completes, the engine drains the microtask queue fully before taking the next macrotask. So promise callbacks execute first.


82) Predict the output and explain:

Answer: 1, 4, 3, 2 Sync logs first, then microtasks (3), then macrotasks (2).


83) What is “starvation” in the event loop context?

Answer: If microtasks keep scheduling more microtasks indefinitely, the event loop may delay rendering and macrotasks, leading to UI freeze.


84) How does the browser rendering pipeline relate to the event loop?

Answer: Browsers typically render between tasks (after microtasks drain). If you block the main thread or keep microtasks busy, rendering can’t happen → jank.


85) Why is setTimeout not a precise timer?

Answer: It’s minimum delay , not exact. Actual execution depends on call stack, microtasks, clamping rules, background tab throttling, and CPU load.


86) What is “re-entrancy” and why does it matter in JS callbacks?

Answer: A function is re-entrant if it can be safely interrupted and called again before finishing. Async callbacks can re-enter logic unexpectedly, causing state bugs if not designed carefully.


87) What is the call stack and why do we get “Maximum call stack size exceeded”?

Answer: The call stack stores nested function calls. Deep recursion or circular calls can overflow it. Use iteration, tail recursion (not widely optimized), or trampolines.


88) What’s a “stack frame” in JS?

Answer: A record for a function call containing parameters, local variables, and return address. Each call pushes a frame; returning pops it.


89) Explain try/catch and async errors: why doesn’t try/catch catch promise errors?

Answer: try/catch catches synchronous exceptions in the current stack. Promise rejections happen asynchronously; you must await inside try/catch or attach .catch().


90) What’s the difference between throwing and rejecting?

Answer: throw creates a synchronous exception. reject (or throwing inside an async function) results in a promise rejection, handled via await + try/catch or .catch().


91) What is the arguments object and why is it considered legacy?

Answer: It’s an array-like object in non-arrow functions containing passed args. It’s less clear than rest parameters and has quirks (like aliasing in non-strict mode). Prefer (...args).


92) What is “shadowing” and why can it be a bug source?

Answer: Declaring a variable in an inner scope with the same name hides the outer one. It can cause logic errors when you think you’re updating the outer variable.


93) What’s the difference between a “method” and a “function” in JS?

Answer: A method is a function called as a property of an object (obj.fn()), which enables implicit this. Same function can be a method or plain function depending on call-site.


94) How does .toString()/.valueOf() affect coercion?

Answer: When converting objects to primitives, JS uses Symbol.toPrimitive if present, otherwise tries .valueOf() and .toString() depending on context (“number” vs “string” hint).


95) What is Symbol.toPrimitive and why would you implement it?

Answer: It customizes how an object converts to a primitive in operations like + or template strings—useful for domain objects (money, units) to avoid weird coercions.


96) What does Object.freeze() actually guarantee?

Answer: It prevents adding/removing/changing own properties (shallow). Nested objects remain mutable unless deep-frozen.


97) Why can mutating prototypes be dangerous in production?

Answer: It affects all objects sharing that prototype, can break third-party code, cause performance de-optimizations, and create security issues (prototype pollution).


98) What is prototype pollution?

Answer: A security vulnerability where attacker-controlled input modifies object prototypes (e.g., __proto__), potentially changing behavior across the app (like ({}).isAdmin === true).


99) What’s the difference between Map and plain objects for key-value storage?

Answer: Map supports non-string keys, preserves insertion order reliably, has predictable iteration, and avoids prototype keys collisions. Objects are better for structured records with known fields.


100) Why does this behave differently inside class methods when used as callbacks?

Answer: Class methods are just functions on the prototype. When passed as callbacks, call-site loses the instance receiver unless bound. Solutions: bind in constructor, use class fields arrow functions, or wrap at call site.

Last updated