You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Spread syntax** (`...`) allows an iterable such as an array
15
-
expression or string to be expanded in places where zero or more arguments (for
16
-
function calls) or elements (for array literals) are expected, or an object expression
17
-
to be expanded in places where zero or more key-value pairs (for object literals) are
18
-
expected.
14
+
**Spread syntax** (`...`) allows an iterable, such as an array or string, to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected. In an object literal, the spread syntax enumerates the properties of an object and adds the key-value pairs to the object being created.
Spread syntax can be used when all elements from an object or array need to be included
25
-
in a list of some kind.
26
-
27
-
In the above example, the defined function takes `x`, `y`, and
28
-
`z` as arguments and returns the sum of these values. An array value is also
29
-
defined.
30
-
31
-
When we invoke the function, we pass it all the values in the array using the spread
32
-
syntax and the array name — `...numbers`.
33
-
34
-
If the array contained more than three numbers, e.g. `[1, 2, 3, 4]`, then it
35
-
would still work fine, except that all four would be passed, but only the first three
36
-
would be used unless you added more arguments to the function, e.g.:
37
-
38
-
```js
39
-
functionsum(x, y, z, n) {
40
-
return x + y + z + n;
41
-
}
42
-
```
16
+
Rest syntax looks exactly like spread syntax. In a way, rest syntax is the opposite of spread syntax. Spread syntax "expands" an array into its elements, while rest syntax collects multiple elements and "condenses" them into a single element. See [rest parameters](/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters) and [rest property](/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment#rest_property).
43
17
44
-
The above example is somewhat rigid; the real value in spread syntax is that it works
45
-
with the same value, no matter how many elements are contained in the object, array,
It is commonly used when you want to add a new item to a local data store, or display
49
-
all stored items plus a new addition. A very simple version of this kind of action
50
-
could look like so:
20
+
## Syntax
51
21
52
22
```js
53
-
let numberStore = [0, 1, 2];
54
-
let newNumber =12;
55
-
numberStore = [...numberStore, newNumber];
23
+
myFunction(a, ...iterableObj, b)
24
+
[1, ...iterableObj, '4', 'five', 6]
25
+
({ ...obj, key:'value' })
56
26
```
57
27
58
-
In the above example you can rerun the last line as many times as you like, to keep
59
-
adding an additional 12 to the end of the array.
28
+
## Description
60
29
61
-
## Syntax
30
+
Spread syntax can be used when all elements from an object or array need to be included in a new array or object, or should be applied one-by-one in a function call's arguments list. There are three distinct places that accept the spread syntax:
62
31
63
-
For function calls:
32
+
-[Function arguments](#spread_in_function_calls) list (`myFunction(a, ...iterableObj, b)`)
myFunction(...iterableObj); // pass all elements of iterableObj as arguments to function myFunction
67
-
```
36
+
Although the syntax looks the same, they come with slightly different semantics.
68
37
69
-
For array literals:
38
+
Only [iterable](/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) objects, like {{jsxref("Array")}}, can be spread in array and function parameters. Many objects are not iterable, including all [plain objects](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) that lack a [`Symbol.iterator`](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator) method:
70
39
71
-
```js
72
-
[...iterableObj, '4', 'five', 6]; // combine two arrays by inserting all elements from iterableObj
40
+
```js example-bad
41
+
constobj= { key1:'value1' };
42
+
constarray= [...obj]; // TypeError: obj is not iterable
73
43
```
74
44
75
-
For object literals (new in ECMAScript 2018):
45
+
On the other hand, spreading in object literals [enumerates](/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties#traversing_object_properties) the own properties of the object. For typical arrays, all indices are enumerable own properties, so arrays can be spread into objects.
76
46
77
47
```js
78
-
let objClone = { ...obj }; // pass all key:value pairs from an object
48
+
constarray= [1, 2, 3];
49
+
constobj= { ...array }; // { 0: 1, 1: 2, 2: 3 }
79
50
```
80
51
81
-
## Rest syntax (parameters)
82
-
83
-
Rest syntax looks exactly like spread syntax. In a way, rest syntax is the opposite of
84
-
spread syntax. Spread syntax "expands" an array into its elements, while rest syntax
85
-
collects multiple elements and "condenses" them into a single element. See
When using spread syntax for function calls, be aware of the possibility of exceeding the JavaScript engine's argument length limit. See {{jsxref("Function.prototype.apply()")}} for more details.
87
53
88
54
## Examples
89
55
@@ -95,68 +61,35 @@ It is common to use {{jsxref("Function.prototype.apply()")}} in cases where you
95
61
use the elements of an array as arguments to a function.
96
62
97
63
```js
98
-
functionmyFunction(x, y, z) {}
99
-
let args = [0, 1, 2];
64
+
functionmyFunction(x, y, z) {}
65
+
constargs= [0, 1, 2];
100
66
myFunction.apply(null, args);
101
67
```
102
68
103
69
With spread syntax the above can be written as:
104
70
105
71
```js
106
-
functionmyFunction(x, y, z) {}
107
-
let args = [0, 1, 2];
72
+
functionmyFunction(x, y, z) {}
73
+
constargs= [0, 1, 2];
108
74
myFunction(...args);
109
75
```
110
76
111
77
Any argument in the argument list can use spread syntax, and the spread syntax can be
112
78
used multiple times.
113
79
114
80
```js
115
-
functionmyFunction(v, w, x, y, z) {}
116
-
let args = [0, 1];
81
+
functionmyFunction(v, w, x, y, z) {}
82
+
constargs= [0, 1];
117
83
myFunction(-1, ...args, 2, ...[3]);
118
84
```
119
85
120
86
#### Apply for new operator
121
87
122
-
When calling a constructor with {{jsxref("Operators/new", "new")}} it's not possible to
123
-
**directly** use an array and `apply()` (`apply()`
124
-
does a `[[Call]]` and not a `[[Construct]]`). However, an array
125
-
can be easily used with `new` thanks to spread syntax:
126
-
127
-
```js
128
-
let dateFields = [1970, 0, 1]; // 1 Jan 1970
129
-
let d =newDate(...dateFields);
130
-
```
131
-
132
-
To use `new` with an array of parameters without spread syntax, you would
133
-
have to do it **indirectly** through partial application:
88
+
When calling a constructor with {{jsxref("Operators/new", "new")}}, it's not possible to **directly** use an array and `apply()`, because `apply()`_calls_ the target function instead of _constructing_ it, which means, among other things, that [`new.target`](/en-US/docs/Web/JavaScript/Reference/Operators/new.target) will be `undefined`. However, an array can be easily used with `new` thanks to spread syntax:
// (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}
91
+
constdateFields= [1970, 0, 1]; // 1 Jan 1970
92
+
constd=newDate(...dateFields);
160
93
```
161
94
162
95
### Spread in array literals
@@ -170,8 +103,8 @@ instead using a combination of {{jsxref("Array.prototype.push", "push()")}},
170
103
"concat()")}}, etc. With spread syntax this becomes much more succinct:
171
104
172
105
```js
173
-
let parts = ['shoulders', 'knees'];
174
-
let lyrics = ['head', ...parts, 'and', 'toes'];
106
+
constparts= ['shoulders', 'knees'];
107
+
constlyrics= ['head', ...parts, 'and', 'toes'];
175
108
// ["head", "shoulders", "knees", "and", "toes"]
176
109
```
177
110
@@ -181,22 +114,19 @@ literal, and may be used more than once.
181
114
#### Copy an array
182
115
183
116
```js
184
-
let arr = [1, 2, 3];
185
-
let arr2 = [...arr]; // like arr.slice()
117
+
constarr= [1, 2, 3];
118
+
constarr2= [...arr]; // like arr.slice()
186
119
187
120
arr2.push(4);
188
121
// arr2 becomes [1, 2, 3, 4]
189
122
// arr remains unaffected
190
123
```
191
124
192
-
> **Note:** Spread syntax effectively goes one level deep while copying
193
-
> an array. Therefore, it may be unsuitable for copying multidimensional arrays, as
194
-
> the following example shows. (The same is true with {{jsxref("Object.assign()")}}
195
-
> and spread syntax.)
125
+
> **Note:** Spread syntax effectively goes one level deep while copying an array. Therefore, it may be unsuitable for copying multidimensional arrays. The same is true with {{jsxref("Object.assign()")}} — no native operation in JavaScript does a deep clone.
196
126
>
197
127
> ```js example-bad
198
-
>let a = [[1], [2], [3]];
199
-
>let b = [...a];
128
+
>consta= [[1], [2], [3]];
129
+
>constb= [...a];
200
130
>
201
131
>b.shift().shift();
202
132
>// 1
@@ -213,32 +143,31 @@ of an existing array. Without spread syntax, this is done as:
213
143
214
144
```js
215
145
let arr1 = [0, 1, 2];
216
-
let arr2 = [3, 4, 5];
146
+
constarr2= [3, 4, 5];
217
147
218
-
//Append all items from arr2 onto arr1
148
+
// Append all items from arr2 onto arr1
219
149
arr1 =arr1.concat(arr2);
220
150
```
221
151
222
152
With spread syntax this becomes:
223
153
224
154
```js
225
155
let arr1 = [0, 1, 2];
226
-
let arr2 = [3, 4, 5];
156
+
constarr2= [3, 4, 5];
227
157
228
158
arr1 = [...arr1, ...arr2];
229
-
// arr1 is now [0, 1, 2, 3, 4, 5]
230
-
// Note: Not to use const otherwise, it will give TypeError (invalid assignment)
159
+
// arr1 is now [0, 1, 2, 3, 4, 5]
231
160
```
232
161
233
162
{{jsxref("Array.prototype.unshift()")}} is often used to insert an array of values at
234
163
the start of an existing array. Without spread syntax, this is done as:
235
164
236
165
```js
237
-
let arr1 = [0, 1, 2];
238
-
let arr2 = [3, 4, 5];
166
+
constarr1= [0, 1, 2];
167
+
constarr2= [3, 4, 5];
239
168
240
169
// Prepend all items from arr2 onto arr1
241
-
Array.prototype.unshift.apply(arr1, arr2)
170
+
Array.prototype.unshift.apply(arr1, arr2);
242
171
243
172
// arr1 is now [3, 4, 5, 0, 1, 2]
244
173
```
@@ -247,38 +176,39 @@ With spread syntax, this becomes:
247
176
248
177
```js
249
178
let arr1 = [0, 1, 2];
250
-
let arr2 = [3, 4, 5];
179
+
constarr2= [3, 4, 5];
251
180
252
181
arr1 = [...arr2, ...arr1];
253
182
// arr1 is now [3, 4, 5, 0, 1, 2]
254
183
```
255
184
256
-
> **Note:** Unlike `unshift()`, this creates a new
257
-
> `arr1`, and does not modify the original `arr1` array
258
-
> in-place.
185
+
> **Note:** Unlike `unshift()`, this creates a new `arr1`, instead of modifying the original `arr1` array in-place.
259
186
260
187
### Spread in object literals
261
188
262
-
The [Rest/Spread Properties for ECMAScript](https://github.com/tc39/proposal-object-rest-spread) proposal (ES2018)
263
-
added spread properties to {{jsxref("Operators/Object_initializer", "object literals", 1)}}.
264
-
It copies own enumerable properties from a provided object onto a new object.
265
-
266
-
Shallow-cloning (excluding prototype) or merging of objects is now possible using a
267
-
shorter syntax than {{jsxref("Object.assign()")}}.
189
+
Shallow-cloning (excluding prototype) or merging of objects is possible using a shorter syntax than {{jsxref("Object.assign()")}}.
268
190
269
191
```js
270
-
let obj1 = { foo:'bar', x:42 };
271
-
let obj2 = { foo:'baz', y:13 };
192
+
constobj1= { foo:'bar', x:42 };
193
+
constobj2= { foo:'baz', y:13 };
272
194
273
-
let clonedObj = { ...obj1 };
195
+
constclonedObj= { ...obj1 };
274
196
// Object { foo: "bar", x: 42 }
275
197
276
-
let mergedObj = { ...obj1, ...obj2 };
198
+
constmergedObj= { ...obj1, ...obj2 };
277
199
// Object { foo: "baz", x: 42, y: 13 }
278
200
```
279
201
280
202
Note that {{jsxref("Object.assign()")}} can be used to mutate an object, whereas spread syntax can't.
Spread syntax (other than in the case of spread properties) can only be applied to [iterable](/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/iterator)
318
-
objects like {{jsxref("Array")}}, or with iterating functions such as `map()`, `reduce()`, and `assign()`.
319
-
320
-
Many objects are not iterable, including {{JSxRef("Object")}}:
321
-
322
-
```js
323
-
let obj = {'key1':'value1'};
324
-
let array = [...obj]; // TypeError: obj is not iterable
325
-
```
326
-
327
-
To use spread syntax with these objects, you will need to provide an iterator function.
328
-
329
-
### Spread with many values
330
-
331
-
When using spread syntax for function calls, be aware of the possibility of exceeding the JavaScript engine's argument length limit.
332
-
See {{jsxref("Function.prototype.apply", "apply()")}} for more details.
333
-
334
245
## Specifications
335
246
336
247
{{Specifications}}
@@ -341,5 +252,6 @@ See {{jsxref("Function.prototype.apply", "apply()")}} for more details.
0 commit comments