Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Cheat Sheets
  3. JavaScript
  4. JavaScript ES6+ Features Cheat Sheet
JavaScriptCheat Sheet

JavaScript ES6+ Features Cheat Sheet

Quick-reference for modern JavaScript features from ES6 through ES2024. Each section includes copy-ready snippets with inline output comments.

On this page
  1. 1Object Destructuring
  2. 2Array Destructuring
  3. 3Spread and Rest Operators
  4. 4Template Literals
  5. 5Arrow Functions
  6. 6Default Parameters
  7. 7Optional Chaining (?.) and Nullish Coalescing (??)
  8. 8Logical Assignment (||=, &&=, ??=)
  9. 9Modules: import/export
  10. 10Symbol and Iterators
  11. 11WeakMap and WeakSet
  12. 12More Modern Features
Object DestructuringArray DestructuringSpread and Rest OperatorsTemplate LiteralsArrow FunctionsDefault ParametersOptional Chaining (?.) and Nullish Coalescing (??)Logical Assignment (||=, &&=, ??=)Modules: import/exportSymbol and IteratorsWeakMap and WeakSetMore Modern Features

Object Destructuring

Extract properties from objects into variables. Supports renaming, defaults, and nesting.

Basic object destructuring
const user = { name: 'Alice', age: 30, role: 'admin' };
const { name, age } = user;
name  // => 'Alice'
age   // => 30
Rename and defaults
const { name: userName, email = 'N/A' } = { name: 'Bob' };
userName  // => 'Bob'
email     // => 'N/A'
Nested destructuring
const config = { db: { host: 'localhost', port: 5432 } };
const { db: { host, port } } = config;
host  // => 'localhost'
port  // => 5432
Rest in objects
const { id, ...rest } = { id: 1, name: 'Alice', age: 30 };
id    // => 1
rest  // => { name: 'Alice', age: 30 }

Array Destructuring

Extract elements by position. Supports skipping, defaults, rest, and swapping.

Basic array destructuring
const [a, b, c] = [1, 2, 3];
a  // => 1
b  // => 2
c  // => 3
Skip elements
const [, , third] = ['a', 'b', 'c'];
third  // => 'c'
Rest elements
const [head, ...tail] = [1, 2, 3, 4, 5];
head  // => 1
tail  // => [2, 3, 4, 5]
Swap variables
let x = 1, y = 2;
[x, y] = [y, x];
x  // => 2
y  // => 1
Destructure function returns
function getRange() {
  return [0, 100];
}
const [min, max] = getRange();

Spread and Rest Operators

Spread (...) expands iterables into individual elements. Rest (...) collects remaining elements into an array or object.

Spread arrays
const a = [1, 2];
const b = [3, 4];
[...a, ...b]          // => [1, 2, 3, 4]
[0, ...a, 5]          // => [0, 1, 2, 5]
Spread objects
const defaults = { theme: 'dark', lang: 'en' };
const prefs = { lang: 'fr', fontSize: 14 };
const merged = { ...defaults, ...prefs };
// => { theme: 'dark', lang: 'fr', fontSize: 14 }

Later spreads overwrite earlier ones. Spread only makes a shallow copy — nested objects are still shared references.

Rest parameters in functions
function sum(...nums) {
  return nums.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3)  // => 6
Spread into function arguments
const args = [1, 5, 3, 9, 2];
Math.max(...args)  // => 9

Template Literals

Backtick strings support interpolation, multiline text, and tagged templates.

String interpolation
const name = 'Alice';
const greeting = `Hello, ${name}!`;  // => 'Hello, Alice!'
`Total: $${(9.99 * 3).toFixed(2)}`   // => 'Total: $29.97'
Multiline strings
const html = `
  <div>
    <h1>${title}</h1>
    <p>${content}</p>
  </div>
`;
Tagged templates
function highlight(strings, ...values) {
  return strings.reduce((acc, str, i) =>
    acc + str + (values[i] !== undefined ? `<b>${values[i]}</b>` : ''), ''
  );
}

