Make Your JavaScript Cleaner with Destructuring Assignment

Which one of the following code snippets would you prefer to write?

This?

// ES6
function displayInfo ({ name = 'No name', email = 'No email', occupation = 'No occupation' }) {
    console.log(name);
    console.log(email);
    console.log(occupation);
}

Or this?

// ES5
function displayInfo (person) {
    person.name = person.name || 'No name';
    person.email = person.email || 'No email';
    person.occupation = person.occupation || 'No occupation';

    console.log(person.name);
    console.log(person.email);
    console.log(person.occupation);
}

If you liked the first one (and you should!), keep reading as I'll teach you about an awesome feature in ES6 called “Destructuring Assignment”.

Before we start

Since this feature is supported only in ES6, and not all browsers support ES6, we have to use the BabelJS compiler to compile ES6 down to ES5.

If you already know how to set up that, feel free to skip this section.

I prefer to use Gulp as my main build system, so this is what we'll use in this tutorial.

First, we have to install all the dependencies via NPM.

npm install --save-dev gulp gulp-babel babel-preset-es2015

Then, we'll need to set up a simple gulp file to define the needed tasks. In this tutorial, we'll only setup a js task with a watcher.

So, create gulpfile.js in your root directory and put in the following.

var gulp = require('gulp');
var babel = require('gulp-babel');

gulp.task('js', function () {
    return gulp.src('assets/js/main.js')
        .pipe(babel({
            presets: ['es2015']
        }))
        .pipe(gulp.dest('dist'));
});

gulp.task('watch', function () {
    gulp.watch('assets/js/**/*.js', ['js']);
});

What this task basically does is compile assets/js/main.js file and store the result in dist directory (also named main.js).

So, this means you have to include this in your html:

<script src="/dist/main.js"></script>

To run this task, you'll either run gulp js each time you make a change, or gulp watch which would watch for changes and do the compilation automatically for you.

What is Destructuring Assignment?

It's just a fancy name for making values assignment in JavaScript so convenient and fast — in terms of writing code.

The way it works is so simple. All you have to do is to match the structure of what you're trying to extract from. Not clear? Here's an example:

var [name, email] = ['John', ''];

After this, name will equal to John, and email will equal to .

This can be as complex as you want, and it'll always work as long as you're matching the position of what you're extracting.

So, here's another slightly complicated example:

var [[name, [email, [occupation]]]] = [['John', ['', ['Web Developer']]]];

Object matching

The previous examples were using arrays, but what about objects?

It's not that different — you have to match what you want to extract.

var person = {
    name: 'John',
    email: '',
    occupation: 'Web Developer',
}

var {name, email, occupation} = person;

console.log(name); // John
console.log(email); // 
console.log(occupation); // Web Developer

Actually, this is the shorthand syntax. In the full syntax we have to determine the name of the variable we want to assign to.

In the previous example, we wanted to extract the properties from the objects to variables with the same name (name, email, occupation).

But, what if you want to assign these properties to different variable names? Here's how:

var person = {
    name: 'John',
    email: '',
    occupation: 'Web Developer',
}

var {name: myName, email: myEmail, occupation: myOccupation} = person;

console.log(myName); // John
console.log(myEmail); // 
console.log(myOccupation); // Web Developer

You can think of it as this: take the value from name and put it into a new variable called myName.

Default values

Another great advantage of using ES6's destructuring is the ability to specify default values in case nothing was specified in the source value.

Of course you can do this in ES5, but it's not so clean, is it? Here's how we used to do it:

var name = person.name || 'Default name';
var email = person.email || 'Default email';
var occupation = person.occupation || 'Default occupation';

Here's how in ES6:

var { name       = 'Default name',
      email      = 'Default email',
      occupation = 'Default occupation' } = person;

Parameter Destructuring

Now what about parameter destructuring? It's the same thing. Just instead of assigning using equal sign “=”, you're receiving values from the function caller — the very first example in this tutorial uses it.

function displayInfo ({ name = 'No name', email = 'No email', occupation = 'No occupation' }) {
    console.log(name);
    console.log(email);
    console.log(occupation);
}

Actually, this is my most favorite part of this feature. Imagine how many times you extract values when you're reading the response of an Ajax request; it's especially useful inside callbacks — when you want to quickly get a specific value from the passed object.

For instance, let's say that you're fetching multiple posts from some API. And you only want to get the title of the first post.

Here's how you'll do it if the data you're expecting to receive is like this:

{
  posts: [
    {
      title: 'Foo',
      // ...
    },
    // other posts
  ]
}
function getFirstPost ({posts: [{title}]}) {
    console.log(title); // Foo
}

One last tip

I'd like to finish up this post with this cool tip. Have you ever been in a situation where you want to capture only the first one or two values from an array and keep the rest in another array?

It's ridiculously easy with Destructuring assignment and spread operator. Here's an example:

var [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 1
console.log(tail); // [2, 3, 4]
JavaScript
Taha Shashtari

About Taha Shashtari

I'm a freelance web developer. Laravel & VueJS are my main tools these days and I love building stuff using them. I write constantly on this blog to share my knowledge and thoughts on things related to web development... Let's be friends on twitter.