RoadmapDay 76 / 80
JavaScript CoreMonth 4 · Week 16

Day 76: Review JS Engine Edge Cases & Tricky Concepts

Drill the specific edge cases that separate a confident answer from a shaky one across execution context, closures, the event loop, and prototypes.

Mark this day complete

Study

Concepts

The recurring "gotcha" list worth memorizing precisely

Revisit these exact edge cases and be able to explain WHY, not just WHAT: `typeof null === 'object'` (a decades-old engine bug preserved for compatibility); `[] + []` is `''` but `[] + {}` is `'[object Object]'` (both operands coerce to strings via valueOf/toString, and array-to-string joins with commas on an empty array producing an empty string); `NaN !== NaN` (per IEEE 754, NaN is defined to never equal itself — use `Number.isNaN` or `Object.is` to check for it correctly); closures capturing a `var` loop variable by reference share ONE binding (Day 2) while `let` creates one binding per iteration.

Also drill: `async function` always wraps its return value in a Promise even if you return a plain value; a `.then()` handler that returns nothing resolves the chain with `undefined`; and `Promise.all` rejects as soon as ANY promise rejects (short-circuits) while `Promise.allSettled` always waits for every promise and never rejects itself — a very commonly confused pair.

See It

Visualizations

Visualization

Promise.all vs Promise.allSettled vs Promise.race vs Promise.any

 Short-circuits on first...Resolves/rejects with...
Promise.allfirst REJECTIONarray of values, or the first rejection reason
Promise.allSettlednever short-circuitsarray of {status, value|reason} for every input
Promise.racefirst SETTLEMENT (resolve OR reject)that single result
Promise.anyfirst FULFILLMENTthat value, or an AggregateError if ALL reject

Build It

Code Examples

A rapid-fire self-check set — predict each before running

js
console.log(typeof null);              // 'object' (legacy engine quirk)
console.log([] + []);                   // ''
console.log([] + {});                   // '[object Object]'
console.log(NaN === NaN);               // false
console.log(Number.isNaN(NaN));         // true
console.log(0.1 + 0.2 === 0.3);         // false (floating point precision)

async function f() { return 42; }
f().then(console.log);                  // 42 — auto-wrapped in a Promise

Promise.all([Promise.resolve(1), Promise.reject('err'), Promise.resolve(3)])
  .catch((e) => console.log('all rejected with:', e)); // 'err' — short-circuits

Promise.allSettled([Promise.resolve(1), Promise.reject('err')])
  .then((r) => console.log(r));
// [{status:'fulfilled', value:1}, {status:'rejected', reason:'err'}]

Remember

Key Takeaways

  • typeof null, NaN !== NaN, and array/object-to-string coercion quirks are classic interview rapid-fire questions — know the WHY behind each.
  • An async function always returns a Promise, even for a plain returned value — a very common source of confusion for less experienced candidates.
  • Promise.all short-circuits on first rejection; Promise.allSettled never does and never itself rejects — know exactly when to use each.
  • Floating point precision (0.1 + 0.2 !== 0.3) is a real, not just trivia, concern in any code comparing computed decimal values.
  • This day is deliberately review, not new material — the goal is speed and confidence, not first-time learning.

Do It

Practice

  1. 1Run the full rapid-fire snippet above cold, predicting every line before executing, and note any you got wrong.
  2. 2Write your own 5-question rapid-fire quiz covering closures, this, and prototypes (Week 1-2) and answer it cold 24 hours later.
  3. 3Explain Promise.any vs Promise.race out loud in one sentence each, without looking at notes.