# JavaScript rules

Follow these CodeWiki-derived rules when you work in this project.

- Do not assume this is safe: `sort()` mutates its array, and without a comparator it compares elements as strings.
  Why: The default order of the numeric array `[2, 10, 1]` isn't numeric ascending order.
  Source: [Array methods](https://codewiki.com/javascript/array-methods/)
- `slice()`, spread syntax, `concat()`, and copying array methods make shallow copies.
  Why: Mutating an element object afterward also changes that same object as observed through the old array.
  Source: [Array methods](https://codewiki.com/javascript/array-methods/)
- Omitting the `reduce()` initial value throws a `TypeError` when the array might be empty.
  Why: For a non-empty input, the first existing item becomes the accumulator and callbacks begin with the next existing item, which can also make accumulator types unstable.
  Source: [Array methods](https://codewiki.com/javascript/array-methods/)
- `filter(Boolean)` removes more than `null` and `undefined`: it also drops valid `0`, `false`, empty strings, and `NaN`.
  Why: Generated cleanup code can silently lose data this way.
  Source: [Array methods](https://codewiki.com/javascript/array-methods/)
- `forEach(async (item) => ...)` doesn't await the Promises returned by its callbacks.
  Why: Outer code continues first, and `forEach()` doesn't collect callback rejections.
  Source: [Array methods](https://codewiki.com/javascript/array-methods/)
- `new Array(3).fill({ pending: true })` stores one object reference in all three slots.
  Why: Updating one item makes all three appear to change.
  Source: [Array methods](https://codewiki.com/javascript/array-methods/)
- An object literal member such as `read: () => this.value` doesn't acquire `object` when invoked as `object.read()`.
  Why: The arrow ignores the receiver supplied by that call form and keeps resolving `this` outside the object literal.
  Source: [Arrow functions](https://codewiki.com/javascript/arrow-functions/)
- After `item => ({ id: item.id })` grows into a logged block such as `item => { log(item); { id: item.id }; }`, it returns `undefined`.
  Why: The braces select a block body, and the inner object-like text may parse as a labelled statement.
  Source: [Arrow functions](https://codewiki.com/javascript/arrow-functions/)
- `on('data', value => consume(value))` and a later `off('data', value => consume(value))` create two different functions.
  Why: Identical source text doesn't give the unregistering API the identity that was registered.
  Source: [Arrow functions](https://codewiki.com/javascript/arrow-functions/)
- Automated refactors often convert a constructor or a function that reads its own `arguments` into an arrow while leaving `new` calls and the original body intact.
  Why: The result may throw `TypeError` at the call site or silently read an enclosing function's `arguments`.
  Source: [Arrow functions](https://codewiki.com/javascript/arrow-functions/)
- An arrow-function field is an own property on every instance.
  Why: Overrides, spies, or patches that depend on `Class.prototype.method` may not intercept it, and every new instance gets a new function identity.
  Source: [Arrow functions](https://codewiki.com/javascript/arrow-functions/)
- `Parent.call(this, value)` is only an ordinary call and doesn't preserve full construction semantics.
  Why: JavaScript classes can't be called without `new`, and `new.target` differs from a genuine construction path.
  Source: [call, apply and bind](https://codewiki.com/javascript/call-apply-bind/)
- An array-like object isn't necessarily iterable, and an iterable doesn't necessarily have `length`.
  Why: Automatically changing `fn.apply(receiver, input)` to `fn.call(receiver, ...input)` can throw or change the argument count.
  Source: [call, apply and bind](https://codewiki.com/javascript/call-apply-bind/)
- `on(this.handle.bind(this))` and a later `off(this.handle.bind(this))` produce two functions.
  Why: Cleanup can't match the registration and may keep the bound function and its receiver reachable indefinitely.
  Source: [call, apply and bind](https://codewiki.com/javascript/call-apply-bind/)
- Do not assume this is safe: binding an already bound function with `bind(other, extra)` ignores `other`, but appends `extra` after existing leading arguments.
  Why: An arrow also ignores the new `thisArg`, although it still receives prefilled arguments.
  Source: [call, apply and bind](https://codewiki.com/javascript/call-apply-bind/)
- A non-strict function substitutes `globalThis` for a `null` or `undefined` receiver, turning missing context into silent global reads or writes.
  Why: Modules and class methods use strict semantics, where the same defect commonly becomes a `TypeError`.
  Source: [call, apply and bind](https://codewiki.com/javascript/call-apply-bind/)
- Common hand-written versions temporarily attach the function to its receiver.
  Why: They convert strict receivers incorrectly, fail on frozen objects or proxies, and may skip cleanup when the target throws; simplified `bind()` versions also miss construction and metadata semantics.
  Source: [call, apply and bind](https://codewiki.com/javascript/call-apply-bind/)
- Using a class declaration early as if it were a function declaration throws `ReferenceError`.
  Why: The class binding exists, but it isn't initialized until execution reaches the declaration.
  Source: [Classes](https://codewiki.com/javascript/classes/)
- `map(service.transform)`, event handlers, and destructuring can separate a method from its receiver.
  Why: If the method reads a public or private field, it then fails because `this` is `undefined` or has the wrong private brand.
  Source: [Classes](https://codewiki.com/javascript/classes/)
- `this.configure()` in a base constructor can dispatch to an override in the derived class.
  Why: Derived fields haven't been initialized yet, so the override may read `undefined` or throw.
  Source: [Classes](https://codewiki.com/javascript/classes/)
- `this.#counter` inside a base static method can throw `TypeError` when the method is called through a subclass.
  Why: A static private field's brand belongs to its declaring class and isn't installed on subclasses like a public static property.
  Source: [Classes](https://codewiki.com/javascript/classes/)
- `get items() { return [...this.#items]; }` copies only the outer array.
  Why: A caller can still mutate the record objects inside it, and the private field will observe those changes.
  Source: [Classes](https://codewiki.com/javascript/classes/)
- An outer binding can change after a closure is created.
  Why: An asynchronous callback reads its current value, which may differ from the value present when work was scheduled.
  Source: [Closures](https://codewiki.com/javascript/closures/)
- Giving one stateful closure to consumers that should be independent makes them silently share counters, caches, or retry state.
  Source: [Closures](https://codewiki.com/javascript/closures/)
- Do not assume this is safe: lexical scope narrows direct access, but it does not stop return values, logs, errors, or callbacks from disclosing captured data.
  Source: [Closures](https://codewiki.com/javascript/closures/)
- Do not assume this is safe: a regular function's `this` is determined by call form; it is not an ordinary lexical variable captured at the definition site.
  Why: Passing a method as a callback can lose its receiver.
  Source: [Closures](https://codewiki.com/javascript/closures/)
- If a longer-lived event source still owns a handler, the component, cache, or request context captured by that handler may remain reachable.
  Source: [Closures](https://codewiki.com/javascript/closures/)
- Even with a `let` loop variable, a mutable object declared outside the loop is shared by every callback.
  Why: `let` separates per-iteration variables; it does not copy other state.
  Source: [Closures](https://codewiki.com/javascript/closures/)
- The fact that `curried(a, b)(c)` works doesn't mean strict currying lets each layer take several arguments.
  Why: Many libraries combine currying and partial application in one interface, while others accept only unary calls.
  Source: [Currying and function composition](https://codewiki.com/javascript/currying-composition/)
- An arity-based helper applied to `(base, options = {}, request)` may execute as soon as it receives `base`.
  Why: A rest-parameter function has a `length` of `0`, so it has no naturally inferred completion point either.
  Source: [Currying and function composition](https://codewiki.com/javascript/currying-composition/)
- `curry(account.charge)` extracts a function value and loses the receiver call form `account.charge()`.
  Why: A helper that reads `this` at different layers can also see different receivers from the first and last partial calls.
  Source: [Currying and function composition](https://codewiki.com/javascript/currying-composition/)
- When a synchronous `pipe` reaches an async stage, it passes the Promise itself to the next function.
  Why: A later property read commonly produces `undefined` or a type error several stages away from the real cause.
  Source: [Currying and function composition](https://codewiki.com/javascript/currying-composition/)
- A long point-free chain hides changes from object to array to string.
  Why: Stages using `sort()`, `reverse()`, or object-field assignment can also make an apparently functional transformation modify caller-owned data.
  Source: [Currying and function composition](https://codewiki.com/javascript/currying-composition/)
- `typeof value === "object"` matches `null`, arrays, and many built-in objects.
  Why: Reading a property immediately makes the `null` branch throw, while treating an array as a record can silently produce the wrong result.
  Source: [Data types](https://codewiki.com/javascript/data-types/)
- `Boolean("false")` and `Boolean("0")` are both `true` because any non-empty string is truthy.
  Why: Generated configuration parsers often pass environment variables straight to `Boolean()`, enabling a feature that should be off.
  Source: [Data types](https://codewiki.com/javascript/data-types/)
- `count || 10` changes a valid `0` to `10`, `enabled || true` changes `false` to `true`, and `label || "default"` discards a meaningful empty string.
  Source: [Data types](https://codewiki.com/javascript/data-types/)
- `Number("")` is `0`, while `parseInt("12px", 10)` is `12`.
  Why: Checking only that the result isn't `NaN` accepts empty or suffixed text outside the contract.
  Source: [Data types](https://codewiki.com/javascript/data-types/)
- Adding a form value of `"20"` to the number `5` produces `"205"`.
  Why: When one side is BigInt and the other is Number, numeric addition throws `TypeError` instead of choosing a representation automatically.
  Source: [Data types](https://codewiki.com/javascript/data-types/)
- Do not assume this is safe: `===` compares object identity rather than walking properties, and `NaN === NaN` is false.
  Why: Conversely, coercion makes `0 == false` true without proving that the two fields represent the same domain value.
  Source: [Data types](https://codewiki.com/javascript/data-types/)
- A generated parser often passes user text straight to `new Date(value)`.
  Why: Non-standard strings may be implementation-defined, and even specified-looking fields can normalize instead of being rejected.
  Source: [Date](https://codewiki.com/javascript/date-object/)
- `new Date('invalid')` creates a truthy object.
  Why: Most getters return `NaN`, `toISOString()` throws, and JSON serialization can turn it into `null` later.
  Source: [Date](https://codewiki.com/javascript/date-object/)
- Combining `getUTCFullYear()` with `getMonth()` or constructing local components before serializing to UTC can assemble fields from different calendar views.
  Source: [Date](https://codewiki.com/javascript/date-object/)
- Setters change the original object, so a helper can silently alter a value still owned by its caller.
  Why: Month and day setters also normalize overflow rather than clamping it.
  Source: [Date](https://codewiki.com/javascript/date-object/)
- Do not assume this is safe: dividing milliseconds by `86_400_000` measures elapsed 24-hour units, not dates on a local calendar.
  Why: Adding that constant can change the displayed hour across a daylight-saving boundary.
  Source: [Date](https://codewiki.com/javascript/date-object/)
- Two separately constructed dates for the same instant are different objects, so `left === right` is `false`.
  Why: Relational comparison happens to coerce them, which makes an equality-only bug easy to miss.
  Source: [Date](https://codewiki.com/javascript/date-object/)
- `function read({ id } = {}) {}` uses the empty object only when the argument is omitted or is `undefined`.
  Why: Passing `null` still throws `TypeError` when the object pattern begins.
  Source: [Destructuring assignment](https://codewiki.com/javascript/destructuring/)
- Generated code often reads `{ count = 10 }` as “use 10 when count is missing or invalid.” Only `undefined` activates the default expression; `null`, `0`, `false`, and `''` survive unchanged.
  Source: [Destructuring assignment](https://codewiki.com/javascript/destructuring/)
- `const { profile: { name = 'guest' } } = user` defaults only `name`.
  Why: If `profile` is missing, `undefined`, or `null`, the inner pattern fails before it can read `name`.
  Source: [Destructuring assignment](https://codewiki.com/javascript/destructuring/)
- In `{ name: displayName }`, `name` is the source property key and `displayName` is the new binding.
  Why: A later read of `name` can hit a different outer variable or throw `ReferenceError`, making a rename mistake surprisingly subtle.
  Source: [Destructuring assignment](https://codewiki.com/javascript/destructuring/)
- `const { password, ...publicUser } = user` copies every own enumerable property except `password`.
  Why: A generated `token`, `mfaSecret`, or internal flag leaks automatically, and nested objects still share references with the input.
  Source: [Destructuring assignment](https://codewiki.com/javascript/destructuring/)
- The empty position in `[first, , third]` binds no name but still obtains and discards one iterator value.
  Why: With a generator, streaming adapter, or logging custom iterator, that consumption can change external state.
  Source: [Destructuring assignment](https://codewiki.com/javascript/destructuring/)
- A broad `catch` that logs and returns `undefined`, `{}`, or `[]` converts every failure into apparent success.
  Why: Callers can no longer distinguish unavailable data from real empty data.
  Source: [Error handling](https://codewiki.com/javascript/error-handling/)
- Do not assume this is safe: `catch (error)` does not prove that `error.message`, `error.stack`, or `error.cause` exists.
  Why: Dependencies and legacy code can reject or throw strings, numbers, `null`, or plain objects.
  Source: [Error handling](https://codewiki.com/javascript/error-handling/)
- Starting an async operation inside `try` and leaving it unawaited lets its rejection occur outside that `catch`.
  Why: A detached `.then()` chain without a rejection owner has the same bug.
  Source: [Error handling](https://codewiki.com/javascript/error-handling/)
- A `return`, `throw`, `break`, or `continue` in `finally` can replace the pending completion.
  Why: The original exception may disappear even though cleanup appears to have succeeded.
  Source: [Error handling](https://codewiki.com/javascript/error-handling/)
- Do not assume this is safe: `Promise.all()` rejects when one input rejects, but it does not stop the other operations.
  Why: They may continue writing data, consuming capacity, or producing later rejections.
  Source: [Error handling](https://codewiki.com/javascript/error-handling/)
- Mechanically changing a declaration into a `const` arrow.
  Why: Generated refactors often preserve the body while changing initialization timing, `this`, `arguments`, and constructibility; startup code that called the declaration early can fail immediately.
  Source: [Functions](https://codewiki.com/javascript/functions/)
- Do not treat a default parameter as a default for every empty value.
  Why: `value = fallback` runs only for `undefined`; when an API returns `null`, the function keeps it and may later fail in a string or numeric operation.
  Source: [Functions](https://codewiki.com/javascript/functions/)
- Forgetting `return` in a block-bodied arrow.
  Why: Changing `item => item.id` to `item => { item.id }` makes the braces a function body, not an object or an implicit return, so every call produces `undefined`.
  Source: [Functions](https://codewiki.com/javascript/functions/)
- Do not treat `arguments` as an array or as an arrow-local value.
  Why: `arguments.map(...)` doesn't exist; an arrow reading `arguments` gets it from an outer scope and may silently consume a completely different call.
  Source: [Functions](https://codewiki.com/javascript/functions/)
- Passing a `this`-dependent method directly as a callback.
  Why: `queue.add(service.handle)` passes only a function object, not `service`; the receiver is gone when the later plain call happens.
  Source: [Functions](https://codewiki.com/javascript/functions/)
- Do not treat an iterator as a repeatable iterable.
  Why: A generator object's `Symbol.iterator` returns itself, so spreading it again after one consumption produces only remaining values or an empty array.
  Source: [Iterators and generators](https://codewiki.com/javascript/iterators-generators/)
- Using `undefined` to detect the end of iteration.
  Why: An iterator may legally yield `undefined`, and its completion result may carry a non-`undefined` final value.
  Source: [Iterators and generators](https://codewiki.com/javascript/iterators-generators/)
- Applying spread, `Array.from()`, or rest destructuring to an unknown-length or infinite iterable.
  Why: These operations keep requesting values, growing memory use or never returning.
  Source: [Iterators and generators](https://codewiki.com/javascript/iterators-generators/)
- Expecting the first `next(value)` call to send `value` into the generator.
  Why: The generator has not reached a `yield`, so no expression can receive that argument.
  Source: [Iterators and generators](https://codewiki.com/javascript/iterators-generators/)
- Omitting `return()` from a hand-written iterator that owns a resource.
  Why: Complete traversal may look correct, but `break` or an exception skips release work that only the producer knows about.
  Source: [Iterators and generators](https://codewiki.com/javascript/iterators-generators/)
- Do not treat `const` as immutable data lets shared objects change inside code that looks safe.
  Why: `Object.freeze()` is shallow too; it doesn't recursively freeze nested objects.
  Source: [JavaScript fundamentals](https://codewiki.com/javascript/fundamentals/)
- Using `value || fallback` for defaults replaces valid values such as `0`, `false`, and `""`.
  Why: Generated pagination, retry, and feature-toggle code is particularly prone to this mistake.
  Source: [JavaScript fundamentals](https://codewiki.com/javascript/fundamentals/)
- A check of only `typeof value === "object"` accepts `null`, arrays, and ordinary objects.
  Why: A later property read throws on `null`, while an array may bypass an expected object-shape check.
  Source: [JavaScript fundamentals](https://codewiki.com/javascript/fundamentals/)
- Do not treat `Number(input)` as validation accepts an empty or whitespace-only string because either converts to `0`.
  Why: `parseInt("12px", 10)` also accepts a prefix and ignores trailing characters.
  Source: [JavaScript fundamentals](https://codewiki.com/javascript/fundamentals/)
- Relying on an object's truthiness says nothing about its contents because empty arrays and empty objects are truthy.
  Why: `if (items)` doesn't prove that an array contains an item.
  Source: [JavaScript fundamentals](https://codewiki.com/javascript/fundamentals/)
- Do not treat successful parsing as valid input.
  Why: `JSON.parse()` accepts `null`, arrays, and objects missing required fields; generated code often destructures or calls a property immediately after parsing. Fix: Validate the top-level category, every required field, nested values, and ranges before use. Keep syntax errors, absent bodies, HTTP failures, and business-validation failures distinct instead of catching everything and returning `{}`.
  Source: [JSON](https://codewiki.com/javascript/json/)
- Do not assume serialization preserves every value.
  Why: Object properties containing `undefined`, functions, and Symbols disappear; corresponding array positions become `null`; non-finite numbers become `null`; `BigInt` and cycles throw. Fix: List the types supported by the wire format and test every boundary value. Consider `structuredClone()` for supported in-memory object graphs; use explicit fields or a versioned codec contract when special types must cross a boundary.
  Source: [JSON](https://codewiki.com/javascript/json/)
- Trying to recover a large integer after parsing.
  Why: `BigInt(value)` merely converts an already-rounded `Number`; it cannot restore lost bits. Comparing an unsafe parsed number with the same source-code numeric literal can also mislead because that literal is rounded too. Fix: The most portable cross-system contract sends large integers as validated decimal strings. In runtimes with reviver source context, a known field can instead construct `BigInt` from `context.source`.
  Source: [JSON](https://codewiki.com/javascript/json/)
- Guessing types with broad revival rules.
  Why: Turning every date-shaped string into a `Date` can change product identifiers, calendar-only dates, or user text; an unvalidated `__type` field can collide with real data. Fix: Revive values at paths named by the schema, or define a namespaced and versioned tag format. Validate the resulting time value and the canonical form required by the protocol, and allowlist tag values.
  Source: [JSON](https://codewiki.com/javascript/json/)
- Claiming that `JSON.parse()` itself pollutes prototypes.
  Why: Parsing `"__proto__"` creates an own data property of that name and does not directly modify `Object.prototype`; danger usually appears when later code sends untrusted keys through legacy setters, recursive mergers, or dynamic property writes. Fix: Map parsed input to a validated domain object instead of merging arbitrary keys into a configuration object with a prototype. If you genuinely need an untrusted dictionary, consider a `Map` or null-prototype object and define a clear allowed-key contract.
  Source: [JSON](https://codewiki.com/javascript/json/)
- Using `JSON.stringify()` as content equality or signature canonicalization.
  Why: Different property insertion orders can produce different texts, while dropped values can make different inputs produce the same text. Getters, `toJSON()`, and replacers can also affect the result during traversal. Fix: Compare explicit fields for business equality. Cache keys, hashes, and signatures need one shared canonicalization rule on both sides, with tests for key order, numbers, Unicode, and absent fields; default serialization is not that cross-system standard.
  Source: [JSON](https://codewiki.com/javascript/json/)
- Generated code often calls `map.set({ id }, value)` and later looks up `map.get({ id })`.
  Why: The two objects have equal fields but different identities, so the lookup never finds the entry.
  Source: [Map and Set](https://codewiki.com/javascript/map-set/)
- `map.get(key) || defaultValue` overwrites valid `0`, `false`, and empty-string values.
  Why: Testing only whether `get()` returns `undefined` also conflates an absent key with a stored `undefined`.
  Source: [Map and Set](https://codewiki.com/javascript/map-set/)
- `new Set([{ id: 1 }, { id: 1 }])` has size `2`.
  Why: `Set` deduplicates by object identity and doesn't recursively compare fields.
  Source: [Map and Set](https://codewiki.com/javascript/map-set/)
- Code that deletes the current entry and reinserts it to “refresh” order may visit the entry again at the end of live iteration.
  Why: Repeating that operation can even prevent the loop from ending.
  Source: [Map and Set](https://codewiki.com/javascript/map-set/)
- `JSON.stringify(new Map([['a', 1]]))` and `JSON.stringify(new Set(['a']))` both produce `'{}'` by default.
  Why: JSON serialization reads enumerable own string properties, not collection entries.
  Source: [Map and Set](https://codewiki.com/javascript/map-set/)
- Generated cache code may read `weakMap.size`, iterate its keys, or assert that an entry has been collected at a fixed time.
  Why: Weak collections deliberately omit those operations, and garbage-collection timing isn't a business event.
  Source: [Map and Set](https://codewiki.com/javascript/map-set/)
- `Math.round(value 100) / 100` performs a binary floating-point multiplication first.
  Why: The representation of `1.005 100` can be slightly below the expected midpoint, so the formula doesn't implement exact two-decimal rounding in general.
  Source: [Math object](https://codewiki.com/javascript/math-object/)
- `Math.abs(a - b) < Number.EPSILON` has a particular meaning only near a scale of `1`.
  Why: It is usually too strict for large magnitudes and can also be too strict near zero when domain noise is larger.
  Source: [Math object](https://codewiki.com/javascript/math-object/)
- `floor` doesn't mean "remove the fractional part," and `round` isn't banker's rounding.
  Why: Generated code also replaces rounding with `value | 0` or `~~value`, which converts to a signed 32-bit integer and can wrap or mishandle non-finite values.
  Source: [Math object](https://codewiki.com/javascript/math-object/)
- `Math.max(...values)` is clear for a small array, but spread turns every element into a function argument.
  Why: A sufficiently large array can exceed an engine's call-argument limit; empty arrays and arrays containing `NaN` also produce results that are easy to miss.
  Source: [Math object](https://codewiki.com/javascript/math-object/)
- `Math.random()` has no security-strength guarantee and no standard seed interface.
  Why: Verification codes, reset tokens, session identifiers, and audited drawings based on it use the wrong threat model; tests that call it directly also become unstable.
  Source: [Math object](https://codewiki.com/javascript/math-object/)
- Trigonometric functions still return an ordinary number when degrees are mistaken for radians, while `Math.sqrt()` merely returns `NaN` for a negative input.
  Why: Such errors can pass through several calculations before appearing at a serialization, rendering, or database boundary.
  Source: [Math object](https://codewiki.com/javascript/math-object/)
- Do not assume this is safe: two objects that reference each other don't automatically leak.
  Why: If a root cannot reach the cycle, a tracing garbage collector can treat the entire unreachable subgraph as garbage.
  Source: [Memory management](https://codewiki.com/javascript/memory-management/)
- A `Map` or ordinary object strongly retains its entries.
  Why: Adding user-derived keys forever without a capacity, TTL, or invalidation mechanism lets reachable data accumulate with traffic.
  Source: [Memory management](https://codewiki.com/javascript/memory-management/)
- A long-lived event source, observer, or timer can retain a callback, and that callback may capture an entire component state.
  Why: Removing the component's DOM node does not necessarily cancel those external registrations.
  Source: [Memory management](https://codewiki.com/javascript/memory-management/)
- Do not assume this is safe: whether `WeakRef.deref()` succeeds depends on the implementation and GC scheduling.
  Why: A target may remain for a long time when memory is plentiful or disappear quickly under pressure, so correctness based on “it is usually still there” becomes irreproducible.
  Source: [Memory management](https://codewiki.com/javascript/memory-management/)
- Do not assume this is safe: a finalizer has no guarantee of prompt or eventual execution, and it may not run at all when the process exits.
  Why: Making it the sole cleanup path for locks, transactions, files, or connections puts correctness behind uncontrollable scheduling.
  Source: [Memory management](https://codewiki.com/javascript/memory-management/)
- Do not assume this is safe: a heap can grow because of warm-up, delayed collection, compiler data, or an intentional cache, and it need not immediately return pages to the operating system.
  Why: One memory reading cannot distinguish live objects, committed space, and memory outside the managed heap.
  Source: [Memory management](https://codewiki.com/javascript/memory-management/)
- Do not treat `const` as immutable data hides mutations behind a stable binding.
  Why: `const settings = {}` prevents `settings = other`, but `settings.theme = 'dark'` remains valid.
  Source: [Modern JavaScript features](https://codewiki.com/javascript/es6-features/)
- Replacing every default with `||` loses valid falsy values.
  Why: Generated configuration code often turns `0`, `false`, or `''` into a fallback even though only missing data should use that fallback.
  Source: [Modern JavaScript features](https://codewiki.com/javascript/es6-features/)
- Do not assume this is safe: spread is a shallow property operation, not a universal clone or redaction boundary.
  Why: Nested values remain aliased, object spread can invoke getters, and a denylist such as `{ password, ...publicUser }` silently exposes any sensitive field added later.
  Source: [Modern JavaScript features](https://codewiki.com/javascript/es6-features/)
- Optional chaining protects only the nullable steps marked in the chain.
  Why: If `account` exists but `account.profile` is missing, `account?.profile.name` still attempts to read `name` from `undefined`. Grouping as `(account?.profile).name` also ends the protected chain.
  Source: [Modern JavaScript features](https://codewiki.com/javascript/es6-features/)
- Do not assume this is safe: `Promise.all` rejects when an input rejects, but it does not cancel the remaining operations.
  Why: Generated code often reports failure and releases resources while another request is still using them.
  Source: [Modern JavaScript features](https://codewiki.com/javascript/es6-features/)
- Do not assume this is safe: imports such as `import "./config"`, `@/services`, or arbitrary bare specifiers copied from TypeScript or bundled projects may build successfully yet fail when run directly by a browser or Node 24.
  Why: Fix: Name whether the code runs in a browser, Node, or a builder, then execute the deployed artifact. Use full URL paths for browser-relative imports; define supported Node package aliases through an `imports` map whose keys begin with `#`.
  Source: [Modules](https://codewiki.com/javascript/modules/)
- `import client from "pkg"`, `import { client } from "pkg"`, and `const client = require("pkg")` don't promise the same shape.
  Why: Inferring a named export from the variable name or adding one `.default` too many breaks the interop boundary. Fix: Inspect the current package version's `exports` and type declarations, then record `Object.keys(namespace)` once in the target runtime. Use the documented entry; don't add both a default export and a same-named export merely to silence the error.
  Source: [Modules](https://codewiki.com/javascript/modules/)
- `` import(`./plugins/${name}.js`) `` lets input control the resolution range and can leave runtime-only paths out of a built artifact.
  Why: Appending a timestamp also creates a new identity on every call, repeating side effects and expanding the cache. Fix: Map public names to fixed specifiers or loader functions, reject unknown keys, and give every target the same export contract. Test loading, evaluation, and business-call failures separately instead of swallowing all three in one `catch`.
  Source: [Modules](https://codewiki.com/javascript/modules/)
- ESM can link a cyclic graph, but that doesn't make every top-level read in the cycle safe.
  Why: If module A reads one of its own `let`, `const`, or `class` exports back through module B before initialization, the read hits the temporal dead zone and throws `ReferenceError`. Fix: Move shared constants or types to a leaf module with no back edge, defer cross-module reads until a function call, and test cold startup through the real entry. Dynamic import changes the API's asynchrony and isn't a mechanical fix for a cycle you haven't explained.
  Source: [Modules](https://codewiki.com/javascript/modules/)
- A top-level `const cache = new Map()` is shared by every importer of the same module instance.
  Why: Tests, requests, or tenants that assume each import creates a cache contaminate each other; query-string cache busting turns that into duplicate instances and retention. Fix: Keep genuine process singletons at module top level and put state requiring isolation in an explicit factory. Interleave two factory instances in tests, and separately verify that module initialization happens only once.
  Source: [Modules](https://codewiki.com/javascript/modules/)
- The same `.js` file can be interpreted as ESM or CommonJS because of its nearest `package.json` boundary.
  Why: Moving a directory, publishing without that file, or retaining `__dirname` and `module.exports` in ESM can make code fail only after publication. Fix: Declare `type` in every package and use `.mjs` or `.cjs` when a boundary file needs an unambiguous format. Execute the Node 24 entry from the built directory and verify every subpath exposed by `exports`, not only source tests.
  Source: [Modules](https://codewiki.com/javascript/modules/)
- `Object.keys()` omits non-enumerable properties, Symbol properties, and inherited properties.
  Why: A debugger showing a field doesn't mean the field appears in `Object.keys()`, object spread, or JSON output.
  Source: [Object static methods](https://codewiki.com/javascript/object-methods/)
- `Object.assign(defaults, input)` uses `defaults` as the target and changes it in place.
  Why: Module-level defaults then retain data from a previous request, and later sources may also invoke a setter on the target.
  Source: [Object static methods](https://codewiki.com/javascript/object-methods/)
- `Object.assign()`, object spread, and descriptor copying create only a new outer object.
  Why: Mutating a shared nested array or object still changes what the source observes.
  Source: [Object static methods](https://codewiki.com/javascript/object-methods/)
- `Object.defineProperty(target, 'port', { value: 8080 })` creates a property that is non-writable, non-enumerable, and non-configurable by default.
  Why: Generated code often supplies only `value` and then misdiagnoses a later failed assignment as a freezing problem.
  Source: [Object static methods](https://codewiki.com/javascript/object-methods/)
- `Object.freeze()` doesn't freeze nested objects or turn a getter into a fixed value.
  Why: On a frozen accessor property, the getter and an existing setter can still run and read or change state elsewhere.
  Source: [Object static methods](https://codewiki.com/javascript/object-methods/)
- A constructor's `.prototype` is an ordinary property that `new` consults.
  Why: An instance's `[[Prototype]]` is an internal link; `instance.prototype` is usually `undefined`, and a function itself has a separate `[[Prototype]]` normally reached through `Function.prototype`.
  Source: [Objects and prototypes](https://codewiki.com/javascript/objects-prototypes/)
- `key in object` and `for...in` include the prototype chain.
  Why: Generated merge or validation code can therefore accept inherited values that were never present in the submitted record.
  Source: [Objects and prototypes](https://codewiki.com/javascript/objects-prototypes/)
- A prototype property such as `Cart.prototype.items = []` stores one array.
  Why: Calling `first.items.push(...)` mutates the shared array, so every instance that has not shadowed `items` observes the change.
  Source: [Objects and prototypes](https://codewiki.com/javascript/objects-prototypes/)
- Do not assume this is safe: writing `__proto__` depends on a legacy accessor and is especially dangerous with untrusted keys.
  Why: `Object.setPrototypeOf()` makes the operation explicit but can fail for non-extensible objects or cycles, and changing a live hierarchy can invalidate assumptions held elsewhere.
  Source: [Objects and prototypes](https://codewiki.com/javascript/objects-prototypes/)
- Do not assume this is safe: `Object.defineProperty(target, 'mode', { value: 'safe' })` does not behave like `target.mode = 'safe'`.
  Why: Its omitted flags are `false`, so later assignment, enumeration, deletion, or redefinition may fail unexpectedly.
  Source: [Objects and prototypes](https://codewiki.com/javascript/objects-prototypes/)
- `constructor` is normally inherited and can be shadowed, deleted, or changed.
  Why: `instanceof` follows one constructor's current `prototype` through one realm's chain, so it can reject compatible objects from another realm and can be customized with `Symbol.hasInstance`.
  Source: [Objects and prototypes](https://codewiki.com/javascript/objects-prototypes/)
- Do not assume this is safe: `instance.#secret` outside the class fails while the script is parsed, before control flow starts.
  Why: Generated code often wraps the line in `try...catch`, leaving the entire test file unable to load.
  Source: [Private fields](https://codewiki.com/javascript/private-fields/)
- `get items() { return this.#items; }` exposes the same array reference.
  Why: A caller can run `push()` and bypass the class's checks; the private field name hasn't made the array read-only.
  Source: [Private fields](https://codewiki.com/javascript/private-fields/)
- A derived class can't read a base private field directly, even when both classes declare a `#value` with the same spelling.
  Why: A static method using `this.#value` can also fail when its receiver is a derived class.
  Source: [Private fields](https://codewiki.com/javascript/private-fields/)
- Passing an instance method as a bare function to `map()`, an event registrar, or a test stub loses the original `this`.
  Why: An empty `Proxy` also makes the proxy the receiver, so ordinary properties may look fine until the first private access throws `TypeError`.
  Source: [Private fields](https://codewiki.com/javascript/private-fields/)
- `Object.freeze(instance)` handles only object properties, so class methods can still mutate private fields.
  Why: Object spread, `structuredClone()`, and default JSON serialization omit private state, and the clone doesn't have the original class's private brand.
  Source: [Private fields](https://codewiki.com/javascript/private-fields/)
- A handler that returns `target[key]` looks correct in tests using ordinary data properties, but it changes `this` inside getters, setters, and prototype chains.
  Why: `Reflect.get(target, key, target)` has the same problem.
  Source: [Proxy and Reflect](https://codewiki.com/javascript/proxy-reflect/)
- `set`, `defineProperty`, and `deleteProperty` are distinct operations; so are `get`, `has`, `ownKeys`, and `getOwnPropertyDescriptor`.
  Why: Covering only one leaves bypasses or contradictory results.
  Source: [Proxy and Reflect](https://codewiki.com/javascript/proxy-reflect/)
- An `ownKeys` result with duplicates, a missing non-configurable own key, or an extra key on a non-extensible target throws `TypeError`.
  Why: Some `get` and `set` results are also constrained by non-configurable properties, so the bug may appear only after a production object is frozen.
  Source: [Proxy and Reflect](https://codewiki.com/javascript/proxy-reflect/)
- Do not assume this is safe: a `set` trap that returns `true` without changing the target makes an assignment appear successful while losing data.
  Why: Always returning `false` instead turns ordinary assignment into `TypeError` in strict mode. No fixed result can represent both outcomes correctly.
  Source: [Proxy and Reflect](https://codewiki.com/javascript/proxy-reflect/)
- `new Proxy(new Map(), {}).get("key")` gives `Map.prototype.get` the proxy as `this`, but the proxy lacks the internal slots a `Map` requires.
  Why: A method that accesses a class private field likewise fails because the proxy doesn't carry the instance's private brand.
  Source: [Proxy and Reflect](https://codewiki.com/javascript/proxy-reflect/)
- `revoke()` disables only that proxy.
  Why: It doesn't destroy the target, close resources held by the target, or stop operations through other references to it. Repeating revocation also doesn't replace idempotent resource cleanup.
  Source: [Proxy and Reflect](https://codewiki.com/javascript/proxy-reflect/)
- Do not assume this is safe: keeping one `/.../g` or `/.../y` object in a module constant and calling `test()` or `exec()` from several sites makes results depend on the previous `lastIndex`.
  Why: Even two Boolean tests against the same string can return different results.
  Source: [Regular expressions](https://codewiki.com/javascript/regexp/)
- `new RegExp(query)` treats `.`, `[`, `*`, backreferences, and other content as syntax.
  Why: An ordinary search term can widen the match, throw `SyntaxError`, or combine with its surrounding pattern into an expensive path.
  Source: [Regular expressions](https://codewiki.com/javascript/regexp/)
- Do not assume this is safe: a pattern can establish that `2026-99-99` has digits and hyphens without proving that the date exists.
  Why: Hand-written email, URL, and IP address patterns also tend to drift away from the protocols they imitate.
  Source: [Regular expressions](https://codewiki.com/javascript/regexp/)
- Generated internationalized code often extracts names with `\b\w+\b` or uses `/^.$/u` to require one user-perceived character.
  Why: The first misses many writing systems, while the second counts a multi-code-point grapheme as several characters.
  Source: [Regular expressions](https://codewiki.com/javascript/regexp/)
- A string passed as `replacement` to `text.replace(pattern, replacement)` interprets `$&`, `$1`, `$`, and `$$`.
  Why: If `replacement` is user-provided literal text, its dollar tokens can turn into matched content.
  Source: [Regular expressions](https://codewiki.com/javascript/regexp/)
- Nested quantifiers, overlapping alternatives, and long inputs that nearly match before failing can make the number of backtracking paths grow sharply.
  Why: Changing `.` to `.?` changes the trial order; it doesn't automatically remove ambiguity.
  Source: [Regular expressions](https://codewiki.com/javascript/regexp/)
- Ignoring string immutability.
  Why: `name.trim()` and `name.toLowerCase()` don't rewrite `name`; generated code often invokes a method and then continues using the old value. Fix: Save the result, as in `const normalized = name.trim()`. When reviewing a chain, trace every receiver, return type, and final use.
  Source: [String methods](https://codewiki.com/javascript/string-methods/)
- Do not treat `length` as a visible-character count.
  Why: Emoji, some historic scripts, and combining sequences make code-unit, code-point, and grapheme-cluster counts differ. An arbitrary `slice()` may also split a surrogate pair. Fix: State the counting unit in protocol limits. Use the string iterator for code points and `Intl.Segmenter` for interface symbols. Test surrogate pairs, combining marks, and zero-width-joiner sequences.
  Source: [String methods](https://codewiki.com/javascript/string-methods/)
- Confusing `replace()` with replace-all behavior.
  Why: A string search value with `replace()` affects only the first match, while `replaceAll()` requires the `g` flag when it receives a regular expression. Fix: Select the API along two axes: first or all matches, and fixed text or a pattern. Test zero, one, and several matches, and return replacement data from a function.
  Source: [String methods](https://codewiki.com/javascript/string-methods/)
- Parsing a full grammar with simple splitting or a regular expression.
  Why: `split(',')` can't handle quoted CSV fields, a tag-removal regex can't implement HTML parsing rules, and hand-written URL splitting misses encoding and relative references. Fix: Reserve string methods for small formats genuinely defined by fixed delimiters. Use the relevant parser for CSV, HTML, URLs, and other formal grammars, then validate business constraints after parsing.
  Source: [String methods](https://codewiki.com/javascript/string-methods/)
- Using case conversion for every case-insensitive comparison.
  Why: `toLowerCase()` doesn't express linguistic collation rules and doesn't automatically solve canonical equivalence, identifier security, or every multi-character case mapping. Fix: Use an explicitly configured `Intl.Collator` for user-visible search and sorting. Follow the protocol's own ASCII or normalization rules for protocol identifiers, and don't reuse display-locale rules for authorization keys.
  Source: [String methods](https://codewiki.com/javascript/string-methods/)
- Do not depend on `localeCompare()` to return exactly `-1` or `1`.
  Why: Its contract guarantees a negative number, positive number, or zero; control flow must not depend on the magnitude. Fix: Test comparison results with ` 0`, and `=== 0`. Reuse an `Intl.Collator`'s `compare` for many comparisons under one configuration, and validate the ordering with data from the target locale.
  Source: [String methods](https://codewiki.com/javascript/string-methods/)
- The descriptions in `Symbol('cache')` look alike, but every call creates a new identity.
  Why: A reader that calls `Symbol('cache')` again accesses a different property and gets `undefined`.
  Source: [Symbol](https://codewiki.com/javascript/symbol/)
- A Symbol key avoids ordinary string enumeration but enforces no access control.
  Why: A caller with the Symbol can access the property directly, and reflection through `Reflect.ownKeys()` or `Object.getOwnPropertySymbols()` discovers unknown Symbols.
  Source: [Symbol](https://codewiki.com/javascript/symbol/)
- Do not assume this is safe: generated code often validates an object with `Object.keys()`, then copies it with object spread and assumes both steps cover the same keys.
  Why: Spread copies enumerable Symbol keys, while default JSON serialization writes no Symbol keys.
  Source: [Symbol](https://codewiki.com/javascript/symbol/)
- `Symbol.for(userInput)` permanently expands the set of names retrievable from the current registry and may collide with another component's convention.
  Why: It doesn't make identity survive JSON, processes, workers, or persistence automatically.
  Source: [Symbol](https://codewiki.com/javascript/symbol/)
- `` `${key}` ``, `'' + key`, and paths that request ordinary string coercion can throw `TypeError` for a Symbol.
  Why: Diagnostic logging can then break a proxy trap, key traversal, or error handler that was otherwise valid.
  Source: [Symbol](https://codewiki.com/javascript/symbol/)
- Do not treat `setTimeout(callback, 0)` as “run now”; doing so makes code depend on an order the API never promises.
  Source: [The event loop](https://codewiki.com/javascript/event-loop/)
- Do not assume this is safe: a recursive microtask chain can keep adding work while the queue is draining, so timers and I/O callbacks do not get a turn.
  Source: [The event loop](https://codewiki.com/javascript/event-loop/)
- Do not assume `setTimeout(..., 0)` always runs before or after `setImmediate()`; doing so ignores the Node phase and the context where both were scheduled.
  Source: [The event loop](https://codewiki.com/javascript/event-loop/)
- Writing several `await` expressions in sequence can serialize independent operations and turn avoidable latency into user-visible delay.
  Source: [The event loop](https://codewiki.com/javascript/event-loop/)
- Do not assume this is safe: moving a CPU-heavy loop into an async function does not stop it from blocking; code before the next suspension point still occupies the event-loop thread.
  Source: [The event loop](https://codewiki.com/javascript/event-loop/)
- Writing an ordinary function beside an object literal or class doesn't permanently bind it to that object.
  Why: Assignment, destructuring, argument passing, and callback registration can all leave a function value without its original receiver.
  Source: [this binding](https://codewiki.com/javascript/this-binding/)
- `run: () => this.task` in an object literal doesn't make `this` point to that object.
  Why: The arrow gets `this` from outside, and an object literal creates no `this` binding of its own.
  Source: [this binding](https://codewiki.com/javascript/this-binding/)
- A detached ordinary function in an old-style non-strict script may replace `this` with `globalThis`, silently reading or writing a global property.
  Why: Modules and class methods are strict, so the same defect becomes an `undefined` receiver and an earlier `TypeError`.
  Source: [this binding](https://codewiki.com/javascript/this-binding/)
- `subscribe(this.handle.bind(this))` and a later `unsubscribe(this.handle.bind(this))` create two different functions.
  Why: The second result can't unregister the first callback even though the target function and receiver match.
  Source: [this binding](https://codewiki.com/javascript/this-binding/)
- A callback is invoked by the API that accepts it; some use an ordinary call, some accept a `thisArg`, and others specify a particular receiver.
  Why: Moving a working method from one API to another can change both `this` and the extra arguments.
  Source: [this binding](https://codewiki.com/javascript/this-binding/)
- Do not assume this is safe: both “a bound function's `this` never changes” and “a constructor always returns the new instance” are inaccurate.
  Why: `new` overrides a bound receiver, while an object explicitly returned by the constructor overrides the automatically created instance.
  Source: [this binding](https://codewiki.com/javascript/this-binding/)
- `new Uint32Array(buffer, 8, 4)` starts at byte 8 and contains 4 elements, so it needs 16 available bytes.
  Why: Reading both units as bytes can select the wrong window or raise `RangeError`.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- Do not assume this is safe: `new DataView(bytes.buffer)` sees the entire backing buffer, not the local window represented by `bytes`.
  Why: A pooled Node.js `Buffer`, a `subarray()` result, or an input assembled from several packets may have a nonzero `byteOffset`.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- Do not assume this is safe: `subarray()` does not copy data, so later writes by the caller can change a saved window.
  Why: Replacing every read-only window with `slice()` has the opposite problem: it silently changes memory and ownership behavior.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- `new Uint32Array(buffer)[0]` uses native byte order.
  Why: Passing tests on a common little-endian machine doesn't prove that it parses a big-endian network field correctly.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- Writing 256 to a `Uint8Array` produces 0, and writing -1 produces 255; these out-of-range values normally don't throw.
  Why: `Uint8ClampedArray` has different saturation behavior, and floating types introduce precision rounding.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- Do not assume this is safe: `new Uint8Array(uint16View)` converts each element value; it does not expose the two backing bytes of every `Uint16` element.
  Why: Reading the raw representation requires a byte view over the same buffer with the right range.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- Transferring an `ArrayBuffer` detaches the source, while shrinking a resizable buffer can put a fixed-length view out of bounds.
  Why: An old view may report length 0 or return `undefined` for indexed access, and some methods throw.
  Source: [Typed arrays and ArrayBuffer](https://codewiki.com/javascript/typed-arrays/)
- Code for cache metrics or an administration page often reads `weakMap.size`, spreads `weakMap`, or calls `entries()`.
  Why: Those members do not exist. Reading `size` produces `undefined`, while iteration throws `TypeError`.
  Source: [WeakMap and WeakSet](https://codewiki.com/javascript/weakmap-weakset/)
- String IDs, numbers, and registered symbols cannot be weak keys.
  Why: Both `new WeakMap().set('u-1', data)` and `new WeakSet().add(Symbol.for('done'))` throw `TypeError` in Node 24.
  Source: [WeakMap and WeakSet](https://codewiki.com/javascript/weakmap-weakset/)
- Do not assume this is safe: after `cache.set(user, result)`, `cache.get({ id: user.id })` does not hit.
  Why: Equal contents, equal prototypes, and equal serialized forms cannot substitute for the original object's identity.
  Source: [WeakMap and WeakSet](https://codewiki.com/javascript/weakmap-weakset/)
- A weak key removes only the collection's strong retention path to that key.
  Why: An event listener, timer, closure, array, or another cache may still strongly reference the object. Changing one `Map` to `WeakMap` neither cuts those paths nor releases files or sockets.
  Source: [WeakMap and WeakSet](https://codewiki.com/javascript/weakmap-weakset/)
- A depth-first traversal that only calls `add()` reports a shared child as a cycle when it encounters that child on another branch.
  Why: This is a graph-state definition error, not a consequence of weak references.
  Source: [WeakMap and WeakSet](https://codewiki.com/javascript/weakmap-weakset/)
