1---2name: toolchains-javascript-core3description: JavaScript ES2024+ and Node.js 22+ core patterns for minimalism, efficiency, code reuse, and performance4---56# JavaScript Core Patterns (ES2024+ / Node.js 22+)78## Quick Start910- `const` by default, `let` only for reassignment, never `var`11- Optional chaining `?.` and nullish coalescing `??` over manual null guards12- ESM `import`/`export` exclusively — treat `require` as legacy13- `structuredClone()` over `JSON.parse(JSON.stringify())`14- `node:` prefix for all built-in modules: `import fs from 'node:fs'`1516## Minimalism Patterns1718- Use `?.` for nested property access; use `??` for defaults (not `||` — it falsely triggers on `0`, `""`, `false`)19- Destructure at point of use to reduce intermediate variables and clarify intent20- Use rest parameters `...args` over `arguments`; use spread over `Object.assign` or `concat`21- Declare private class fields with `#prefix`; never use underscore conventions to simulate privacy22- Use `using` declarations for explicit resource management — resources with `[Symbol.dispose]()` auto-cleanup on scope exit23- Use `await using` for async resources (`[Symbol.asyncDispose]()`); eliminates try/finally for streams and connections24- Use `DisposableStack` / `AsyncDisposableStack` when resource acquisition is conditional or multiple disposables need aggregation2526## Efficiency Patterns2728- Attach event listeners on a parent element (event delegation); use `event.target.closest()` to identify source29- Batch DOM mutations into a `DocumentFragment` before appending to the live DOM30- Use `requestAnimationFrame` for all visual/DOM updates; never modify DOM in `setTimeout` for animations31- Use `requestIdleCallback` (or `scheduler.postTask({ priority: 'background' })`) for non-urgent background work32- Use `IntersectionObserver` for lazy loading, infinite scroll, and visibility detection — never poll scroll position33- Call `observer.unobserve(el)` or `observer.disconnect()` when observation is no longer needed34- Use `AbortController` to batch-remove multiple event listeners with a single `abort()` call on cleanup35- Use `WeakMap` to associate metadata with DOM elements; entries auto-clean when elements are garbage-collected3637## Code Reuse3839- Use ESM `import`/`export` exclusively; use dynamic `import()` for code splitting and lazy-loading40- Build reusable UI with Web Components (Custom Elements + Shadow DOM + HTML Templates) — framework-agnostic41- Name custom elements in kebab-case with a hyphen (`my-button`) to avoid collision with native HTML tags42- Use Declarative Shadow DOM (`<template shadowrootmode="open">`) for server-rendered Web Components43- Use `:host` and CSS custom properties as the theming API for Web Components; keep internal styles encapsulated44- Use `Proxy` for cross-cutting concerns (validation, logging, access control) without modifying target objects45- Use `Reflect` methods inside Proxy traps to forward default behavior — never re-implement native semantics46- Export pure functions and compose them; prefer composition over class inheritance for business logic4748## Modern JS (ES2024+ / Node.js 22+)4950- `structuredClone()` — deep copy with support for `Date`, `Map`, `Set`, `ArrayBuffer`, circular refs51- `Object.groupBy()` / `Map.groupBy()` — replace reduce-based grouping patterns52- `Set` methods: `.union()`, `.intersection()`, `.difference()`, `.symmetricDifference()`, `.isSubsetOf()`53- Immutable array methods: `toSorted()`, `toReversed()`, `toSpliced()`, `with()` — no source mutation54- Iterator helpers: `.map()`, `.filter()`, `.take()`, `.drop()`, `.toArray()` directly on iterators (lazy)55- `Iterator.from(iterable)` — create iterator objects from any iterable56- `Promise.withResolvers()` — extract resolve/reject without wrapping in a constructor callback57- `Promise.try(fn)` — unify sync and async error handling into a single promise chain58- `RegExp.escape(str)` — safely interpolate user input into regular expressions59- Import attributes: `import data from './data.json' with { type: 'json' }` for type-safe module imports60- Temporal API (`Temporal.PlainDate`, `Temporal.ZonedDateTime`, `Temporal.Duration`): use `temporal-polyfill` until native support lands6162## Node.js 22+ Performance Patterns6364- Always use `node:` prefix: `import { readFile } from 'node:fs/promises'`65- Use `import.meta.dirname` and `import.meta.filename` instead of `__dirname`/`__filename` in ESM66- Use built-in `fetch()` for HTTP; combine with `AbortController` for timeouts and cancellation67- Use `--env-file=.env` or `process.loadEnvFile()` to load env vars; eliminates the `dotenv` dependency68- Use `--watch` for dev auto-restart instead of `nodemon`69- Use `node:test` runner for testing; eliminates Jest/Mocha for most projects70- Use Web Crypto API (`globalThis.crypto`) for cryptographic operations aligned with browser standards71- Run TypeScript directly with `node index.ts` (strip-types) for scripts and prototyping7273## DOM Performance7475- Batch reads then writes — never interleave reads and writes (forces layout thrashing)76- Use `IntersectionObserver` over scroll listeners; use `MutationObserver` over DOM polling77- Use `ResizeObserver` to respond to element size changes without window resize listeners78- Event delegation on parent containers scales to thousands of dynamic children at zero extra listener cost79- Virtual scrolling for long lists: render only visible items, translate with `transform: translateY`80- Prefer CSS for animation, container queries, `:has()`, and scroll-driven effects over JavaScript equivalents8182## Testing8384- Use `node:test` with `describe`/`it` blocks; supports nested suites and `before`/`after` hooks85- Mock with `context.mock.fn()` (spy) and `context.mock.method(obj, 'name')` for object methods86- Mock timers: `context.mock.timers.enable({ apis: ['setTimeout', 'Date'] })`; advance with `.tick(ms)`87- Coverage: `node --test --experimental-test-coverage` — no `nyc` or `c8` needed88- Watch mode: `node --test --watch` for rapid feedback89- For browser and E2E: Playwright — cross-browser, network interception, screenshot/video90- Property-based testing: fast-check for discovering edge cases in pure functions91- Vitest for projects already using Vite; Jest API-compatible with faster parallel execution9293## Anti-Patterns9495- Never use `var` — hoisting bugs and scope leaks that `const`/`let` prevent96- Never use `JSON.parse(JSON.stringify())` for deep cloning — use `structuredClone()`97- Never poll scroll position with `scroll` listeners — use `IntersectionObserver`98- Never import Lodash, Moment.js, jQuery, or RequireJS for new code — native ES2024+ covers core use cases99- Never use `arguments` object — use rest parameters `...args` which produce a real Array100- Never write manual null-check chains — use `?.` and `??`101- Never modify `Object.prototype` or prototypes you do not own — causes naming collisions102- Never use `eval()` — security risk and performance penalty103- Never add individual listeners to thousands of child elements — use event delegation104- Never attach closures referencing large objects to long-lived event listeners without cleanup — memory leak