const name = 'Alice';
highlight`Hello, ${name}!`
// => 'Hello, <b>Alice</b>!'

Tags receive string parts and interpolated values separately. They do NOT auto-escape — your tag function must handle sanitization.

String.raw — no escape processing
String.raw`\n\t`          // => '\\n\\t' (literal backslashes)
String.raw`C:\Users\docs`  // => 'C:\\Users\\docs'

Arrow Functions

Concise function syntax with lexical this binding. No own this, arguments, or prototype.

Basic arrow syntax
const double = (x) => x * 2;
const add = (a, b) => a + b;
const greet = () => 'hello';
Multi-line body (needs return)
const process = (items) => {
  const filtered = items.filter(Boolean);
  return filtered.map(x => x.toUpperCase());
};
Return object literal (wrap in parens)
const makeUser = (name) => ({ name, role: 'user' });
makeUser('Alice')  // => { name: 'Alice', role: 'user' }

Without parentheses, { } is a block body, not an object. Wrap in () to return an object literal.

Lexical this (no own this)
class Timer {
  constructor() {
    this.seconds = 0;
    // Arrow inherits `this` from constructor
    setInterval(() => {
      this.seconds++;  // `this` is the Timer instance
    }, 1000);
  }
}

Arrow functions inherit this from the enclosing scope. Regular functions create their own this based on how they are called.

Default Parameters

Set fallback values for function parameters. Defaults are evaluated at call time, not definition time.

Basic defaults
function greet(name = 'World') {
  return `Hello, ${name}!`;
}
greet()         // => 'Hello, World!'
greet('Alice')  // => 'Hello, Alice!'
Defaults with destructuring
function createUser({ name = 'Anonymous', role = 'user' } = {}) {
  return { name, role };
}
createUser()                    // => { name: 'Anonymous', role: 'user' }
createUser({ name: 'Alice' })  // => { name: 'Alice', role: 'user' }
Defaults trigger on undefined, not null
function show(x = 10) {
  return x;
}
show(undefined)  // => 10 (default used)
show(null)       // => null (NOT default)
show(0)          // => 0 (NOT default)

Only undefined triggers the default. null, 0, and "" are valid values that bypass the default.

Optional Chaining (?.) and Nullish Coalescing (??)

Safely access nested properties and provide defaults for null/undefined without falsy confusion.

Optional chaining for nested access
const user = { address: { city: 'NYC' } };
user?.address?.city       // => 'NYC'
user?.profile?.avatar     // => undefined (no error)
user?.getEmail?.()        // => undefined (safe method call)
Optional chaining with arrays
const data = { items: ['a', 'b'] };
data?.items?.[0]    // => 'a'
data?.missing?.[0]  // => undefined
Nullish coalescing (??)
null ?? 'default'       // => 'default'
undefined ?? 'default'  // => 'default'
0 ?? 'default'          // => 0 (not nullish!)
'' ?? 'default'         // => '' (not nullish!)
false ?? 'default'      // => false (not nullish!)

?? only checks null/undefined. || checks all falsy values (0, "", false, null, undefined, NaN). Use ?? when 0 or "" are valid values.

Combined pattern
const port = config?.server?.port ?? 3000;
const name = user?.profile?.name ?? 'Anonymous';

Logical Assignment (||=, &&=, ??=)

Shorthand for assigning values based on logical conditions. ES2021.

??= (assign if nullish)
let config = { timeout: null };
config.timeout ??= 5000;
config.timeout  // => 5000

let port = 8080;
port ??= 3000;
port  // => 8080 (not nullish, keeps value)
||= (assign if falsy)
let name = '';
name ||= 'Anonymous';
name  // => 'Anonymous' (empty string is falsy)

let count = 0;
count ||= 10;
count  // => 10 (0 is falsy — probably a bug!)

Use ??= when 0, false, or "" are valid values. Use ||= when you want to replace any falsy value.

&&= (assign if truthy)
let user = { name: 'Alice' };
user.name &&= user.name.toUpperCase();
user.name  // => 'ALICE'

