51

At ECMAScript specification the SpreadElement is described

SpreadElement[Yield]:
...AssignmentExpression[In, ?Yield]

Is this the same as the Spread syntax

Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Syntax

For function calls:

myFunction(...iterableObj);

For array literals:

[...iterableObj, 4, 5, 6]

described at MDN documentation?

What are use cases of SpreadElement and, or, spread syntax; and if SpreadElement and spread syntax are different, in which specific manners do they differ?

Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
guest271314
  • 1
  • 15
  • 104
  • 177
  • 1
    For function calls, I'd personally say its REST parameter instead of spread operator. Yet they both serve the almost same purposes and way of implementing it. – choz May 11 '16 at 02:26
  • 1
    @choz: Eh, if we want to be precise, it should be spread in calls, rest in definitions: `x = f(a, ...b)` spreads `b`, `function f(a, ...b)` collects the rest of the arguments into `b`. Same with arrays: in literals `x = [a, ...b]` it's spread, in destructuring assignment `[a, ...b] = x` it's rest. – Amadan May 11 '16 at 02:29
  • 1
    @Amadan In `x = f(a, ...b)`, `b` has to be an iterable object. I'd say this is still called [spread](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator). And `function f(a, ...b)`, which makes `b` has to come last in it and able to contain the rest of parameters. So, I call it [Rest parameters](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/rest_parameters) – choz May 11 '16 at 02:35
  • @choz: I think you just said exactly what I did :P – Amadan May 11 '16 at 02:37
  • 2
    Yes, the entire point is that [spread *syntax* is not an "operator"](http://stackoverflow.com/q/35019557/1048572) – Bergi May 11 '16 at 02:56
  • @Amadan Ups.. your comment was actually screwing my head. I thought it was the other way around. Nvm :) – choz May 11 '16 at 03:01
  • @Bergi A link to that Answer http://stackoverflow.com/q/37151298/ is what ultimately led to this Question . Amandan actually brought up another part of Question which have yet to properly formulate: What is difference between `spread` and `rest` parameters? Are there any other uses of `...`? – guest271314 May 11 '16 at 03:05
  • @guest271314: Uh, Amadan just explained you the different between spread and rest? Btw, we already have [that question](http://stackoverflow.com/q/33898512/1048572) – Bergi May 11 '16 at 03:07
  • Does this answer your question? [Spread Syntax vs Rest Parameter in ES2015 / ES6](https://stackoverflow.com/questions/33898512/spread-syntax-vs-rest-parameter-in-es2015-es6) – Henke Mar 15 '21 at 13:55

4 Answers4

109

The term "spread operator" is kind of an "umbrella term" that refers to various syntactic constructs in ES6 which all look like ...x. MDN does the same.

However, this is misguiding, because ... is not an operator (at least not in the sense the ECMAScript spec uses the term "operator"). It doesn't generate a value that can be used in further computations. I'd rather compare it to other punctuators, such as , or ; (which are also kind of related but have different meaning in different context).

The term "spread operator" could refer to:

  • Spread element, var arr = [a, b, ...c];: The spread element expands the iterable (c) into the new array. It's equivalent to something like [a,b].concat(c).

  • Rest element, [a, b, ...c] = arr;: Inside destructuring, the ... construct has the opposite effect: It collects remaining elements into an array. The example here is equivalent to

    a = arr[0];
    b = arr[1];
    c = arr.slice(2);
    

    (note that this only an approximation, because destructuring works on any iterable value, not just arrays)

  • fun(a, b, ...c): This construct doesn't actually have a name in the spec. But it works very similar as spread elements do: It expands an iterable into the list of arguments.
    It would be equivalent to func.apply(null, [a, b].concat(c)).

    The lack of an official name might be the reason why people started to use "spread operator". I would probably call it "spread argument".

  • Rest parameter: function foo(a, b, ...c): Similar like rest elements, the rest parameter collects the remaining arguments passed to the function and makes them available as array in c. The ES2015 actually spec uses the term BindingRestElement to refer to to this construct.

Related questions:


: If we are very pedantic we would even have to distinguish between a variable declaration (var [a, b, ...c] = d;) and simple assignment ([a, b, ...c] = d;), according to the spec.

Community
  • 1
  • 1
Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • 1
    By the way, for the '`...` is not an operator' part, I created a CW canonical for that (if you haven't already seen it): https://stackoverflow.com/q/44934828/5647260 to explain a bit more detail, albeit a year late. – Andrew Li Jul 06 '17 at 15:53
1

SpreadElement is just a name in the ES6 grammar for spread "operator" together with its argument when in an Array literal:

SpreadElement[Yield]:
    ... AssignmentExpression[In, ?Yield]

So, SpreadElement in [a, b, ...c] is ...c; spread "operator" is .... (scare quotes because it is not a real operator in the same sense that, e.g. - is.)

The name of the grammar rule being used in function calls will be different, as it is a different grammatical context (it's just one kind of ArgumentList).

Amadan
  • 191,408
  • 23
  • 240
  • 301
  • _"`SpreadElement` is just a name in the ES6 grammar for elision operator"_ What is "elision operator"? – guest271314 May 11 '16 at 02:21
  • @guest271314: A typo. Elision is when you write `[a, b, , , , , c]`, and is not relevant here. – Amadan May 11 '16 at 02:21
  • `SpreadElement` and `Spread operator` described at MDN documentation are equivalent? the same having different names at different documentations? Why does MDN refer to `...` as an `operator`? – guest271314 May 11 '16 at 02:23
  • 1
    No, `SpreadElement` is a grammar rule in ES6 spec, as I explained above, that covers more than just the `...` operator. And MDN refers to `...` as "operator" because it is clear what is meant in the context, and only pedants will insist on `syntactic construct` or something else. – Amadan May 11 '16 at 02:27
  • _"because it is not a real operator in the same sense that, e.g.` - ` is"_ Why does MDN use term operator? "spread operator" is not listed at ECMAScript documentation – guest271314 May 11 '16 at 02:28
  • _"No, `SpreadElement` is a grammar rule in ES6 spec, as I explained above, that covers more than just the `...` operator"_ What more does `SpreadElement` cover? Context was not immediately clear, here, as first read of `SpreadElement` today; not mentioned at MDN documentation. What are "pedants"? – guest271314 May 11 '16 at 02:30
  • 1
    Are you trolling? "Why does MDN use term operator?" answered above: "And MDN refers to `...` as 'operator' because it is clear what is meant in the context, and only pedants will insist on syntactic construct or something else". "What more does SpreadElement cover?" answered above: "`SpreadElement` in `[a, b, ...c]` is `...c`; spread "operator" is `...`". "What are 'pedants'?" Find a dictionary. – Amadan May 11 '16 at 02:32
  • 4
    @guest271314—ECMA-262 is the language specification, so it is **the** authority. MDN is a public wiki that anyone can contribute to, it is not an authority on anything. For the record (and pedants), `...` is a [*punctuator*](http://www.ecma-international.org/ecma-262/6.0/#sec-punctuators) that forms part of a SpreadElement. – RobG May 11 '16 at 02:36
  • @Amadan _"Are you trolling?"_ Really? For requesting greater clarity as to Question? If you do not want to provide further details, then perhaps you should delete your Answer? Or, simply say that your answer is your answer, and that is it. Though, it is up to you. You provided greater detail in exchange at comments http://stackoverflow.com/questions/37151966/what-is-spreadelement-in-ecmascript-documentation-is-it-the-same-as-spread-oper#comment61841764_37151966 than actual Answer? No, no "trolling", here. Name calling is not necessary to communicate. – guest271314 May 11 '16 at 02:37
  • If you wanted a clarification, you could have said "I don't understand what you mean by ...". However, you literally repeated a question I just answered. I did not call you names, I questioned if you were trolling, as your questions did not make any sense. (As for the details in question comments - they are not the answer to your question, as posed.) – Amadan May 11 '16 at 02:43
  • @Amadan The Question: _"What are use cases of SpreadElement and, or, Spread operator"_ If, in your experience, you could infer that `...` `spread` could also be interpreted as `...` `rest`, depending on usage; at comments above, you could possibly elaborate on this? Had not actually considered `rest` parameters; that is an interesting portion of where this Question is seeking greater awareness as well. I.e.g, could you thorough describe `spread` element or `operator`, `rest` parameter? Some context http://stackoverflow.com/questions/37151298/allocate-new-array-in-javascript/37151334#37151600 – guest271314 May 11 '16 at 02:56
  • 1
    @guest271314: You might want to have a look at the comments of [this deleted question](http://stackoverflow.com/q/35029217/1048572) about how the `...` token constitutes an operator. – Bergi May 11 '16 at 03:04
0

One more use case is a replacement for Object.assign method:

// naive use of assign--overwrites shared properties in o:

Object.assign(o, defaults); 

/* non-naive use of assign—prevents shared properties in o from being 
   overwritten */ 
o = Object.assign({}, defaults, o);  

alternately, use the spread operator:

o = {...defaults, ...o} 

This is one of the most import features in ES2018

let position = { x: 0, y: 0 };  
let dimensions = { width: 100, height: 75 };  
let rect = { ...position, ...dimensions };  
rect.x + rect.y + rect.width + rect.height // => 175 

-MDA

0

Normally the three dots are referred to as the "spread operator", but when written as part of a function parameter it is referred to as the "rest operator" (MDN Link). It's used when you may not know exactly how many arguments may be passed into the function. The rest operator will group all of the arguments passed into the function into an array. Example below:

function getNames(...names){
  console.log(names) // Output: ["Raul", "Chris", "Megan"]
}

getNames("Raul", "Chris", "Megan")

If you want the functionality of passing a combination of known arguments and a grouping of remaining arguments, you would need to make sure the rest operator is the last parameter listed when creating the function. For example:

function getNamesInClass(teacher, room, ...students){
  console.log(teacher) // Output: "David"
  console.log(room) // Output: "3B"
  console.log(students) // Output: ["Raul", "Chris", "Megan"]
}

getNamesInClass("David", "3B", "Raul", "Chris", "Megan")