All skills
ccheney avatar

/modern-javascript

@00695ba

Implement or debug JavaScript language behavior, including promise completion, async iteration, mutation, and runtime compatibility. Use for ECMAScript semantics or polyfill/transform choices; not unrelated framework or TypeScript type design.

Use this Skill: https://skilld.dev/gh/ccheney/robust-skills/modern-javascript

This session only. Nothing lands on disk.

referencesCHEATSHEET.md

≈3.5k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Modern JavaScript Cheatsheet

Syntax lookup for standardized ECMAScript through ES2026, plus explicitly labeled Stage 4 ES2027 features and selected toolchain-backed proposals. Check COMPATIBILITY.md before using post-ES2023 APIs on an undeclared baseline.

Contents

Variables & Scope

const x = 1;        // Block-scoped, cannot reassign
let y = 2;          // Block-scoped, can reassign
// var z = 3;       // Function-scoped, avoid

Arrow Functions

const add = (a, b) => a + b;            // Expression body
const greet = name => `Hello ${name}`;  // Single param, no parens
const getObj = () => ({ key: 'value' }); // Return object literal
const multi = (a, b) => {               // Block body
  const sum = a + b;
  return sum * 2;
};

Destructuring

// Object
const { name, age = 18 } = user;
const { name: n, address: { city } } = user;
const { id, ...rest } = user;

// Array
const [first, second] = arr;
const [head, ...tail] = arr;
const [, , third] = arr;
[a, b] = [b, a];  // Swap

Spread & Rest

// Spread
const merged = [...arr1, ...arr2];
const clone = { ...obj };
const updated = { ...obj, key: 'new' };
Math.max(...numbers);

// Rest
const sum = (...nums) => nums.reduce((a, b) => a + b);
const { id, ...userData } = user;

Template Literals

const str = `Hello ${name}!`;
const multi = `Line 1
Line 2`;
const html = `<div class="${cls}">${content}</div>`;

Object Shorthand

const name = 'Alice';
const obj = {
  name,                    // Property shorthand
  greet() { },             // Method shorthand
  [`key_${id}`]: value,    // Computed property
};

Optional Chaining & Nullish Coalescing

obj?.prop              // Property access
obj?.[key]             // Dynamic property
obj?.method?.()        // Method call
arr?.[0]               // Array access

value ?? 'default'     // Nullish coalescing (null/undefined only)
value || 'default'     // Falsy coalescing (0, '', false, null, undefined)

obj.prop ??= 'default' // Assign if nullish
obj.prop ||= 'default' // Assign if falsy
obj.prop &&= newValue  // Assign if truthy

Array Methods

// Transform
arr.map(x => x * 2)
arr.filter(x => x > 0)
arr.reduce((acc, x) => acc + x, 0)
arr.flatMap(x => [x, x * 2])
arr.flat(2)

// Search
arr.find(x => x.id === 1)
arr.findIndex(x => x.id === 1)
arr.findLast(x => x > 5)           // ES2023
arr.findLastIndex(x => x > 5)      // ES2023
arr.includes(value)
arr.indexOf(value)

// Check
arr.some(x => x > 0)
arr.every(x => x > 0)

// Access
arr.at(-1)                         // ES2022 - last element
arr.at(-2)                         // second to last

// Non-mutating (ES2023)
arr.toSorted((a, b) => a - b)
arr.toReversed()
arr.toSpliced(1, 1)
arr.with(0, 'new')

// Group (ES2024)
Object.groupBy(arr, x => x.type)
Map.groupBy(arr, x => x.type)

// Create
Array.from({ length: 5 }, (_, i) => i)
Array.of(1, 2, 3)
await Array.fromAsync(asyncIterable)  // ES2026; sequential async consumption

String Methods

str.includes('sub')
str.startsWith('pre')
str.endsWith('suf')
str.padStart(10, '0')          // ES2017
str.padEnd(10, '-')            // ES2017
str.repeat(3)
str.trim()
str.trimStart()                // ES2019
str.trimEnd()                  // ES2019
str.matchAll(/pattern/g)       // ES2020 - iterator of matches
str.replaceAll('a', 'b')       // ES2021
str.at(-1)                     // ES2022 - last char
str.isWellFormed()             // ES2024
str.toWellFormed()             // ES2024

Object Methods

Object.keys(obj)
Object.values(obj)
Object.entries(obj)
Object.fromEntries(entries)
Object.assign({}, obj, updates)
Object.hasOwn(obj, 'key')      // ES2022
Object.groupBy(arr, fn)        // ES2024

Promises

// Create
new Promise((resolve, reject) => { })
Promise.resolve(value)
Promise.reject(error)
Promise.withResolvers()        // ES2024
Promise.try(() => fn())        // ES2025

// Combinators
Promise.all([p1, p2, p3])
Promise.allSettled([p1, p2])   // ES2020
Promise.race([p1, p2])
Promise.any([p1, p2])          // ES2021

// Instance methods
promise.then(onFulfilled, onRejected)
promise.catch(onRejected)
promise.finally(onFinally)     // ES2018

