javascript

Verified·Scanned 2/18/2026

This skill is a concise JavaScript guide covering equality traps, this binding, closures, array mutation, async pitfalls, numeric and iteration pitfalls. No security-relevant behaviors detected.

from clawhub.ai·v4dc9d82·2.9 KB·0 installs
Scanned from 1.0.0 at 4dc9d82 · Transparency log ↗
$ vett add clawhub.ai/ivangdavila/javascript

Equality Traps

  • == coerces: "0" == false is true — use === always
  • NaN !== NaN — use Number.isNaN(), not === NaN
  • typeof null === "object" — check === null explicitly
  • Objects compare by reference — {} === {} is false

this Binding

  • Regular functions: this depends on call site — lost in callbacks
  • Arrow functions: this from lexical scope — use for callbacks
  • setTimeout(obj.method) loses this — use arrow or .bind()
  • Event handlers: this is element in regular function, undefined in arrow (if no outer this)

Closure Gotchas

  • Loop variable captured by reference — let in loop or IIFE to capture value
  • var hoisted to function scope — creates single binding shared across iterations
  • Returning function from loop: all share same variable — use let per iteration

Array Mutation

  • sort(), reverse(), splice() mutate original — use toSorted(), toReversed(), toSpliced() (ES2023)
  • push(), pop(), shift(), unshift() mutate — spread [...arr, item] for immutable
  • delete arr[i] leaves hole — use splice(i, 1) to remove and reindex
  • Spread and Object.assign are shallow — nested objects still reference original

Async Pitfalls

  • Forgetting await returns Promise, not value — easy to miss without TypeScript
  • forEach doesn't await — use for...of for sequential async
  • Promise.all fails fast — one rejection rejects all, use Promise.allSettled if need all results
  • Unhandled rejection crashes in Node — always .catch() or try/catch with await

Numbers

  • 0.1 + 0.2 !== 0.3 — floating point, use integer cents or toFixed() for display
  • parseInt("08") works now — but parseInt("0x10") is 16, watch prefixes
  • Number("") is 0, Number(null) is 0 — but Number(undefined) is NaN
  • Large integers lose precision over 2^53 — use BigInt for big numbers

Iteration

  • for...in iterates keys (including inherited) — use for...of for values
  • for...of on objects fails — objects aren't iterable, use Object.entries()
  • Object.keys() skips non-enumerable — Reflect.ownKeys() gets all including symbols

Implicit Coercion

  • [] + [] is "" — arrays coerce to strings
  • [] + {} is "[object Object]" — object toString
  • {} + [] is 0 in console — {} parsed as block, not object
  • "5" - 1 is 4, "5" + 1 is "51" — minus coerces, plus concatenates

Strict Mode

  • "use strict" at top of file or function — catches silent errors
  • Implicit globals throw in strict — x = 5 without declaration fails
  • this is undefined in strict functions — not global object
  • Duplicate parameters and with forbidden — good riddance