Destructuring assignment is a special syntax that allows us to retrieve pieces of arrays or objects and assign them to separate variables.
This approach can be used for: arrays, objects, and iterables.
Let's start by taking a grasp of how arrays are destructured.
Consider the following example that doesn't use the pattern:
const numbers = [1, 2, 3];
const firstNumber = numbers[0];
const secondNumber = numbers[1];
const thirdNumber = numbers[2];
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "3"
Imagine having many arrays of much bigger size, code starts rapid growing.
Let's add some destructuring:
const numbers = [1, 2, 3];
const [firstNumber, secondNumber, thirdNumber] = numbers;
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "3"
Looks much, much cleaner.
Imagine having nested arrays. It is possible to destructure them as well:
const numbers = [1, 2, 3, [4, [5]]];
const [
firstNumber,
secondNumber,
thirdNumber,
[fourthNumber, [fifthNumber]],
] = numbers;
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "3"
console.log(fourthNumber); // Prints "4"
console.log(fifthNumber); // Prints "5"
Unwanted elements can be ignored by using commas:
const numbers = [1, 2, 3];
const [firstNumber, , thirdNumber] = numbers;
console.log(firstNumber); // Prints "1"
console.log(thirdNumber); // Prints "3"
In the example above, the second number is skipped.
You can capture all trailing items in an array with a "rest" pattern:
const numbers = [1, 2, 3];
const [firstNumber, ...rest] = numbers;
console.log(firstNumber); // Prints "1"
console.log(rest); // Prints "[2, 3]"
Destructuring non-existing element results in undefined
:
const numbers = [1, 2];
const [firstNumber, secondNumber, thirdNumber] = numbers;
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "undefined"
If you want the default value to replace non existing while destructuring, you can use the assignment operator:
const numbers = [1, 2];
const [firstNumber, secondNumber, thirdNumber = 3] = numbers;
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "3"
Default values can be more complex expressions (including function calls). They are evaluated only in case if the value is not provided:
const numbers = [1, 2, 3];
const [firstNumber, secondNumber, thirdNumber = 30] = numbers;
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "3"
In the example above, the assigned number 30
is ignored.
Objects are destructured exactly the same way as arrays, except the parentheses []
are replaced with curly braces {}
:
const user = {
name: "John",
surname: "Doe",
age: 18,
};
const {name, surname, age} = user;
console.log(name); // Prints "John"
console.log(surname); // Prints "Doe"
console.log(age); // Prints "18"
Important note: when destructuring objects, the order does not matter:
const user = {
name: "John",
surname: "Doe",
age: 18,
};
const {name, age, surname} = user;
console.log(name); // Prints "John"
console.log(surname); // Prints "Doe"
console.log(age); // Prints "18"
Nested objects can be destructured using the same pattern (curly braces {}
):
const user = {
name: "John",
surname: "Doe",
address: {
street: "John Doe street",
},
};
const {name, surname, address: { street }} = user;
console.log(name); // Prints "John"
console.log(surname); // Prints "Doe"
console.log(street); // Prints "John Doe street"
Important note: there is no variable address
as we take its context instead.
In order not to destructure property from an object, just don't put it inside the brackets, and that's it:
const user = {
name: "John",
surname: "Doe",
age: 18,
};
const {name, surname} = user;
console.log(name); // Prints "John"
console.log(surname); // Prints "Doe"
Trailing elements can be assigned to an object using "rest" pattern (like arrays, right?):
const user = {
name: "John",
surname: "Doe",
age: 18,
};
const {name: userName, ...rest} = user;
console.log(userName); // Prints "undefined"
console.log(rest); // Prints {surname: "Doe", age: 18}
Results in undefined
:
const user = {
surname: "Doe",
age: 18,
};
const {name: userName, surname: userSurname, age: userAge} = user;
console.log(userName); // Prints "undefined"
console.log(userSurname); // Prints "Doe"
console.log(userAge); // Prints "18"
The default value can be set using the assignment operator:
const user = {
surname: "Doe",
age: 18,
};
const {name = "John", surname, age} = user;
console.log(name); // Prints "John"
console.log(surname); // Prints "Doe"
console.log(age); // Prints "18"
Important note: default value can refer to any variable, including another variable in the same pattern:
const user = {
age: 18,
};
const {name = "John", surname = name, age} = user;
console.log(name); // Prints "John"
console.log(surname); // Prints "John"
console.log(age); // Prints "18"
Sometimes, you can face the situation, when the variable that you try to destructure value to, has already been declared.
In this case, you can destructure value into a variable with another name using the colon :
:
const user = {
name: "John",
surname: "Doe",
age: 18,
};
const {name: userName, surname: userSurname, age: userAge} = user;
console.log(userName); // Prints "John"
console.log(userSurname); // Prints "Doe"
console.log(userAge); // Prints "18"
There is one important thing to remember about - don't start destructuring operation with curly braces {}
:
const user = {
name: "John",
surname: "Doe",
age: 18,
};
{name, surname, age} = user; // SyntaxError: Unexpected token
Code blocks begin with a curly brace, statements must not begin with it.
We can create a function that accepts a single object with multiple properties as a parameter instead of many individual parameters.
Inside of such function, we can use access parameters by using destructuring:
const createUser = ({
name,
surname,
email,
password,
passwordConfirmation,
}) => {
// ...
};
const user = createUser({
name: "John",
surname: "Doe",
email: "john.doe@example.com",
password: "qwerty1234",
passwordConfirmation: "qwerty1234",
});
Without using parameters destructuring:
const createUser = (
name,
surname,
email,
password,
passwordConfirmation,
) => {
// ...
};
const user = createUser(
"John",
"Doe",
"john.doe@example.com",
"qwerty1234",
"qwerty1234",
);
Destructured function parameters can be given default value the exact same ways as objects or arrays:
const createUser = ({
name = "John",
surname,
email,
password,
passwordConfirmation,
}) => {
// ...
};
const user = createUser({
surname: "Doe",
email: "john.doe@example.com",
password: "qwerty1234",
passwordConfirmation: "qwerty1234",
});
The function can return multiple values (using an array literal), which can be destructured later on:
const example = () => [1, 2, 3];
const [firstNumber, secondNumber, thirdNumber] = example();
console.log(firstNumber); // Prints "1"
console.log(secondNumber); // Prints "2"
console.log(thirdNumber); // Prints "3"
undefined