My Profile Photo

Hao's Keeper


A blog to place memos


Spread Syntax

  • Function argument list (myFunction(a, ...iterableObj, b))
  • Array literals ([1, ...iterableObj, '4', 'five', 6])
  • Object literals ({...obj, key: 'value'})

Replace apply()

function myFunction(x, y, z) { }
let args = [0, 1, 2];
myFunction.apply(null, args);

can be written as

function myFunction(x, y, z) { }
let args = [1, 2, 2];
myFunction(...args);

can be used multiple time.

function myFunction(v, w, x, y, z) { }
let args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

Apply for new operator

When calling a constructor with new it’s not possible to directly use an array and apply() (apply() does a [[Call]] and not a [[Construct]]).
However, an array can be easily used with new thanks to spread syntax:

let dataFields = [1970, 0, 1]; // 1 Jan 1970
let d = new Date(...dataFields);

Copy an array

let arr = [1,2,3];
let arr2 = [...arr]; // like arr.slice()
arr2.push(4);
// arr2 becomes [1,2,3,4]
// arr remains unaffected

Maybe Unsuitable for copying multimenstional arrays

Spread syntax effectively goes one level deep while copying an array.
(The same is true with Object.assign().)

let a = [[1], [2], [3]];
let b = [...a];

b.shift().shift();
// 1

// Oh no!  Now array 'a' is affected as well:
a
// [[], [2], [3]]

A better way to concatenate arrays

let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];

// Append all items from arr2 onto arr1
arr1 = arr1.concat(arr2);

arr1 = [...arr1, ...arr2];
// Note: Not to use const otherwise, it will give TypeError (invalid assignment)

Array.propotype.unshift() is often used to insert an array of values at the start of an existing array.

// Prepen all items from arr2 onto arr1
Array.prototype.unshift.apply(arr1, arr2);
// arr1 is now [3, 4, 5, 0, 1, 2]

arr1 = [...arr2, ...arr1]

Unlike unshift(), this creates a new arr1, and does not modify the original arr1 array in-place.

Spread in object literals

The Rest/Spread Properties for ECMAScript proposal (ES2018) added spread properties to object literals. It copies own enumerable properties from a provided object onto a new object. Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than Object.assign().

let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };

let cloneObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

let cloneObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

Note that Object.assign() triggers setters, whereas spread syntax doesn’t.

Note that you cannot replace or mimic the Object.assign() function:

let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );

let mergeObj1 = merge (obj1, obj2);
// Object { 0: { foo: 'bar', x: 42}, 1: { foo: 'baz', y: 13 } }

Only for iterables

Spread syntax (other than in the case of spread properties) can only be applied to iterable objects like Array, or with iterating functions such as map(), reduce(), and assign(). Many objects are not iterable, including Object:

let obj = {'key1': 'value1'};
let array = [...obj]; // TypeError: obj is not iterable

To use spread syntax with these objects, you will need to provide an iterator function.