Skip to the chapter
←JavaScriptGGroundworkJSJavaScript
JavaScript/Beginner/★
41 / 41 written chapters
/

The cover
  1. B1Setup & mental model
  2. B2Execution context
  3. B3var, let & const
  4. B4Scope
  5. B5Single thread
  6. B6In the browser
  7. B7Types & values
  8. B8Strings & Math
  9. B9Operators & flow
  10. B10Functions
  11. B11Objects & arrays
  12. B12this
  13. B13Closures
  14. B14DOM & events
  15. B15Callbacks & promises
  16. B16Errors & tools
  17. B17Guided project
  18. ★Cheat page
  1. I1Scope & functions, properly
  2. I2Objects deeply
  3. I3Prototypes & OOP
  4. I4Async, properly
  5. I5Modules & tooling
  6. I6Regex & dates
  7. I7Error handling
  8. I8Real-time connections
  9. I9Offline & storage
  10. I10Browser APIs
  11. I11Modern JS
  12. ★Cheat page
  1. A1Engine & memory
  2. A2Advanced async
  3. A3Metaprogramming
  4. A4Types & data
  5. A5Patterns & architecture
  6. A6Performance
  7. A7Security
  8. A8Ecosystem
  9. A9Testing
  10. A10Observability
  11. A11Interview bank
  12. A12Build it yourself
  13. ★Cheat page

JS★ · Part 1 · Beginner

The cheat page

Not another lesson — the night-before-the-interview skim of the other 38.

6 min read9 sections0 exercises
41 of 41

In this chapter

  • Coercion & comparison, at a glance
  • Type checks, at a glance
  • Scope, closures, this — the 30-second version
  • Array & object methods — mutates, or doesn't?
  • Async ordering — the one rule

and 4 more

about 6 min
09On this page
  1. Coercion & comparison, at a glance
  2. Type checks, at a glance
  3. Scope, closures, this — the 30-second version
  4. Array & object methods — mutates, or doesn't?
  5. Async ordering — the one rule
  6. Classes & prototypes — the 30-second version
  7. "Implement X" — the classic from-scratch asks
  8. The gotchas grid
  9. How to actually use this page

Nothing new gets taught here. Every row links back to the chapter that actually explains the why — this page exists purely so the what is skimmable in one pass, table after table, instead of re-reading three levels of chapters the night before something matters.

Coercion & comparison, at a glance

null == undefined 0 == false "0" == 0 [] == false NaN == NaN null == 0 "" == "0"

Full coercion table and the non-transitivity proof: Operators & flow.

console.log(0.1 + 0.2);            // what happens?
console.log(0.1 + 0.2 === 0.3);    // what happens?

0.30000000000000004, then false. Not a JS bug — IEEE 754 floats can't represent 0.1 or 0.2 exactly in binary, in any language that uses them. Never compare floats with ===; compare Math.abs(a - b) < Number.EPSILON instead, or work in integers (cents, not dollars) where exactness actually matters.

===Object.is()
NaN vs NaNfalsetrue
0 vs -0truefalse

Type checks, at a glance

ExpressionResult
typeof null"object" — a 25-year-old bug, permanent for compatibility
typeof undefined"undefined"
typeof NaN"number" — NaN IS a number, just not a useful one
typeof []"object" — use Array.isArray()
typeof function(){}, typeof class{}both "function"
typeof Symbol(), typeof 10n"symbol", "bigint"
[1,2] === [1,2]false — different references, same shape

Full type system: Types & values. Reference vs primitive: same chapter.

Scope, closures, this — the 30-second version

RankRuleTrigger
1newnew Fn()
2explicit.call() / .apply() / .bind()
3implicitobj.method()
4defaultbare fn() → undefined in strict mode

Arrows never bind their own this — they read it from where they're written. The four rules and how this gets lost: The this keyword. The proof that new beats bind: Scope & functions, properly. All five real closure uses: Closures.

Array & object methods — mutates, or doesn't?

Mutates the originalReturns a new one, leaves the original alone
push, pop, shift, unshiftslice, concat, map, filter
splice, sort, reverseflat, flatMap, spread [...arr]
Object.assign(target, …){ ...obj }, structuredClone(obj)
⚠ .map() skips holes in a sparse array Array(3).map(x => 1) is still [ <3 empty items> ], not [1, 1, 1] — Array(3) creates empty slots, not undefined values, and map/forEach/filter all skip holes entirely. Array.from({ length: 3 }) or Array(3).fill() first if you actually want real, mappable elements.

