Skip to content
JavaScript Basics: Unpack Arrays and Objects

JavaScript Basics: Unpack Arrays and Objects

October 17, 2026

Destructuring names the pieces of a value that your code needs. Try positional array unpacking, renamed object fields, and nested records.

These examples use built-in features and were tested on Linux with Node.js v24.19.0. No packages are needed. Assertions check the results before the program finishes.

Prepare a scratch directory

You need Bash, a text editor, Node.js on your PATH, and the mktemp, rm, and rmdir utilities. Keep using the same terminal. These commands stop the shell if setup fails. Save each named source file as UTF-8; .mjs selects ES modules.

start_dir="$PWD"
work_dir="$(mktemp -d)" || exit 1
cd -- "$work_dir" || exit 1

1. Split an array into a first item and the rest

Save this as unpack-array.mjs:

import assert from 'node:assert/strict';

const priorities = ['urgent', 'normal', 'later'];
const [firstPriority, ...otherPriorities] = priorities;
assert.equal(firstPriority, 'urgent');
assert.deepEqual(otherPriorities, ['normal', 'later']);
otherPriorities.push('optional');
assert.equal(priorities.length, 3);
console.log(`First: ${firstPriority}`);
console.log(`Rest: ${otherPriorities.join(', ')}`);
console.log(`Original length: ${priorities.length}`);

Run it:

node unpack-array.mjs

Output:

First: urgent
Rest: normal, later, optional
Original length: 3

Array destructuring follows iteration order. The rest element creates a new array, but does not deeply copy nested objects. See the destructuring reference.

2. Rename a field and collect remaining properties

Save this as unpack-record.mjs:

import assert from 'node:assert/strict';

const record = { title: 'Draft', attempts: 0, owner: 'Mina' };
const { title: heading, attempts = 3, ...details } = record;
assert.equal(heading, 'Draft');
assert.equal(attempts, 0);
assert.deepEqual(details, { owner: 'Mina' });
console.log(`Heading: ${heading}`);
console.log(`Attempts: ${attempts}`);
console.log(`Details: ${JSON.stringify(details)}`);

Run it:

node unpack-record.mjs

Output:

Heading: Draft
Attempts: 0
Details: {"owner":"Mina"}

The colon renames title to the local variable heading; it does not change the original property. A default applies only when a value is undefined, including a missing property. It does not replace 0, false, an empty string, or null. Object rest copies remaining own enumerable properties.

3. Select a nested field

Save this as unpack-nested-record.mjs:

import assert from 'node:assert/strict';

const task = { title: 'Review', owner: { name: 'Mina', team: 'Platform' } };
const { title, owner: { name: ownerName } } = task;
assert.equal(title, 'Review');
assert.equal(ownerName, 'Mina');
assert.equal(task.owner.team, 'Platform');
assert.throws(() => {
  const { owner: { name } } = { title: 'Unassigned' };
  return name;
}, TypeError);
console.log(`Task: ${title}`);
console.log(`Owner: ${ownerName}`);
console.log('Missing owner object: rejected');

Run it:

node unpack-nested-record.mjs

Output:

Task: Review
Owner: Mina
Missing owner object: rejected

A nested pattern follows the object structure. Here it declares title and ownerName, not a variable named owner. The pattern expects an owner object: a missing or null owner throws. Destructuring does not validate an external record or make missing nested objects safe. Check its shape before unpacking it.

Clean up

In the same terminal, remove only the example files, return to your original directory, and remove the empty scratch directory:

rm -- unpack-array.mjs unpack-record.mjs unpack-nested-record.mjs
cd -- "$start_dir" || exit 1
rmdir -- "$work_dir"
unset start_dir work_dir

Acknowledgements

This post was created with assistance from AI.

Last updated on