The spread syntax allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) or multiple variables (for destructuring assignment) are expected.
Syntax
For function calls:
myFunction(...iterableObj);
For array literals:
[...iterableObj, 4, 5, 6];
Examples
Replace apply
Example: it is common to use Function.prototype.apply
in cases where you want to use an array as arguments to a function.
function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction.apply(null, args);
With spread syntax the above can be written as:
function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction(...args);
Any argument in the argument list can use spread syntax and it can be used multiple times.
function myFunction(v, w, x, y, z) { } var args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);
A more powerful array literal
Example: Without spread syntax, to create a new array using an existing array as one part of it, the array literal syntax is no longer sufficient and imperative code must be used instead using a combination of push
, splice
, concat
, etc. With spread syntax this becomes much more succinct:
var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes']; // ["head", "shoulders", "knees", "and", "toes"]
Just like spread for argument lists, ...
can be used anywhere in the array literal and it can be used multiple times.
Apply for new
Example: 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:
var dateFields = [1970, 0, 1]; // 1 Jan 1970 var d = new Date(...dateFields);
To use new with an array of parameters without spread syntax, you would have to do it indirectly through partial application:
function applyAndNew(constructor, args) { function partial () { return constructor.apply(this, args); }; if (typeof constructor.prototype === "object") { partial.prototype = Object.create(constructor.prototype); } return partial; } function myConstructor () { console.log("arguments.length: " + arguments.length); console.log(arguments); this.prop1="val1"; this.prop2="val2"; }; var myArguments = ["hi", "how", "are", "you", "mr", null]; var myConstructorWithArguments = applyAndNew(myConstructor, myArguments); console.log(new myConstructorWithArguments); // (internal log of myConstructor): arguments.length: 6 // (internal log of myConstructor): ["hi", "how", "are", "you", "mr", null] // (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}
Copy an array
var arr = [1, 2, 3]; var arr2 = [...arr]; // like arr.slice() arr2.push(4); // arr2 becomes [1, 2, 3, 4] // arr remains unaffected
Note: Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays as the following example shows (it's the same with Object.assign()
and spread syntax).
var a = [[1], [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // Now array a is affected as well: [[], [2], [3]]
A better way to concatenate arrays
Example: concat
is often used to concatenate an array to the end of an existing array. Without spread syntax this is done as:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Append all items from arr2 onto arr1 arr1 = arr1.concat(arr2);
With spread syntax this becomes:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr1, ...arr2];
Example: unshift
is often used to insert an array of values at the start of an existing array. Without spread syntax this is done as:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Prepend all items from arr2 onto arr1 Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]
With spread syntax this becomes:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]
Only for iterables
Spread syntax can be applied only to iterable objects:
var obj = {'key1': 'value1'}; var array = [...obj]; // TypeError: obj is not iterable
Rest syntax (parameters)
Rest syntax looks exactly like spread syntax, but is used for destructuring arrays and objects. In a way, rest syntax is the opposite of spread syntax: spread 'expands' an array into its elements, while rest collects multiple elements and 'condenses' them into a single element. See rest parameters.
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) | Standard | Defined in several sections of the specification: Array Initializer, Argument Lists |
ECMAScript Latest Draft (ECMA-262) | Draft | No changes. |
Browser compatibility
Feature | Chrome | Edge | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|---|
Spread operation in array literals | 46 | 20 (12.10240) | 16 (16) | No support | 37 | 7.1 |
Spread operation in function calls | 46 | 20 (12.10240) | 27 (27) | No support | 37 | 7.1 |
Spread operation in destructuring | 49 | No support | 34 (34) | No support | 37 | ? |
Feature | Android | Android Webview | Edge | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|---|---|
Spread operation in array literals | No support | 46 | ? | 16.0 (16) | No support | No support | 8 | 46 |
Spread operation in function calls | No support | 46 | ? | 27.0 (27) | No support | No support | 8 | 46 |
Spread operation in destructuring | No support | No support | ? | 34 (34) | ? | ? | ? | No support |
See also
- Rest parameters (also ‘
...
’)