$npx -y skills add ccheney/robust-skills --skill modern-javascriptProactively apply when creating web applications, Node.js services, or any JavaScript project. Triggers on JavaScript, ES6, ES2020, ES2022, ES2024, ES2025, ES2026, modern JS, refactor legacy, array methods, async/await, optional chaining, nullish coalescing, destructuring, spread
| 1 | # Modern JavaScript (ES6-ES2026) |
| 2 | |
| 3 | Write clean, performant, maintainable JavaScript using modern language features. This skill covers ES6 through ES2026, emphasizing immutability, functional patterns, and expressive syntax — and it pins each feature to the ECMAScript edition and runtimes that actually support it, because misattributed versions are the most common way modern-JS advice breaks. |
| 4 | |
| 5 | ## Quick Decision Trees |
| 6 | |
| 7 | ### "Which array method should I use?" |
| 8 | |
| 9 | ``` |
| 10 | What do I need? |
| 11 | ├─ Transform each element → .map() |
| 12 | ├─ Keep some elements → .filter() |
| 13 | ├─ Find one element → .find() / .findLast() |
| 14 | ├─ Check if condition met → .some() / .every() |
| 15 | ├─ Reduce to single value → .reduce() |
| 16 | ├─ Get last element → .at(-1) |
| 17 | ├─ Sort without mutating → .toSorted() |
| 18 | ├─ Reverse without mutating → .toReversed() |
| 19 | ├─ Group by property → Object.groupBy() / Map.groupBy() |
| 20 | ├─ Collect an async iterable → Array.fromAsync() |
| 21 | └─ Flatten nested arrays → .flat() / .flatMap() |
| 22 | ``` |
| 23 | |
| 24 | ### "How do I handle nullish values?" |
| 25 | |
| 26 | ``` |
| 27 | Nullish handling? |
| 28 | ├─ Safe property access → obj?.prop / obj?.[key] |
| 29 | ├─ Safe method call → obj?.method?.() |
| 30 | ├─ Default for null/undefined only → value ?? 'default' |
| 31 | ├─ Default for any falsy → value || 'default' |
| 32 | ├─ Assign if null/undefined → obj.prop ??= 'default' |
| 33 | └─ Check property exists → Object.hasOwn(obj, 'key') |
| 34 | ``` |
| 35 | |
| 36 | ### "Should I mutate or copy?" |
| 37 | |
| 38 | ``` |
| 39 | Always prefer non-mutating methods: |
| 40 | ├─ Sort array → .toSorted() (not .sort()) |
| 41 | ├─ Reverse array → .toReversed() (not .reverse()) |
| 42 | ├─ Splice array → .toSpliced() (not .splice()) |
| 43 | ├─ Update element → .with(i, val) (not arr[i] = val) |
| 44 | ├─ Add to array → [...arr, item] (not .push()) |
| 45 | └─ Merge objects → {...obj, key} (not Object.assign()) |
| 46 | ``` |
| 47 | |
| 48 | ## ES Version Quick Reference |
| 49 | |
| 50 | Editions are set by which proposals reach TC39 Stage 4 before the spring cutoff, so a feature's edition often lags its browser availability (e.g. `Array.fromAsync` shipped in browsers in 2023-24 but is spec'd in ES2026). Cite editions from this table, not from memory. |
| 51 | |
| 52 | | Version | Year | Key Features | |
| 53 | |---------|------|--------------| |
| 54 | | ES6 | 2015 | let/const, arrow functions, classes, destructuring, spread, Promises, modules, Symbol, Map/Set, Proxy, generators | |
| 55 | | ES2016 | 2016 | Array.includes(), exponentiation operator ** | |
| 56 | | ES2017 | 2017 | async/await, Object.values/entries, padStart/padEnd, trailing commas, SharedArrayBuffer, Atomics | |
| 57 | | ES2018 | 2018 | Rest/spread for objects, for await...of, Promise.finally(), RegExp named groups, lookbehind, dotAll flag | |
| 58 | | ES2019 | 2019 | .flat(), .flatMap(), Object.fromEntries(), trimStart/End(), optional catch binding, stable Array.sort() | |
| 59 | | ES2020 | 2020 | Optional chaining ?., nullish coalescing ??, BigInt, Promise.allSettled(), globalThis, dynamic import(), matchAll | |
| 60 | | ES2021 | 2021 | String.replaceAll(), Promise.any(), logical assignment ??= \|\|= &&=, numeric separators 1_000_000, WeakRef | |
| 61 | | ES2022 | 2022 | .at(), Object.hasOwn(), top-level await, private class fields #field, static blocks, Error cause, /d flag | |
| 62 | | ES2023 | 2023 | .toSorted(), .toReversed(), .toSpliced(), .with(), .findLast(), .findLastIndex(), hashbang grammar | |
| 63 | | ES2024 | 2024 | Object.groupBy(), Map.groupBy(), Promise.withResolvers(), RegExp /v flag, resizable ArrayBuffer + transfer(), Atomics.waitAsync(), isWellFormed() | |
| 64 | | ES2025 | 2025 | Set methods (.union, .intersection, ...), iterator helpers (.map, .filter, .take), RegExp.escape(), Promise.try(), import attributes + JSON modules, duplicate named capture groups, RegExp inline modifiers, Float16Array | |
| 65 | | ES2026 | 2026 | Array.fromAsync(), Error.isError(), Math.sumPrecise(), Uint8Array.fromBase64()/toBase64(), Iterator.concat(), Map.getOrInsert(), JSON.parse source access | |
| 66 | |
| 67 | Already Stage 4 and slated for ES2027: **Temporal**, **explicit resource management (`using`/`await using`)**, `Atomics.pause()`, `Iterator.zip()`. Decorators remain Stage 3 (transpiler only). Records & Tuples (`#{}`/`#[]`) w |