Javascript 101
2.7 Destructuring
2.7 Destructuring
Together with the rest and spread operators, ES6 also comes with a destructuring assignment capability. It allows easy matching of arrays or properties from objects and assigning them to variables.
Array Matching
It is possible to match and unpack variables from an array into variables. For
example, the following code snippet shows how we can assign the first value of
an array into a variable first
and assign the second value of the array into a
variable second
.
var array = [1, 2, 3, 4, 5];
var [first, second] = array;
console.log(first); //1console.log(second); //2
It is possible to skip one or more variables in the array.
var array = [1, 2, 3, 4, 5];
var [first, , third, , fifth] = array;
console.log(first); //1console.log(third); //3console.log(fifth); //5
It is also possible to use destructuring together with the rest operator.
var array = [1, 2, 3, 4, 5];
var [, , ...rest] = array;
console.log(rest); //[3, 4, 5]
Destructuring also provides an easy way to swap values of 2 variables.
//traditionally, we will define a temporary value for doing swappingvar num1 = 10;var num2 = 20;var temp;
//swappingtemp = num1;num1 = num2;num2 = temp;
console.log(num1); //20console.log(num2); //10
var num1 = 10;var num2 = 20;
//now with destructuring - just 1 statement!var [num1, num2] = [num2, num1];
console.log(num1); //20console.log(num2); //10
Object Matching
It is also possible to destructuring object properties.
var person = { firstName: "John", lastName: "Doe", age: 20 };
//assume we want the firstName the person object,//typically this is what we will do:var firstName = person.firstName;
//with destructuring:var { firstName } = person;
//this is equivalent to://var firstName = person.firstName;
console.log(firstName); //John
var person = { firstName: "John", lastName: "Doe", age: 20 };
//possible to destructure multiple propertiesvar { firstName, lastName } = person;
console.log(firstName); //Johnconsole.log(lastName); //Doe
var person = { firstName: "John", lastName: "Doe", age: 20 };
//if some properties should be const, should split//the variable declarationsconst { firstName, lastName } = person;let { age } = person;
console.log(firstName); //Johnconsole.log(lastName); //Doeconsole.log(age); //20
//possible to separate variable declaration from the assignmentvar person = { firstName: "John", lastName: "Doe", age: 20 };
//possible to destructure multiple propertiesvar firstName, lastName;
//must enclose with ( )({ firstName, lastName } = person);
console.log(firstName); //Johnconsole.log(lastName); //Doe
Notice that the destructured variables are taking the same name as the property of the object. It is also possible to declare and assign it to another variable name (i.e. "rename" the variable).
var person = { firstName: "John", lastName: "Doe", age: 20 };
var { firstName: fname, lastName: lname } = person;
console.log(fname); //Johnconsole.log(lname); //Doe
console.log(firstName); //Error: firstName is not undefined
It also works with property names with spaces.
var person = { "first name": "John", "last name": "Doe", age: 20 };
var { "first name": fname, "last name": lname } = person;
console.log(fname); //Johnconsole.log(lname); //Doe
While not common, it is possible to use the above "renaming" idea together with computed property names.
var key = "firstName";var { [key]: fname } = person;
console.log(fname); //John
//note that without computed property syntax we won't be able to do it//since the property will be wrongly treated as the property name:var { key: fname } = person;
//this will be same as:var fname = person.key;
Possible to use the rest operator with destructuring similar to array.
var person = { firstName: "John", lastName: "Doe", age: 20 };
var { age, ...rest } = person;
console.log(rest); //{firstName: "John", lastName: "Doe"}
On a separate note, it is possible to perform object destructuring on arrays.
const items = ["first", "second", "third", "fourth", "fifth"];const { 0: x, 4: y } = items;
console.log(x); //firstconsole.log(y); //fifth
Nested Array/Object Matching
Destructuring works with nested array/object.
var person = { name: { firstName: "John", lastName: "Doe", }, addresses: [{ address: "123 Mars Street" }, { address: "456 Rainbow Town" }],};
var { name: { firstName, lastName }, addresses: [firstAddress],} = person;
console.log(firstName); //Johnconsole.log(lastName); //Doeconsole.log(firstAddress); //{address: "123 Mars Street"}
The above ideas (renaming, rest, etc) works together with this.
var person = { name: { firstName: "John", lastName: "Doe", }, addresses: [{ address: "123 Mars Street" }, { address: "456 Rainbow Town" }],};
var { name: { firstName: fname },} = person;
console.log(fname); //John
Default values
Similar to default values for functions, it is possible to define default values when doing destructuring.
//assume the person is retrieved from an AJAX request//where some of the properties might be not definedvar person = { firstName: "John", age: 20 };
var { firstName, lastName } = person;
console.log(firstName + " " + lastName); //John undefined
//could define default values for the variablesvar { firstName = "", lastName = "" } = person;
console.log(firstName + " " + lastName); //John
The default value can be objects.
var person = { name: { firstName: "John", lastName: "Doe", }, addresses: [{ address: "123 Mars Street" }],};
var { name: { firstName: fname }, addresses: [, secondAddress = { address: "no second address" }],} = person;
console.log(secondAddress); //{address: "no second address"}
Function Parameter Matching
Destructuring can be used in function parameters. This allows more concise codes.
var person = { firstName: "John", lastName: "Doe", age: 20 };
//default value is empty string if either firstName//and/or lastName are not specifiedfunction printName({ firstName = "", lastName = "" }) { console.log(firstName + " " + lastName);}
printName(person); //John DoeprintName({ firstName: "Jane" }); //Jane
//however this will failprintName(); //error!
//can also specify a default value if no object//is specifiedfunction printName( { firstName = "", lastName = "" } = { firstName: "", lastName: "" }) { console.log(firstName + " " + lastName);}
//now okprintName(); //[empty string]
//but just take note that this will still failprintName(null); //Uncaught TypeError: null has no properties//should probably handle it in the body of function//and not use destructuring of function parameter if we//have this scenario
//previously without destructuring we would have to do this:function printName1(firstName = "", lastName = "") { console.log(firstName + " " + lastName);}
printName1(person.firstName, person.lastName); //John Doe//but this approach becomes more cumbersome with more properties
Whatever that is discussed before could be used together with destructuring for function parameters (e.g. specifying default values).
//array destructuringvar array = [1, 2, 3, 4, 5, 6];
function foo([first, second, ...rest]) { console.log("sum of first 2 values:", first + second);
function sumReducer(accumulator, currentValue) { return accumulator + currentValue; }
console.log("sum of the rest of the values:", rest.reduce(sumReducer, 0));}
foo(array);//sum of first 2 values: 3//sum of the rest of the values: 18