Full method tables: Objects & arrays (first half) and Objects deeply.

Async ordering — the one rule

Sync code runs first, always. Then the whole microtask queue drains (every .then(), every await continuation) — completely — before a single macrotask (setTimeout, a click) gets a turn.

CombinatorSettles when
Promise.allall fulfill, or the first rejection
Promise.allSettledeverything has settled — never rejects itself
Promise.racethe first to settle, win or lose
Promise.anythe first to fulfill — ignores earlier rejections

Full step-through demos: Setup & mental model. Sequential-vs-parallel await, retries, AbortController: Async, properly.

Classes & prototypes — the 30-second version

obj.hasOwnProperty("x")     // true only for OWN properties, never inherited ones
Object.getPrototypeOf(obj)  // the real link an instance follows
Fn.prototype                // what becomes that link for every "new Fn()"
class B extends A {
  constructor() { super(); }   // MUST run before "this" is usable
}

The 4 steps new actually performs, and #private being parser-enforced: Prototypes & OOP.

"Implement X" — the classic from-scratch asks

AskTaught in
debounce / throttleClosures
curry / partial application / composeScope & functions, properly, Patterns & architecture
memoize / onceClosures
your own EventEmitter / pub-subPatterns & architecture
deep clonestructuredClone() — Objects deeply
a concurrency-limited task queueAdvanced async
a custom iterable (Symbol.iterator)Metaprogramming
new from scratchPrototypes & OOP

The gotchas grid

{} + [] → 0 (statement position) [] + {} → "[object Object]" 1 < 2 < 3 → true 3 > 2 > 1 → false var in a loop + setTimeout → same value every time forEach can't be broken out of indexOf(NaN) is always -1 a bound "this" loses to new

Every one of these is explained, not just listed, in Operators & flow, Scope & functions, properly, and Objects & arrays.

Dry run: two gotchas from the grid above, traced

ExpressionHow the parser reads itResult
{} + [] (as its own statement){} opens as an empty block statement, not an object literal; +[] is then a unary plus on an array, which coerces to 00
({} + []) or console.log({} + []) (expression position){} is now read as an object literal, so + is the binary operator; both sides stringify and concatenate"[object Object]"
[] + {}an array can never start a block, so this is always binary + regardless of position"[object Object]"
1 < 2 < 3left-to-right: (1 < 2) is true, then true < 3 coerces true to 1, and 1 < 3true
3 > 2 > 1left-to-right: (3 > 2) is true, then true > 1 coerces true to 1, and 1 > 1false

Same {} + [], two different answers, purely from where it sits in the code — the exact trap the "(statement position)" note on the chip above is flagging. Chained comparisons resolve the same way: pairwise, left to right, each result coerced to a number before feeding the next comparison — never a genuine three-way check.

How to actually use this page

  1. Don't start here. Every row above assumes the chapter behind its link has already been read once — this page is recall, not first exposure.
  2. Cover the "Result" column with your hand and predict it before checking. Being surprised by a row you've "read" before is the actual signal it needs another real pass, not just a re-skim.
  3. For the gotchas grid specifically: cover the chip past the arrow and say the reason out loud, not just the result — "why" is what an interviewer is actually asking for.
  4. If a whole section reads unfamiliar rather than "oh right" — go read that chapter properly. This page is a mirror, not a shortcut past the mirror.
Before you move on
  • Predict a chip from the gotchas grid before checking the arrow, and explain the reason, not just the result.
  • Explain why {} + [] can equal both 0 and "[object Object]" depending on where it sits in code.
  • Say which of === and Object.is() treats NaN as equal to itself, and which treats 0 and -0 as different.
  • Name which array methods mutate their target, without checking the table.
  • Explain why 0.1 + 0.2 !== 0.3, using IEEE 754 floats, without opening the Operators & flow chapter.
★

Finished reading?

0 of 41 chapters read in this series

→Next stop

  1. A12Previous · A12Build it yourself
  2. ★you are here
  3. The endBack to the coverAll chapters

01On this page

9 sections · 0%

  1. 01Coercion & comparison, at a glance
  2. 02Type checks, at a glance
  3. 03Scope, closures, this — the 30-second version
  4. 04Array & object methods — mutates, or doesn't?
  5. 05Async ordering — the one rule
  6. 06Classes & prototypes — the 30-second version
  7. 07"Implement X" — the classic from-scratch asks
  8. 08The gotchas grid
  9. 09How to actually use this page

[] chapters · t top