DEV Community

Cover image for [JavaScript] 5 Interesting uses of JavaScript destructuring!
Yuma-Tsushima
Yuma-Tsushima

Posted on

[JavaScript] 5 Interesting uses of JavaScript destructuring!

Looking at my regular JavaScript code, I see that destructuring assignments are everywhere.

Reading object properties and accessing array items are frequent operations. The destructuring assignments make these operations so much easier and concise.

In this post, I will describe 5 interesting uses of destructuring in JavaScript, beyond the basic usage.

1) Swap variables

The usual way to swap 2 variables requires an additional temporary variable. Let’s see a simple scenario:

let a = 1;
let b = 2;
let temp;

temp = a;
a = b;
b = temp;

a; // => 2
b; // => 1
Enter fullscreen mode Exit fullscreen mode

temp is a temporary variable that holds the value of a. Then a is assigned with the value of b, and consequently b is assigned with temp.

The destructuring assignment makes the variables swapping simple, without any need of a temporary variable:

let a = 1;
let b = 2;

[a, b] = [b, a];

a; // => 2
b; // => 1
Enter fullscreen mode Exit fullscreen mode

[a, b] = [b, a] is a destructuring assignment. On the right side, an array is created [b, a], that is [2, 1]. The first item of this array 2 is assigned to a, and the second item 1 is assigned to b.

Although you still create a temporary array, swapping variables using destructuring assignment is more concise.

This is not the limit. You can swap more than 2 variables at the same time. Let’s try that:

let zero = 2;
let one = 1;
let two = 0;

[zero, one, two] = [two, one, zero];

zero; // => 0
one;  // => 1
two;  // => 2
Enter fullscreen mode Exit fullscreen mode

You can swap as many variables as you want! Although, swapping 2 variables is the most common scenario.

2) Access array item

You have an array of items that potentially can be empty. You want to access the first, second, or nth item of the array, but if the item does not exist, get a default value.

Normally you would use the length property of the array:

const colors = [];

let firstColor = 'white';
if (colors.length > 0) {
 firstColor = colors[0];
}

firstColor; // => 'white'
Enter fullscreen mode Exit fullscreen mode

Fortunately, array destructuring helps you achieve the same way shorter:

const colors = [];
const [firstColor = 'white'] = colors;

firstColor; // => 'white'
Enter fullscreen mode Exit fullscreen mode

const [firstColor = 'white'] = colors destructuring assigns to firstColor variable the first element of the colors array. If the array doesn’t have any element at the index 0, the 'white' default value is assigned.

Note the comma on the left side of the destructuring: it means that the first element is ignored. secondColor is assigned with the element at index 1 from the colors array.

3) Immutable operations

When I started using React, and later Redux, I was forced to write code that respects immutability. While having some difficulties at the start, later I saw its benefits: it’s easier to deal with unidirectional data flow.

Immutability forbids mutating objects. Fortunately, destructuring helps you achieve some operations in an immutable manner easily.

The destructuring in combination with ... rest operator removes elements from the beginning of an array:

const numbers = [1, 2, 3];

const [, ...fooNumbers] = numbers;

fooNumbers; // => [2, 3]
numbers; // => [1, 2, 3]
Enter fullscreen mode Exit fullscreen mode

The destructuring [, ...fooNumbers] = numbers creates a new array fooNumbers that contains the items from numbers but the first one.

numbers array is not mutated, keeping the operation immutable.

In the same immutable manner you can delete properties from objects. Let’s try to delete foo property from the object big:

const big = {
 foo: 'value Foo',
 bar: 'value Bar'
};

const { foo, ...small } = big;

small; // => { bar: 'value Bar' }
big; // => { foo: 'value Foo', bar: 'value Bar' }
Enter fullscreen mode Exit fullscreen mode

The destructuring assignment in combination with object rest operator creates a new object small with all properties from big, only without foo.

4) Destructuring iterables

In the previous sections, the destructuring was applied to arrays. But you can destructure any object that implements the iterable protocol.

Many native primitive types and objects are iterable: arrays, strings, typed arrays, sets, and maps.

const str = 'cheese';

const [firstChar = ''] = str;

firstChar; // => 'c'
Enter fullscreen mode Exit fullscreen mode

