Advanced⏱️ 12 min📘 Topic 13 of 13

🧬 Advanced JavaScript — Prototypes, this, Hoisting & The Event Loop

Senior-level JavaScript concepts: prototype chain, `this` binding, hoisting, event loop, currying, debounce vs throttle. Built to crack the toughest interview rounds.

These are the topics that separate junior from senior JavaScript developers — and they're guaranteed to come up in mid/senior interviews.

🧬 Prototype chain

Every object has a hidden link (__proto__) to another object. Property lookups walk up that chain until found or hitting null.

const arr = [];
arr.__proto__ === Array.prototype;            // true
Array.prototype.__proto__ === Object.prototype;// true
Object.prototype.__proto__ === null;           // top

🎯 `this` — the 5 rules

  1. Method callobj.fn() → this is obj
  2. Plain callfn() → undefined (strict) or window
  3. newnew Fn() → the new instance
  4. call/apply/bind — explicit
  5. Arrow — inherits from enclosing scope

🔁 Event loop deep cut

One call stack. A microtask queue (Promises, queueMicrotask). A macrotask queue (setTimeout, I/O, UI events). After every macrotask, the engine drains all microtasks before painting or processing the next macrotask.

🍛 Currying

const add = a => b => c => a + b + c;
add(1)(2)(3); // 6

⏱️ Debounce vs Throttle

  • Debounce: wait until user stops (search input)
  • Throttle: at most once per interval (scroll handler)

💻 Code Examples

Debounce — search input

function debounce(fn, ms) {
  let t;
  return (...args) => {
    clearTimeout(t);
    t = setTimeout(() => fn(...args), ms);
  };
}
const onSearch = debounce(query => fetch(`/search?q=${query}`), 300);
Output:
fetch only fires 300ms after typing stops.

this binding gotcha

const user = {
  name: 'Sam',
  greet() { return `Hi ${this.name}`; }
};
const g = user.greet;
user.greet(); // 'Hi Sam'
g();          // 'Hi undefined' — lost this
Output:
Detaching a method loses `this`. Fix with .bind(user) or arrow wrapping.

Prototype chain in action

function Animal(name) { this.name = name; }
Animal.prototype.speak = function() {
  return `${this.name} makes a sound`;
};
const dog = new Animal('Rex');
dog.speak(); // 'Rex makes a sound'
Output:
speak isn't on dog — it's found via the prototype chain.

⚠️ Common Mistakes

  • Confusing prototype with __proto__ — Foo.prototype is what instances inherit; obj.__proto__ is the actual link.
  • Using arrow functions for methods that need `this` bound to the object.
  • Throttling when you meant to debounce (or vice versa).
  • Assuming setTimeout(fn, 0) runs immediately — it waits for the current call stack and microtasks to clear.

🎯 Interview Questions

Real questions asked at top product and service-based companies.

Q1.Explain the prototype chain.Advanced
Every object has a [[Prototype]] reference to another object. When you access a property, JS searches the object, then its prototype, then that prototype's prototype, up to Object.prototype, whose prototype is null. That walk is the prototype chain.
Q2.What is `this` and how is it determined?Advanced
`this` is the execution context of a function call. Rules: method call → object; plain call → undefined/window; new → new instance; call/apply/bind → explicit value; arrow → lexically inherited.
Q3.Explain the event loop.Advanced
JS runs on a single call stack. Async operations are handled by host APIs and put their callbacks in microtask or macrotask queues. The loop: run stack to empty → drain microtasks → take next macrotask → repeat. Render happens between macrotasks.
Q4.Difference between debounce and throttle?Advanced
Debounce delays execution until X ms after the LAST call — good for search-as-you-type. Throttle ensures at most one execution per X ms — good for scroll, resize, mousemove.
Q5.What is currying?Advanced
Transforming a function of N arguments into N nested functions of 1 argument each: `f(a, b, c)` → `f(a)(b)(c)`. Enables partial application and cleaner composition.
Q6.What's the output? `setTimeout(()=>console.log(1),0); Promise.resolve().then(()=>console.log(2)); console.log(3);`Advanced
3, 2, 1. Synchronous logs first, then all microtasks (Promises), then macrotasks (setTimeout).

🧠 Quick Summary

  • Prototypes power JS inheritance — classes are sugar over them.
  • 5 `this` rules: method, plain, new, call/bind, arrow.
  • Event loop drains microtasks fully between macrotasks.
  • Debounce = wait until quiet; throttle = rate-limit.
  • Currying transforms multi-arg functions into chained single-arg ones.