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
- Arrow Functions
- Destructuring
- Spread & Rest
- Template Literals
- Object Shorthand
- Optional Chaining & Nullish Coalescing
- Array Methods
- String Methods
- Object Methods
- Promises
- Async/Await
- Classes
- Modules
- Set & Map
- Iterators & Generators
- Regular Expressions
- Primitives, Errors, Cloning, Resource Management
- Post-ES2026 and Toolchain Features
- Quick Migration Guide
Variables & Scope
const x = 1; // Block-scoped, cannot reassign
let y = 2; // Block-scoped, can reassign
// var z = 3; // Function-scoped, avoidArrow 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]; // SwapSpread & 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 truthyArray 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 consumptionString 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() // ES2024Object 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) // ES2024Promises
// 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) // ES2018Async/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 arithmeticPost-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() |