let empty = '';
empty &&= 'replaced';
empty  // => '' (falsy, not assigned)

Modules: import/export

ES modules use static import/export for code organization. Named exports allow multiple values; default exports provide a single main export.

Named exports
// math.js
export const PI = 3.14159;
export function add(a, b) { return a + b; }

// main.js
import { PI, add } from './math.js';
Default export
// logger.js
export default function log(msg) {
  console.log(msg);
}

// main.js
import log from './logger.js';
Rename imports
import { add as sum } from './math.js';
import * as math from './math.js';
math.add(1, 2)  // => 3
Dynamic import (lazy loading)
const { default: Chart } = await import('./chart.js');
// Module loaded on demand, not at startup

Dynamic import() returns a Promise and can be used anywhere. Static import must be at the top level.

Symbol and Iterators

Symbols create unique, non-string property keys. Built-in symbols like Symbol.iterator power the for...of loop.

Creating and using symbols
const id = Symbol('id');
const user = { [id]: 123, name: 'Alice' };
user[id]               // => 123
Object.keys(user)      // => ['name'] (symbols hidden)
Well-known symbols
// Symbol.iterator makes an object iterable
const range = {
  from: 1,
  to: 5,
  [Symbol.iterator]() {
    let current = this.from;
    const last = this.to;
    return {
      next() {
        return current <= last
          ? { value: current++, done: false }
          : { done: true };
      }
    };
  }
};

[...range]  // => [1, 2, 3, 4, 5]
Symbol.for() — global symbol registry
const s1 = Symbol.for('app.id');
const s2 = Symbol.for('app.id');
s1 === s2  // => true (same global symbol)

WeakMap and WeakSet

Weak collections hold object references without preventing garbage collection. Keys must be objects, and entries are not enumerable.

WeakMap — private data pattern
const privateData = new WeakMap();

class User {
  constructor(name) {
    privateData.set(this, { name });
  }
  getName() {
    return privateData.get(this).name;
  }
}
// When a User instance is GC'd, its WeakMap entry is too
WeakMap — cache/memoize
const cache = new WeakMap();
function expensiveCompute(obj) {
  if (cache.has(obj)) return cache.get(obj);
  const result = /* heavy work */ obj;
  cache.set(obj, result);
  return result;
}
WeakSet — track visited objects
const visited = new WeakSet();
function traverse(node) {
  if (visited.has(node)) return;  // prevent cycles
  visited.add(node);
  // process node...
}

WeakMap/WeakSet cannot be iterated (no forEach, no size). Use Map/Set if you need enumeration.

More Modern Features

Additional ES2020+ features that improve everyday code.

Object shorthand properties and methods
const name = 'Alice';
const age = 30;
const user = { name, age };     // => { name: 'Alice', age: 30 }

const obj = {
  greet() { return 'hello'; },  // shorthand method
  ['key' + 1]: 'dynamic',      // computed property
};
for...of loop
for (const char of 'hello') {
  console.log(char);  // h, e, l, l, o
}

for (const [key, val] of new Map([['a', 1], ['b', 2]])) {
  console.log(`${key}: ${val}`);
}
Structured clone (deep copy)
const original = { a: 1, nested: { b: 2 } };
const deep = structuredClone(original);
deep.nested.b = 99;
original.nested.b  // => 2 (unaffected)

structuredClone handles nested objects, arrays, Date, Map, Set, and more. Does not clone functions or DOM nodes.

Promise.withResolvers() (ES2024)
const { promise, resolve, reject } = Promise.withResolvers();
// Expose resolve/reject outside the Promise constructor
setTimeout(() => resolve('done'), 1000);
await promise  // => 'done'
Learn JavaScript in Depth
JavaScript Collections Practice →JavaScript Functions Practice →JavaScript Modules & Scope Practice →
See Also
Array Methods →Async/Await →Object Methods →

Start Practicing JavaScript

Free daily exercises with spaced repetition. No credit card required.

← Back to JavaScript Syntax Practice
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.