DEV Community

Kevin Ball
Kevin Ball

Posted on • Originally published at zendev.com on

Understanding the Spread Operator in JavaScript

Newer versions of JavaScript have brought vast improvements to the language in terms of expressiveness and ease of development, but the rapid pace of change has left many developers feeling like they're struggling to keep up.

With Wordpress now embracing React and modern JavaScript in the new Gutenberg editor, the massive audience of Wordpress developers is being brought into this world, like it or not, and scrambling rapidly to catch up.

In this post we're going to break down one of the most popular new features of the JavaScript language - the Spread operator (aka the ... operator).

A friend recently asked for help understanding some example code from the Gutenberg blocks library, particular the gallery. As of this writing that code can be seen here, but it has moved several times so I've reproduced it below:

setImageAttributes( index, attributes ) {
  const { attributes: { images }, setAttributes } = this.props;
  if ( ! images[index] ) {
    return;
  }
  setAttributes( {
    images: [
      ...images.slice( 0, index ),
      {
        ...images[index],
        ...attributes,
      },
      ...images.slice( index + 1 ),
    ],
  } );
}
Enter fullscreen mode Exit fullscreen mode

In particular, the confusing part was:

images: [
    ...images.slice( 0, index ),
    {
        ...images[index],
        ...attributes,
    },
    ...images.slice( index + 1 ),
],
Enter fullscreen mode Exit fullscreen mode

This certainly looks a little intimidating, especially if you haven't been spending all of your time recently coding modern JavaScript. Let's break down what's happening.

Spread Operators for Arrays

The core piece to know is the ... syntax. This is the spread operator, and it essentially takes either an array or an object and expands it into its set of items. This lets you do fancy things, so for example if you have the code:

const array = [1, 2];
const array2 = [...array, 3, 4];
Enter fullscreen mode Exit fullscreen mode

The value of array2 will end up being [1, 2, 3, 4].

The spread operator lets you essentially drop an array in and get its values.

Coming back to our original code example, at the outer level what we have is

images = [...images.slice(0, index), {some stuff}, ...images.slice(index+1)]
Enter fullscreen mode Exit fullscreen mode

What this is saying is: set the images array to be the old images array from 0 to index, followed by a new thing that we'll cover shortly, followed by the old images array from index+1 to the end.

In other words, we're going to replace the item at index.

Spread Operators for Objects

Next, for objects that spread syntax lets you do the equivalent of Object.assign, copying the values of an object into a new one. Looking at a simple code example:

const obj1 = {a: 'a', b: 'b'};
const obj2 = {c: 'c', ...obj1};
Enter fullscreen mode Exit fullscreen mode

This results in obj2 being {a: 'a', b: 'b', c: 'c'}.

Looking back to the Gutenberg code example, the inner level , (labeled {some stuff} in our assessment of the array), we have:

{
  ...images[index],
  ...attributes,
}
Enter fullscreen mode Exit fullscreen mode

To translate: create an object, populate it first with the values from images[index], and then with the values from attributes. Any duplicate values get overwritten by the later one.

So this is saying: take my old image from index, and apply any values I have in attributes to it, with values in attributes taking precedence.

If we come back to our entire code example:

images: [
    ...images.slice( 0, index ),
    {
        ...images[index],
        ...attributes,
    },
    ...images.slice( index + 1 ),
],
Enter fullscreen mode Exit fullscreen mode

The whole big fancy thing is saying: I have an images array, an index, and a set of attributes I want to apply. Return a new images array that changes the item at index to have my new attributes.

Spread Syntax Enables Compact and Expressive Code

Let's look at what we've accomplished. In one short, hopefully now readable statement we've managed to create a new copy of an array that has an updated, complex object at a particular index. We have not modified the original array, meaning other parts of our code can call this without fear of side effects. Beautiful.


P.S. —  If you’re interested in these types of topics, I send out a weekly newsletter called the ‘Friday Frontend’. Every Friday I send out 15 links to the best articles, tutorials, and announcements in CSS/SCSS, JavaScript, and assorted other awesome Front-end News. Sign up here: https://zendev.com/friday-frontend.html

Top comments (0)