You’re not limited to native types. Destructuring logic can be customized by implementing the iterable protocol.

movies holds a list of movie objects. When destructuring movies, it would be great to get the movie title as a string. Let’s implement a custom iterator:

const movies = {
  list: [
    { title: 'Skyfall' }, 
    { title: 'Interstellar' }
  ],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.list.length) {
          const value = this.list[index++].title;
          return { value, done: false };
        }
        return { done: true };
      }
    };
  }
};

const [firstMovieTitle] = movies;
console.log(firstMovieTitle); // => 'Skyfall'
Enter fullscreen mode Exit fullscreen mode

movies object implements the iterable protocol by defining the Symbol.iterator method. The iterator iterates over the titles of movies.

Conforming to an iterable protocol allows the destructuring of movies object into titles, specifically by reading the title of the first movie: const [firstMovieTitle] = movies.

The sky is the limit when using destructuring with iterators.

5) Destructuring dynamic properties

In my experience, the destructuring of an object by properties happens more often than arrays destructuring.

The destructuring of an object looks pretty simple:

const movie = { title: 'Skyfall' };

const { title } = movie;

title; // => 'Skyfall'
Enter fullscreen mode Exit fullscreen mode

const { title } = movie creates a variable title and assigns to it the value of property movie.title.

When first reading about objects destructuring, I was a bit surprised that you don’t have to know the property name statically. You can destructure an object with a dynamic property name!

To see how dynamic destructuring works, let’s write a greeting function:

function greet(obj, nameProp) {
 const { [nameProp]: name = 'Unknown' } = obj;
 return `Hello, ${name}!`;
}

greet({ name: 'Ben' }, 'name'); // => 'Hello, Ben!'
greet({ }, 'name'); // => 'Hello, Unknown!'
Enter fullscreen mode Exit fullscreen mode

greet() function is called with 2 arguments: the object and the property name.

Inside greet(), the destructuring assignment const { [nameProp]: name = 'Unknown' } = obj reads the dynamic property name using square brackets [nameProp]. The name variable receives the dynamic property value.

Even better you can specify a default value 'Unknown' in case if the property does not exist.

Conclusion

Destructuring works great if you want to access object properties and array items.

On top of the basic usage, array destructuring is convinient to swap variables, access array items, perform some immutable operations.

JavaScript offers even greater possibilities because you can define custom destructuring logic using iterators.

Question: What interesting applications of destructuring do you know? Write a comment below!

Credits

48656c6c6f2045766572796f6e65

header

PROGRAMMERARTISTHACKER

About Me:

  • Name: Undisclosed
  • Alias: Yuma, V37R1X
  • Age: 19
  • Hobbies: Drawing, Hacking, Coding
  • Personality: INTJ-T 5w4 584 sp/sx RLOEI ILI Melancholic-Choleric LVFE

I am a/an:

CTFs:

HackTheBox

Coding:

Languages and Tools:

node javascript c# css html bash python git github latex linux md mongo mysql react vsc vim redux

Badges:

HackTheBox Hack The Box


TryHackMe

TryHackMe




BACK TO TOP

header






Follow me!

Discord Servers!!

Bounty Hunters: An amazing bug hunting community full of developers and exploiters!!!

CyberArtByte: My server full of bling and joy!!

New Soundcloud Track!!

Top comments (17)

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

The usual way to swap 2 variables requires an additional temporary variable.

Yet destructuring requires a temporary array, which my intuition tells me, is harder (not impossible, mind you) to optimise and has to be garbage-collected.


let firstColor = 'white';
if (colors.length > 0) {
 firstColor = colors[0];
}
Enter fullscreen mode Exit fullscreen mode

There's a much nicer way to do this without destructuring:

let firstColor = colors[0] ?? "white"
Enter fullscreen mode Exit fullscreen mode

or using || on older javascript versions.


const [, ...fooNumbers] = numbers;
Enter fullscreen mode Exit fullscreen mode

Again, there's a much more readable version of this without destructuring:

const fooNumbers = numbers.slice(1)
Enter fullscreen mode Exit fullscreen mode

const { foo, ...small } = big;
Enter fullscreen mode Exit fullscreen mode

That's actually a really good example where destructuring is the most readable way of doing it. That being said, one could always just write a function to do a similar thing:

