Be careful with the spread syntax of ES6

Published On: 13. December 2022|By |3.5 min read|692 words|Tags: , |

The spread syntax is a JavaScript feature that really comes in handy for several use cases. Yet there are some caveats that you should be aware of when using it.

What is the spread syntax?

The spread syntax ... can be used together with JavaScript objects and iterables (such as arrays) in JavaScript ES6 or TypeScript. When using the spread syntax with an array, the array can be expanded in a place where zero or more arguments (e.g. in function calls) or elements (e.g. within array literals) are expected. When used with an object, the key value pairs are added to the new object created – similar to Object.assign().

const arrayA = [1, 2, 3];
const arrayB = [...arrayA, 4];

console.log(arrayA);
// [1, 2, 3, 4]

function foo(greeting, ...rest) {
  return greeting + rest.join(', ');
}

console.log(foo('hello', ...arrayA));
// hello 1, 2, 3
const objA = {
  foo: '123'
};

console.log({
  foo: 'XXX',
  bar: 'XXX',
  ...objA
});
// { foo: '123', bar: 'XXX' }

As you can see, the spread syntax can be used in many ways and generally is a useful and well liked JavaScript feature.

Where to be careful when using the spread syntax

I am writing this post because some developer colleagues (including me) have all done the same mistake when using the spread syntax in the past. One of the best known use cases of the spread syntax is to create a copy or clone an object or array. There are other ways to do that, like Array.slice() or Object.assign(), but some developers prefer the spread syntax just for their readability.

Yet there is one thing you definitely need to know before running into issues that can be very hard to debug. The spread syntax is not creating a deep clone of the array or object you are copying! What does this mean? While a single JavaScript object can be assigned to many variables in your code, all of this variables still reference the same object stored in memory. So as long as no new object is created, altering property values of the original object will affect all variables this object has been assigned to.

const a = { foo: 'hello' };
const b = a;

b.foo = 'guten tag';

console.log(a);
// { foo: 'guten tag' }

If you want a copy of that object that is not referencing the original object, you can use the spread syntax. Alternatives to the spread syntax are Array.slice() or Object.assign(), depending on your use case.

const a = { foo: 'hello' };
const b = { ...a };

b.foo = 'guten tag';

console.log(a);
// { foo: 'hello' }

What you need to understand is, that this copy process only works for the top level object. In case of nested objects, arrays of objects or nested arrays, it is not sufficient to create a deep clone! The outer object will have a new object reference, but nested objects will remain the same.

const a = { foo: { bar: 'hello' } };
const b = { ...a };

b.foo.bar = 'guten tag';

console.log(a);
// { foo: { bar: 'guten tag' } }

Depending on your case this might be sufficient, but for a deep copy you will need different tools.

How to create a deep copy of an object or array

Probably there are more solutions, but I will show you two easy ways to create a deep copy of any plain object or array.

JSON.stringify() and JSON.parse()

The first way to create a deep close is to use the builtin JavaScript methods of JSON.stringify() and JSON.parse(). Used in combination, this is a solid and robust method to copy either an object or array.

const a = { foo: { bar: 'hello' } };
const b = JSON.parse(JSON.stringify(a));

console.log(a.foo === b.foo);
// false

const c = { ...a };

console.log(a.foo === c.foo);
// true

Depending on the size of your object, this method can be slow in performance. This is why I recommend the following alternative.

Lodash’s cloneDeep method

If you do not hesitate to use an additional package or you are already using lodash, you can use its _.cloneDeep() method as well. It is also available as a standalone npm package which can be found here. The documentation also has some additional information on the use of it.

First lecture at Hochschule Düsseldorf
Goodbye and thank you, MHP!