ES6 gives us a new way of assigning values using pattern matching allowing us to destructure objects and arrays to the smaller pieces that we require. This gives us a more expressive way mapping values from one object to smaller variables.

Array Destructuring

Array Matching allows us to destructure and assign parts of our array into individual variables. As an example:

1
2
3
4
let pointVals = [1,2]
let [x, y] = pointVals
console.log(x) // 1
console.log(y) // 2

This is equivalent to doing this in ES5:

1
2
3
4
5
var pointVals = [1, 2]
var x = pointVals[0]
var y = pointVals[1]
console.log(x) // 1
console.log(y) // 2

Default values

Default values can be assigned if needed.

1
2
3
4
let pointVals = [1]
let [x, y = 3] = pointVals
console.log(x) // 1
console.log(y) // 3

Skipping

When destructuring an array, you’re able to skip certain parts of an array by simply adding a comma “,” in place of the index of the item that you want to skip. See example:

1
2
3
4
let vals = [1,2,3]
let [x, ,y] = vals
console.log(x) // 1
console.log(y) // 3

Deep Array

Another great thing about Array matching is that you’re able to further dive down deeper into array of arrays (multi-dimensional arrays).

1
2
3
4
5
let vals = [1, 2, ['a', 'b', 'c'], 3]
let [num1, num2, [alpha1, alpha2, alpha3], num3] = vals
console.log(alpha1) // a
console.log(alpha2) // b
console.log(alpha3) // c

This even works with rest.

1
2
3
let vals = [1, 2, ['a', 'b', 'c'], 3]
let [num1, num2, [...alphas], num3] = vals
console.log(alphas) // ['a', 'b', 'c']

Works on any Iterable Object

This isn’t really strictly only applicable to Array’s, but any Iterable Object.

1
2
3
4
5
6
let pointVals = "abcde"
let [a, b, c, ,e ] = pointVals
console.log(a) // a
console.log(b) // b
console.log(c) // c
console.log(e) // e

Object Destructuring

You can destructure object’s using the following syntax:

1
2
3
4
let point = { x: 1, y: 2 }
let { x, y } = point // -> destructure
console.log(x) // 1
console.log(y) // 2

So in this case, we’re simply mapping properties x and y to variables named the same as the properties within the object we are wanting to destructure.

We can also assign the destructured properties to different variable names:

1
2
3
4
let point = { x: 1, y: 2 }
let { x: a, y: b, c = 10 } = point // -> destructure
console.log(a) // 1
console.log(b) // 2

WARNING: Right is the new Left

AssignmentProperty : PropertyName : AssignmentElement
Let name be the result of evaluating PropertyName.
ReturnIfAbrupt(name).
Return the result of performing KeyedDestructuringAssignmentEvaluation of AssignmentElement with value and name as the arguments.
ECMA-262 7.0

The KEY thing is the first line of the expression specification for AssignmentProperty - “Let name be the result of evaluating PropertyName

This means that what the left hand side PropertyName is the property we are assigning to AssignmentElement.

When we think about the expression’s specification, it does seem wrong that the assignment element is on the right hand side rather than the left. We have been trained to always look at the left for what we’re trying to assign to and the right where we are getting the value from.

This will confuse the hell out of people coming to ES6 regardless of their programming background.

Mixed

You can mix and nest the destructure expression to extract any part of an Object or Array.

1
2
3
4
5
6
7
8
9
10
let obj = { 
  a: 1, 
  b:2, 
  c: ['a', 'b', 'c', 'd'] 
}

let { a, b, c: [...c] } = obj
console.log(a)
console.log(b)
console.log(c)

Destructuring arguments in a Function

Arguments can be destructured as they are passed. This is amazing to see as you’re now able to be much more expressive as to what’s required by a function.

1
2
3
4
5
6
7
8
9
10
11
12
13
let printPosition = ({ x, y }) =>  {
  console.log(`x: ${x}, y: ${y}`)
}

let points = [
  { x: 1, y: 2 },
  { x: 3, y: 4 },
  { x: 5, y: 6 },
  { x: 7, y: 8 },
  { x: 9, y: 10 },
]

points.forEach((point) => printPosition(point))

Destructuring Computed Property Name

You can destructure computed (or dynamic) property names like this:

1
2
3
let myDynamicName = 'a'
let { a } = { a : '1' }
console.log(a) // 1

Point to remember

An easy thing to miss is the changing usage of square brackets “[]” for an Array or any Iterable Object and curly braces “{}” for destructuring an Object.

Caveats

Watch out for undefined. If no value can be assigned to the property name or Iterable index you are attempting to destructure and assign to a variable, then undefined will be assigned to the variable.

1
2
3
let { a, b } = { b: 2 }
console.log(a) // undefined
console.log(b) // 2