drop = (object, drop) => Object.fromEntries(Object.entries(object).filter(([key]) => drop.indexOf(key)))
Enter fullscreen mode Exit fullscreen mode

Is it pretty? no, not really. But at least it's possible :D


Personally, I really like using destructuring for function arguments. You might have already spotted it in my drop() example above: instead of indexing the array in the function body, I let the function declaration take care of that, and then just work with the variables I actually want in the body.

Getting many values out of a nested data structure is also really nice this way:

let {name: {first: firstname, last: lastname}, address: {street}} = user
Enter fullscreen mode Exit fullscreen mode
Collapse
 
yumatsushima07 profile image
Yuma-Tsushima

To be honest I do use || for destructuring also.

let firstColor = colors[0] ?? "white"
Enter fullscreen mode Exit fullscreen mode

or using || on older javascript versions.

You did make some good points here thanks :)

const fooNumbers = numbers.slice(1)
Enter fullscreen mode Exit fullscreen mode

I do also like the way you did this.

:) Thanks again

Collapse
 
grahamthedev profile image
GrahamTheDev

Quick heads up - it looks like the paragraph at the end of section 2 belongs in section 3.

Great article and well explained! ❤️

Collapse
 
yumatsushima07 profile image
Yuma-Tsushima

Nice point out but I do like giving people a preview

Collapse
 
grahamthedev profile image
GrahamTheDev • Edited

Note the comma on the left side of the destructuring: it means that the first element is ignored. secondColor is assigned with the element at index 1 from the colors array.

That doesn’t lead in to the next section it is referencing a code snippet that is either missing (which after rereading, looks to be the case) or further down and part of section 3 but you changed the example. Either way it is definitely not right!

Or if you were being sarcastic and I missed it then feel free to r/whoosh me 😜🤣

Thread Thread
 
yumatsushima07 profile image
Yuma-Tsushima • Edited

ahahha

yeah I was being sarcastic , it was more of a trick

Thread Thread
 
bogdanbatsenko profile image
bogdanbatsenko

It was a trick to provoke thinking over again and getting to the bottom of the topic

Collapse
 
austinbooth profile image
austinbooth

Nice article. I have a question about the movies iterable example. Why are you using the increment operator when accessing the value?

Collapse
 
yumatsushima07 profile image
Yuma-Tsushima

So post increment was used in the movies example .
So it adds 1 to the operator.
So if you do index++ it will log the firstvalue.
If you do ++index it will log the secondvalue

eg

const movies = {
  list: [
    { title: 'Skyfall' }, 
    { title: 'Interstellar' }
  ],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.list.length) {
          const value = this.list[index++].title;
          return { value, done: false };
        }
        return { done: true };
      }
    };
  }
};

const [firstMovieTitle] = movies;
console.log(firstMovieTitle); // so it logs skyfall
Enter fullscreen mode Exit fullscreen mode

but once we use the pre increment it will log interstellar

const movies = {
  list: [
    { title: 'Skyfall' }, 
    { title: 'Interstellar' }
  ],
  [Symbol.iterator]() {
    let index = 0;
    return {
      next: () => {
        if (index < this.list.length) {
          const value = this.list[++index].title;
          return { value, done: false };
        }
        return { done: true };
      }
    };
  }
};

const [firstMovieTitle] = movies;
console.log(firstMovieTitle); // now logs interstellar 
Enter fullscreen mode Exit fullscreen mode

and if we just left it without increment then it would just be skyfall because it just logs the index.

I hope that helps.

Collapse
 
austinbooth profile image
austinbooth

Thanks for the explanation. So without the increment you wouldn’t be able to destructure further movies in the list, only the first one?

Thread Thread
 
yumatsushima07 profile image
Yuma-Tsushima

yes

Collapse
 
kathybowing profile image
Kathy Bowing

Wow, you have some good content on there.

Collapse
 
yumatsushima07 profile image
Yuma-Tsushima

Thank you

Collapse
 
mistycoruscate profile image
mistycoruscate

Awesome, thank you :-)

Collapse
 
yumatsushima07 profile image
Yuma-Tsushima

Thanks for reading it 🙂

Collapse
 
forkbikash profile image
Bikash Mishra

Excellent article!

Collapse
 
yumatsushima07 profile image
Yuma-Tsushima

Thank you