JavaScript Destructuring Assignments

When JavaScript developers speak of destructuring, they are referring to the destructuring assignment. Destructuring is a great language feature that has been introduced with ES6 and therefore is available since June 2015.

Syntax Of Destructuring Assignments

On the left side of the assignment, you have a list of variables in square brackets or curly braces. On the right side, you can have any iterable. The iterable can be an array or an object, for example. But let's look at more concrete examples in the next sections.

JavaScript Array Destructuring

Imagine we have an array of three values that we want to assign to three different variables to make our code more readable. We would have done something like this before we had the destructuring assignment in JavaScript.

const someValues = ['Tick', 'Trick', 'Track']
const first = someValues[0]
const second = someValues[1]
const third = someValues[2]

first    // 'Tick'
second   // 'Trick'
third    // 'Track'

With a destructuring assignment, we can write this more concise and make it more readable as well.

const someValues = ['Tick', 'Trick', 'Track']
const [first, second, third] = someValues

first    // 'Tick'
second   // 'Trick'
third    // 'Track'

someValues is an array and, therefore, an iterable.

JavaScript Object Destructuring

Because an object is also iterable, we can destructure objects in JavaScript. The syntax looks similar to the syntax of array destructuring.

const point = { x: 5, y: 10 }
const { x: x, y: y } = point

x    // 5
y    // 10

The names of the property and the name of the variable we are binding do not have to match. We can provide any name we like to the variables. If we think that the names x and y are not expressive enough, we can write something like this:

const point = { x: 5, y: 10 }
const { x: coordinateX, y: coordinateY } = point

coordinateX    // 5
coordinateY    // 10

If we are happy with the naming of the property and want the same name for our new variable, we can write more concise code.

const point = { x: 5, y: 10 }
const { x, y } = point

x    // 5
y    // 10

Destructuring With Iterables

We have seen that objects and arrays can be destructured because they are iterable. But there are many other iterables in JavaScript. For example, you can destructure characters from a string.

const [firstChar, secondChar, thirdChar] = 'abc'

firstChar    // 'a'
secondChar   // 'b'
thirdChar    // 'c'

You can also skip over items returned from the iterator. For example, when we are not interested in the first two items, we can skip over them.

const [, , thirdChar] =  'abc'


Another iterable you can destructure from is a generator function.

function* name() {
  yield 'Tick'
  yield 'Trick'
  yield 'Track'

const [first, second, third] = name()


Destructuring Function Arguments

We can create better APIs for our functions when using destructuring assignment. Instead of relying on argument order, we can pass objects to our functions. This way, we can use the attribute names and do not have to rely on the attributes' order.

const fullName = ({ first, last }) => `${first} ${last}`

fullName({ first: 'Jack', last: 'Sparrow'})     // 'Jack Sparrow'
fullName({ last: 'Swann', first: 'Elizabeth'})  // 'Elizabeth Swann'

The order of object attributes does not matter; it only matters that we provide an attribute first and an attribute last. Therefore the interface is more resilient to errors.

Destructuring And Default Values

The iterable you want to destructure from may have not enough values. Any variables for which no values can be assigned will be undefined.

const [foo, bar, baz] = [1, 2]
foo    // 1
bar    // 2
baz === undefined    // true

You can provide a default value to avoid a variable being undefined when destructuring.

const [foo, bar, baz = 0] = [1, 2]
foo    // 1
bar    // 2
baz    // 0

Destructuring And The Rest Parameter

Sometimes you might be interested in some values but still want to keep the unassigned values. You can collect unassigned values with the rest parameter.

const [foo, bar,] = [1, 2, 3, 4, 5]
foo     // 1
bar     // 2
rest    // [ 3, 4, 5 ]

You certainly can use destructuring with the rest parameter and objects as well.

const { x, y, } = { x: 1, y: 10, z: 20 }

x       // 1
y       // 10
rest    // { z: 20 }

JavaScript Destructuring Tricks

Functions With Multiple Return Values

Imagine you want to write a function that stores a value and gives you a getter function with which you can get the value you stored and a setter function that allows you to change the store's value. But you do not want to have generic names for the getter and setter functions.

function store(initialValue) {
  let value = initialValue
  return [() => value, (v) => { value = v; return }]

const [count, setCount] = store(20)
const [name, setName] = store('John')

count()       // 20
count()       // 3
name()        // 'John'

The function store() accepts an initial value and returns an array with the first item being the getter function and the second item being the setter function. This implementation has the benefit that we can name the getters and setter how we like.

Swapping Two Variables

We can use a destructuring assignment to swap two variables in JavaScript.

let a = 1, b = 2;    // The semicolon is needed in RunJS.

[a, b] = [b, a]

a // => 2
b // => 1

Create An Array Of Chars From a String

const [...chars] = 'hello'

chars    // [ 'h', 'e', 'l', 'l', 'o' ]


JavaScript destructuring assignment is another cool language feature introduced in ES6.

In this article, we learned the basics of destructuring in JavaScript. But you can do a lot more with it, which has not been mentioned in this article. For example, destructuring deeply nested objects is something I left out intentionally. Although destructuring is an essential addition to the language, I think that we need to be careful to keep the code we write readable.

Posted on CuteMachine.

Jo's Profile ImageWritten by Jo who lives and works in Frankfurt building digital doodah. Stalk him on Twitter.

TOS • Privacy • Disclaimer