JavaScript Destructuring Table

PatternWhat it doesField note
const {a, b} = objObject properties to variablesNames must match the keys - rename with a: newA
const [x, y] = arrArray items by positionOrder is the name - index does not matter, position does
const {a: renamed} = objExtract and renamea: renamed reads 'a into renamed'
const {c = 5} = objDefault when undefinedFires only for undefined - null passes through
const {a, ...rest} = objRest of the objectOmits a; rest is a fresh plain object
const [first, ...others] = arrHead and tailThe array idiom replacing slice for readability
function f({name, age})Parameter destructuringNamed-argument style for APIs - the biggest readability win
let a = 1, b = 2; [a, b] = [b, a]Variable swapNo temp variable; needs the semicolon before the line
const {p: {q}} = objNested extractionThrows if an intermediate level is null - optional chaining cannot help here
Reference: the MDN destructuring reference. The two facts that prevent most destructuring bugs: object patterns match KEY NAMES (rename with the colon, never the other way), and defaults fire only for undefined - a null value passes through and explodes at the next property access. Bottom line: destructuring function parameters is the single biggest readability upgrade in modern JavaScript - named options, one line, self-documenting APIs. Related tools: JS array methods table, classes table for the objects being unpacked, and equality table for the comparisons after extraction.

Destructuring is unpacking: one statement pulls values out of objects and arrays into named variables. The table below is the working nine - the patterns that cover real code, from the basic object and array forms to the parameter destructuring that makes APIs self-documenting.

Bottom line: object patterns match KEY NAMES (const {a} = obj reads the property a), and renaming goes left-to-right - const {a: renamed} means take a, call it renamed. Array patterns match POSITION - const [x, y] takes the first two items whatever they are. Mixing the two mental models is the source of every destructuring typo.

The honest part: the default-value feature fires only for undefined - const {c = 5} = {c: null} gives c the value null, not 5. And nested patterns throw when an intermediate level is missing: const {p: {q}} = {} is a TypeError, because you cannot read q of undefined. Optional chaining cannot help inside a pattern; guard the object first.

How to use

  1. Match the shape: objects unpack by key name, arrays unpack by position - the left side mirrors the data's structure.
  2. Add defaults for undefined-prone fields, and rename when the property name is ugly or collides in scope.
  3. Use parameter destructuring for option objects - function f({name, age = 18}) is a named-arguments API in one line.

Frequently asked questions

How does destructuring with renaming work?

The colon means INTO: const {a: renamed} = obj takes obj.a and stores it in a variable called renamed - read the colon as into. The property name comes first because it must match the object; the variable name is yours. Swapping them is the classic typo: {renamed: a} looks for a property literally called renamed. Arrays have no names, so array patterns never need this syntax.

When do default values in destructuring apply?

Only for undefined. const {c = 5} = {c: null} leaves c as null - the property exists, so the default never fires. This matters for APIs that return explicit nulls for missing data: strip nulls first, or use the nullish pattern (c ?? 5) after destructuring. The same rule covers parameters: function f({limit = 10}) gets 10 only when limit is absent - passing {limit: undefined} still yields 10, but {limit: null} yields null.

Why does nested destructuring throw on missing objects?

Because destructuring is sugar for property access: const {p: {q}} = obj compiles to obj.p.q - if obj.p is undefined, reading q of undefined is a TypeError. Defaults guard each LEVEL separately: const {p: {q} = {}} = obj gives p an empty default, and q then reads undefined. Optional chaining cannot appear inside a pattern, so deeply-nested API responses want a guard or a default at every level that might be missing.

Is parameter destructuring just syntax sugar?

Mechanically yes - function f({name, age = 18}) unpacks the first argument - but it changes the API design: callers pass a named-options object, order stops mattering, and every option is self-documenting at the call site ({name: 'Ada', age: 36}). Two production habits: destructure with defaults for every option, and keep one non-destructured argument for required primary data (function send(to, {subject, body})) - the hybrid keeps the required part impossible to omit.

Related tools