JavaScript
## When to Use
User needs JavaScript expertise — from core language features to modern patterns. Agent handles async/await, closures, module systems, and ES2023+ features.
## Quick Reference
| Topic | File |
|-------|------|
| Async patterns | `async.md` |
| Type coercion rules | `coercion.md` |
| Array and object methods | `collections.md` |
| Modern ES features | `modern.md` |
## 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 Traps
- 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
标签
skill
ai