Async/Await

async function fn() {
  try {
    const result = await promise;
    return result;
  } catch (error) {
    handleError(error);
  }
}

// Parallel
const [a, b] = await Promise.all([fetchA(), fetchB()]);

// Sequential
for (const item of items) {
  await process(item);
}

Classes

class Animal {
  #privateField = 0;           // Private field
  static count = 0;            // Static field

  constructor(name) {
    this.name = name;
    Animal.count++;
  }

  speak() {                    // Method
    return `${this.name} speaks`;
  }

  #privateMethod() { }         // Private method

  get displayName() {          // Getter
    return this.name.toUpperCase();
  }

  set displayName(value) {     // Setter
    this.name = value.toLowerCase();
  }

  static create(name) {        // Static method
    return new Animal(name);
  }
}

class Dog extends Animal {
  constructor(name, breed) {
    super(name);
    this.breed = breed;
  }

  speak() {
    return `${super.speak()}: Woof!`;
  }
}

Modules

// Export
export const x = 1;
export function fn() { }
export default class { }
const a = 1, b = 2;
export { a, b as c };
// Import
import Default from './module';
import { x, fn } from './module';
import { x as y } from './other';
import * as mod from './module';
import './module';  // Side effects only

// Dynamic
const dynamic = await import('./module');

Set & Map

// Set
const set = new Set([1, 2, 3]);
set.add(4);
set.has(1);
set.delete(1);
set.size;
set.clear();

// ES2025 Set methods
setA.union(setB)
setA.intersection(setB)
setA.difference(setB)
setA.symmetricDifference(setB)
setA.isSubsetOf(setB)
setA.isSupersetOf(setB)
setA.isDisjointFrom(setB)

// Map
const map = new Map([['a', 1], ['b', 2]]);
map.set('c', 3);
map.get('a');
map.has('a');
map.delete('a');
map.size;

Iterators & Generators

// Generator
function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

// Async generator
async function* asyncGen() {
  yield await fetch(url1);
  yield await fetch(url2);
}

// for...of
for (const x of iterable) { }
for await (const x of asyncIterable) { }  // ES2018

// Iterator helpers (ES2025)
iter.map(fn)
iter.filter(fn)
iter.take(n)
iter.drop(n)
iter.toArray()
Iterator.from(iterable)

Regular Expressions

// Named capture groups (ES2018)
const pattern = /(?<year>\d{4})-(?<month>\d{2})/;
const { year, month } = str.match(pattern).groups;

// Lookbehind assertions (ES2018)
/(?<=\$)\d+/;        // Positive lookbehind
/(?<!\$)\d+/;        // Negative lookbehind

// Flags
/pattern/g;          // Global
/pattern/i;          // Case-insensitive
/pattern/m;          // Multiline
/pattern/s;          // dotAll - . matches newlines (ES2018)
/pattern/u;          // Unicode
/pattern/d;          // Match indices (ES2022)
/pattern/v;          // Unicode sets (ES2024)

// Inline modifiers (ES2025) — toggle i/m/s for part of a pattern
/^(?i:hello) world$/;

// Unicode property escapes (ES2018)
/\p{Letter}/u;       // Any letter
/\p{Emoji}/u;        // Emoji
/\p{Script=Greek}/u; // Greek script

// Unicode set operations (ES2024 /v flag)
/[\p{Emoji}--\p{ASCII}]/v;  // Emoji minus ASCII
/[[a-z]&&[^aeiou]]/v;       // Consonants only

// Duplicate named groups across alternatives (ES2025)
/(?<year>\d{4})-(?<month>\d{2})|(?<month>\d{2})\/(?<year>\d{4})/;

// Match indices (ES2022)
const match = /(?<g>\w+)/d.exec('hello');
match.indices.groups.g  // [0, 5]

// RegExp.escape (ES2025)
RegExp.escape('$100')   // '\\$100'

Primitives, Errors, Cloning, Resource Management

// BigInt (ES2020)
const big = 9007199254740991n;
BigInt(123);

// Numeric separators (ES2021)
const million = 1_000_000;

// globalThis (ES2020)
globalThis.setTimeout

// Error cause (ES2022)
throw new Error('msg', { cause: originalError });

// structuredClone (host/web API, not ECMA-262)
const deep = structuredClone(obj);

// String well-formed (ES2024)
str.isWellFormed()    // Check for lone surrogates
str.toWellFormed()    // Fix lone surrogates

