Destructuring unpacks values from an object or array into separate variables in one step. You have already seen it in a few lessons (like for (const [key, value] of map)); this lesson covers every form of it. It does not change the original: destructuring only copies values out.
Put variable names in curly braces on the left. Each one is filled from the property with the same name:
const person = { firstName: "John", lastName: "Doe", age: 50 };
const { firstName, lastName } = person;
console.log(firstName, lastName);
That one line replaces const firstName = person.firstName; and const lastName = person.lastName;.
const person = { firstName: "John", lastName: "Doe", age: 50 };
const { lastName, firstName, country } = person;
console.log(firstName, lastName, country);
console.log(person); // unchanged
Object destructuring matches by name, not position. A name the object does not have simply gets undefined.
Give a fallback with =. It is used only when the value is undefined:
const person = { firstName: "John", lastName: "Doe", age: 50 };
const { firstName, country = "US" } = person;
console.log(firstName, country);
const { a = 1, b = 2 } = { a: null, b: undefined };
console.log(a, b); // null is a real value: no default
Use property: newName to store the value under a different variable name. You can add a default too:
const person = { firstName: "John", lastName: "Doe", age: 50 };
const { lastName: surname, country: home = "US" } = person;
console.log(surname, home);
{ lastName: surname } there is no variable called lastName; only surname exists. It reads backward from how an object literal looks, which trips everyone up at first.
...rest collects every property you did not name into a new object:
const person = { firstName: "John", lastName: "Doe", age: 50 };
const { age, ...names } = person;
console.log(age, names);
Use square brackets. Arrays are matched by position:
const fruits = ["Bananas", "Oranges", "Apples", "Mangos"];
const [fruit1, fruit2] = fruits;
console.log(fruit1, fruit2);
const [first, , , last] = fruits; // extra commas skip items
console.log(first, last);
const { [0]: a, [3]: d } = fruits; // or pick positions by index
console.log(a, d);
Defaults work here too, and missing positions are undefined:
const [x = 1, y = 2, z] = [10];
console.log(x, y, z);
const numbers = [10, 20, 30, 40, 50, 60, 70];
const [a, b, ...rest] = numbers;
console.log(a, b, rest);
The rest must come last: const [...start, end] = numbers; is SyntaxError: Rest element must be last element.
Array destructuring works on anything you can loop over with for...of: strings, Sets, Maps, and more.
const [a1, a2, a3] = "W3Schools";
console.log(a1, a2, a3);
const [firstTag] = new Set(["js", "css", "html"]);
console.log(firstTag);
const fruits = new Map([["apples", 500], ["bananas", 300]]);
for (const [key, value] of fruits) {
console.log(key + " is " + value);
}
const scores = { ava: 92, ben: 85 };
for (const [name, score] of Object.entries(scores)) {
console.log(`${name}: ${score}`);
}
let firstName = "John";
let lastName = "Doe";
[firstName, lastName] = [lastName, firstName];
console.log(firstName, lastName);
The right side builds a temporary array, and the left side unpacks it back in the opposite order. No third "temp" variable needed.
Patterns can go inside patterns to reach into nested data:
const user = { name: "Ava", address: { city: "Baltimore", zip: "21201" }, scores: [92, 85] };
const { address: { city }, scores: [firstScore] } = user;
console.log(city, firstScore);
user has no address, then const { address: { city } } = user; is TypeError: Cannot read properties of undefined (reading 'city'). Give the inner pattern a default: const { address: { city } = {} } = user; makes city simply undefined.
Destructuring in the parameter list lets a function take an "options object" with named values, in any order, with defaults:
function greet({ name, age = 0 }) {
return `${name} is ${age}`;
}
console.log(greet({ name: "Ava", age: 16 }));
console.log(greet({ name: "Ben" }));
Calling greet() with nothing crashes, because there is no object to unpack:
function greet({ name }) {
return "Hi " + name;
}
console.log(greet());
The fix is a default for the whole parameter: function greet({ name = "friend" } = {}).
A function can only return one value, but that value can be an array or object you destructure right away:
function minMax(list) {
return [Math.min(...list), Math.max(...list)];
}
const [low, high] = minMax([3, 9, 1]);
console.log(low, high);
For arrays this just works, as the swap showed. For objects, a statement that starts with { is read as a code block, so wrap the whole thing in parentheses:
let a, b;
({ a, b } = { a: 1, b: 2 });
console.log(a, b);
Without the parentheses, { a, b } = { a: 1, b: 2 }; is SyntaxError: Unexpected token '='.
| const { a, b } = obj | Properties by name |
| const { a: x } = obj | Rename a to x |
| const { a = 1 } = obj | Default when undefined |
| const { a, ...rest } = obj | Everything else in a new object |
| const [x, y] = arr | Items by position |
| const [x, , z] = arr | Skip an item |
| const [x, ...rest] = arr | Everything else in a new array |
| [x, y] = [y, x] | Swap two variables |
| function f({ a } = {}) | Named parameters with a safe default |
What does this log?
const [a, , b = 5, ...c] = [1, 2, undefined, 4, 5];
console.log(a, b, c);
1 5 [4, 5]. The 2 is skipped, the third item is undefined so the default 5 is used, and the rest collects the last two items.You want the lastName property stored in a variable called surname. Which is correct?
const { lastName = surname } = person;const { surname: lastName } = person;const { lastName: surname } = person;const { lastName as surname } = person;function show({ title }) { ... } crashes when called as show(). Why, and what is the fix?
undefined, and you cannot destructure undefined. Add a default object: function show({ title } = {}).pet, renaming one and giving another a default"Ada Lovelace".split(" ") into first and last{ width, height = width } and returns the area