JavaScript Cheatsheet
At a glance
| What it is | The language of the web, standardized as ECMAScript (ECMA-262) by TC39, and runs in browsers, Node.js, Deno and Bun |
| Use it for | Browser UIs, servers and APIs (Node.js), tooling and scripts, serverless functions |
| Latest stable | ECMAScript 2026 (ECMA-262 17th edition, approved 2026-06-30) - checked 2026-10-31 |
| Official docs | ECMA-262 spec · MDN JavaScript · TC39 proposals |
Core concepts
- Primitives vs objects:
string,number,bigint,boolean,undefined,null,symbolare immutable values. Everything else is an object passed by reference. - Scope:
let/constare block-scoped and sit in the temporal dead zone until declared.varis function-scoped and hoisted. - Closures: a function keeps access to the variables of the scope it was created in.
this: set by the call site (obj.fn()), bynew, or bycall/apply/bind. Arrow functions takethisfrom the enclosing scope.- Prototypes: objects inherit through the prototype chain.
classis syntax on top of it. - Event loop: one call stack. Microtasks (promises,
queueMicrotask) all run before the next macrotask (setTimeout, I/O, events). - Equality:
===compares without coercion.Object.isalso treatsNaNas equal to itself and+0as different from-0. - Modules: ES modules (
import/export) are strict, static and live-bound. CommonJS (require) is the older Node.js format. - Truthiness: falsy values are
false,0,-0,0n,"",null,undefined,NaN. Everything else is truthy.
Syntax & commands
// Variables, destructuring, spread, defaults
const { id, name = "anon", ...rest } = user;
const [first, , third = 0] = list;
const merged = { ...defaults, ...overrides };
const copy = structuredClone(deepObject); // deep copy
// Optional chaining, nullish coalescing, logical assignment
const city = user?.address?.city ?? "unknown";
settings.theme ??= "light";
count ||= 1;
// Functions
const add = (a, b = 0) => a + b;
function sum(...nums) { return nums.reduce((t, n) => t + n, 0); }
// Arrays: non-mutating helpers
arr.map(fn).filter(Boolean).reduce((acc, x) => acc + x, 0);
arr.at(-1); // last item
arr.toSorted((a, b) => a - b); // copy, original untouched
arr.toReversed(); arr.toSpliced(1, 1); arr.with(0, "x");
arr.findLast(fn); arr.findLastIndex(fn);
Object.groupBy(users, (u) => u.role); // { admin: [...], user: [...] }
Array.from({ length: 3 }, (_, i) => i); // [0, 1, 2]
// Objects
Object.entries(obj).map(([k, v]) => `${k}=${v}`);
Object.fromEntries(map);
Object.hasOwn(obj, "key");
// Classes
class Counter {
#count = 0; // private field
static create() { return new Counter(); }
get value() { return this.#count; }
inc() { this.#count++; return this; }
}
// Async
const res = await fetch(url, { signal: AbortSignal.timeout(5000) });
const data = await res.json();
const [a, b] = await Promise.all([getA(), getB()]); // fail fast
const results = await Promise.allSettled([p1, p2]); // never rejects
const fastest = await Promise.any([mirror1, mirror2]); // first fulfilled
const { promise, resolve, reject } = Promise.withResolvers();
for await (const chunk of stream) process(chunk);
// Modules
export const PI = 3.14;
export default function main() {}
import main, { PI } from "./math.js";
const { heavy } = await import("./heavy.js"); // lazy load
import config from "./config.json" with { type: "json" }; // import attributes
Common patterns
| Need | Pattern |
|---|---|
| Debounce input | clearTimeout(t); t = setTimeout(fn, 300) |
| Unique values | [...new Set(arr)] |
| Set math (ES2025) | a.union(b), a.intersection(b), a.difference(b), a.isSubsetOf(b) |
| Count / cache by key (ES2026) | map.getOrInsert(key, 0), map.getOrInsertComputed(key, () => compute()) |
| Lazy pipelines (ES2025) | iter.values().filter(fn).map(fn).take(10).toArray() |
| Safe sync-or-async call (ES2025) | Promise.try(() => maybeThrows()) |
| Cancel a request | const ac = new AbortController(); fetch(url, { signal: ac.signal }); ac.abort(); |
| Deep clone | structuredClone(value) (no functions or DOM nodes) |
| Format numbers / dates | new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }).format(n) |
| Retry with backoff | loop with await new Promise(r => setTimeout(r, 2 ** i * 100)) |
// Error handling with cause
try {
await saveUser(user);
} catch (err) {
throw new Error("Saving user failed", { cause: err });
}
Gotchas
0.1 + 0.2 !== 0.3. Use integers (cents) orMath.sumPrecise(ES2026) for sums of floats.typeof null === "object"andtypeof [] === "object". UseArray.isArrayandvalue === null.arr.sort()sorts as strings by default and mutates. Pass a compare function or usetoSorted.parseInt("08abc")returns8.Number("08abc")returnsNaN. Pick the one you mean.forEachdoes not wait forasynccallbacks. Usefor...ofwithawait, orPromise.all(arr.map(...)).- Losing
this:const f = obj.method; f()has noobj. Bind it or use an arrow wrapper. JSON.stringifydropsundefined, functions and symbols, and throws onBigIntand circular references.new Date("2026-01-02")is parsed as UTC, whilenew Date(2026, 0, 2)is local time, with months starting at 0.==coerces types ("" == 0is true). Default to===.
What's new in recent releases
- ES2026 (June 2026):
Map/WeakMapgetOrInsert/getOrInsertComputed(upsert),Iterator.concat,Uint8Arraybase64/hex (toBase64,Uint8Array.fromBase64,toHex,fromHex),Math.sumPrecise,Error.isError,Array.fromAsync,RegExp.escape, andJSON.parsesource text access (context.sourcein revivers,JSON.rawJSON). - ES2025 (June 2025): iterator helpers (
.map,.filter,.take,.drop,.toArrayon iterators), newSetmethods, import attributes and JSON modules,Promise.try,Float16Array, RegExp modifiers and duplicate named capture groups. - ES2024:
Object.groupBy/Map.groupBy,Promise.withResolvers, resizableArrayBuffer, RegExpvflag. - Next (ES2027, already stage 4):
Temporaldate/time API and explicit resource management (using/await using). Node.js 26 already shipsTemporalon by default.