// Private slot check (ES2022) — only valid inside the class body
class HasField {
  #field;
  static check(obj) { return #field in obj; }  // true if obj has #field
}

// Static initialization blocks (ES2022)
class C {
  static {
    // Runs when class is defined
  }
}

// Promise.finally (ES2018)
promise.finally(() => cleanup())

// Promise.try (ES2025)
Promise.try(() => mayThrow())

// Float16 (ES2025)
new Float16Array([1.5, 2.5])
Math.f16round(1.337)

// Import attributes (ES2025)
import data from './data.json' with { type: 'json' }

// WeakRef & FinalizationRegistry (ES2021)
const ref = new WeakRef(obj);
ref.deref()  // obj or undefined

// Symbol.description (ES2019)
Symbol('name').description  // 'name'

// Optional catch binding (ES2019)
try { } catch { }  // No parameter needed

// Hashbang (ES2023): '#!/usr/bin/env node' allowed as the very first line of a file

// Explicit Resource Management (Stage 4 → expected ES2027)
{
  using file = openFile('data.txt');  // file[Symbol.dispose]() runs on block exit
}
async function withDb() {
  await using db = await connect();   // db[Symbol.asyncDispose]() awaited on exit
}
new DisposableStack()                 // Aggregate disposables

// Array.fromAsync (ES2026, widely supported since 2024)
await Array.fromAsync(asyncIterable)
await Array.fromAsync(generator(), mapFn)

// Error.isError (ES2026)
Error.isError(err)  // Cross-realm-safe for ECMAScript Error objects

// Math.sumPrecise (ES2026)
Math.sumPrecise([1e20, 0.1, -1e20])  // 0.1 (one final rounding)
// Accurate for binary Number inputs; not exact decimal-money arithmetic.

// Uint8Array ⇄ base64/hex (ES2026)
Uint8Array.fromBase64('SGVsbG8=')
bytes.toBase64()
bytes.toHex()

// Map upsert (ES2026)
map.getOrInsert(key, [])                    // insert default if absent
map.getOrInsertComputed(key, k => make(k))  // lazy default

// Iterator.concat (ES2026)
Iterator.concat(iterA, iterB).toArray()

// JSON source access (ES2026)
JSON.parse(text, (k, v, ctx) => k === 'id' ? BigInt(ctx.source) : v)
JSON.stringify({ id: JSON.rawJSON('12345678901234567890') })

// Intl.DurationFormat (ECMA-402 Intl API)
new Intl.DurationFormat('en', { style: 'long' })
  .format({ hours: 1, minutes: 30 })  // "1 hour, 30 minutes"

// Temporal API (Stage 4 → expected ES2027; native in Firefox 139+,
// Chrome 144+, official Node 26 builds; feature-detect custom Node builds
// and use a maintained polyfill elsewhere)
Temporal.PlainDate.from('2024-03-15')     // Date only
Temporal.PlainTime.from('14:30:00')       // Time only
Temporal.PlainDateTime.from('2024-03-15T14:30:00')            // Date + time
Temporal.ZonedDateTime.from('2024-03-15T14:30:00[America/New_York]')  // With timezone
Temporal.Now.instant()                     // Current moment
Temporal.Duration.from({ hours: 2 })       // Duration
date.add({ months: 1 })                    // Immutable arithmetic

Post-ES2026 and Toolchain Features

// Decorators (Stage 2.7 as of 2026-08; requires a pinned transform)
@logged
class User {
  @validate name;
  @memoize getData() { }
}

// Decorator Metadata (Stage 2.7; requires compatible Symbol.metadata)
User[Symbol.metadata]  // { name: 'string', ... }

// Joint iteration (Stage 4 → expected ES2027)
Iterator.zip([[1, 2], ['a', 'b']]).toArray()
// [[1, 'a'], [2, 'b']]

// Atomics.pause (Stage 4 → expected ES2027; native engine hint only)
if (typeof Atomics.pause === 'function') Atomics.pause()

Quick Migration Guide

Legacy Modern
var x = 1 const x = 1 or let x = 1
function(x) { return x * 2 } x => x * 2
arr[arr.length - 1] arr.at(-1)
arr.sort() arr.toSorted()
arr.reverse() arr.toReversed()
arr.splice(i, 1) arr.toSpliced(i, 1)
arr[i] = val arr.with(i, val)
str.replace(/a/g, 'b') str.replaceAll('a', 'b')
obj.hasOwnProperty('k') Object.hasOwn(obj, 'k')
a && a.b && a.b.c a?.b?.c
x || 'default' x ?? 'default'
Object.assign({}, a, b) { ...a, ...b }
[].concat(a, b) [...a, ...b]
.then().catch() async/await + try/catch
let resolve; new Promise(r => resolve = r) Promise.withResolvers()
Ambiguous date/time model Select the correct Temporal type when native or intentionally polyfilled; keep Date for required platform interop
Manual grouping with reduce Object.groupBy()

Source: SKILL.md on GitHub

No alerts14d4 checks · Risk SAFE
  • Gen Agent Trust Hub14d

    The skill provides a technical reference for modern JavaScript features and toolchains. It includes an indirect prompt injection surface by directing the agent to read and analyze project files, such as lockfiles and build configurations, which may contain untrusted data that could influence the agent's code generation logic.

  • Socket14d

    No alerts

  • Snyk14d

    Risk: LOW · No issues

  • Runlayer7mo

    12 files scanned · No issues

Signed by skilld at 00695ba. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 3 weeks ago.

Activeupdated 3 weeks ago

README badge

README badge for ccheney/robust-skills/modern-javascript