24

Why can't the spread operator be used multiple times?

let arr = [[[1, 2, 3]]];
console.log(arr); // Array [[[1, 2, 3]]]
console.log(...arr); // Array [[1, 2, 3]]
console.log(...(...arr));
// Uncaught SyntaxError: Unexpected token '...'

I had expected :

console.log(...(...arr)); // Array [1, 2, 3]
Henke
5,9076 gold badges41 silver badges54 bronze badges
asked Jan 26, 2016 at 17:04
4
  • ...(arr) works. it is the same as ...arr Commented Jan 26, 2016 at 17:23
  • 1
    According to the ES6 spec when the spread operator is encountered an iterator is created from a spread object that is the result of evaluating the assignment expression which is in your working example arr e.g. ...arr. With console.log(...(...arr)); you are attempting to pass a spread operator + assignment expression as an assignment expression to another spread operator. See ecma-international.org/ecma-262/6.0/#sec-argument-lists Commented Jan 26, 2016 at 17:44
  • You might want to try console.log(...[].concat(...arr)) (or any other flattening function) Commented Jan 26, 2016 at 19:15
  • Related: Spread Syntax vs Rest Parameter in ES2015 / ES6. Commented May 10, 2021 at 13:49

4 Answers 4

18

Why can't spread operator be used multiple times?

... is not an operator. (...arr) is not valid JavaScript. ... is only allowed inside array literals and in arguments lists, but those are special forms of the syntax (notice the ... in the production rules below).

ArrayLiteral

ArrayLiteral :
 [ Elision_opt ]
 [ ElementList ]
 [ ElementList , Elision_opt ]
ElementList :
 Elision_opt SpreadElement
 ElementList , Elision_opt SpreadElement
SpreadElement:
 ... AssignmentExpression

Arguments

Arguments :
 ( )
 ( ArgumentList )
ArgumentList :
 AssignmentExpression
 ... AssignmentExpression
 ArgumentList , AssignmentExpression
 ArgumentList , ... AssignmentExpression
answered Jan 26, 2016 at 17:52
Sign up to request clarification or add additional context in comments.

6 Comments

I was convinced that spreading an already spread array would not evaluate, but turns out I was wrong, because it does. This seems to be the only right answer. +1
@madox2: Yes. I don't know who came up with the term "spread operator", but it's certainly not an operator in the JavaScript sense. It's just a token.
@FelixKling could you explain it little bit more? I went through your answer many times but I don't get it.
You might like to support the question I've asked to gain clarification of the term "operator": What, actually, is and is not an operator?
@madox2: If we consider operators a special form of functions (which it is in other languages), then we could say that we can use an operator everywhere were we can use a function call. E.g. instead of var foo = add(1, 2); we can write var foo = 1 + 2;. However, we cannot replace var foo = spread(arr); with var foo = ...arr;. There is no such thing as a standalone spread operator, it is simply an extension of the syntax of array initializers and argument lists. And that becomes clear when looking at the language grammar.
|
3

According to this, spread syntax input is an iterable (e.g. array), but its produce output which is non-iterable (e.g. non-array). So the problem is that in outer spread syntax ... as input you put non-iterable thing (...arr) which cause SyntaxError. To flat you array you can use flat (if you put Infinity instead 2, then you will flat any nested array)

arr.flat(2)

let arr = [[[1, 2, 3]]];
console.log(arr.flat(2));
let arr2 = [[1,2,[3,4,[5,[6]]]], [[7,[8]],9]];;
console.log(arr2.flat(Infinity));

answered Feb 18, 2019 at 12:22

Comments

1

Because ...arr isn't like a function that returns a value in normal scenarios (you can test this by just typing ...[[1,2,3]] in console, if ... operated like a normal function we would expect a return of [1 2 3]. For that reason you can't chain spreads. From MDN:

The spread operator allows an expression to be expanded in places where multiple arguments (for function calls) or multiple elements (for array literals) are expected.

Ergo, spreads need to happen within array literals, object literals (if using obj spread, which is ES7) or within function calls So you could do console.log(...[].concat(...arr))

Matsemann
22k20 gold badges60 silver badges91 bronze badges
answered Jan 26, 2016 at 17:45

Comments

1

Not an answer to your question, but - in general, the three dots ... Spread syntax can be applied to an iterable, such as an array or string.

Why can't the spread operator be used multiple times?

I will not answer the question of Why.
But the snippet ...[].concat(...arr) achieves what you expected from ...(...arr). \

const arr = [[[1, 2, 3]]];
console.log(JSON.stringify(arr)); // [[[1,2,3]]]
console.log(JSON.stringify(...arr)); // [[1,2,3]]
// console.log(JSON.stringify(...(...arr))); // SyntaxError
console.log(JSON.stringify(...[].concat(...arr))); // [1,2,3]
console.log(...[].concat(...[].concat(...arr))); // 1 2 3
.as-console-wrapper { max-height: 100% !important; top: 0; }

Inspired by this comment.

answered Mar 15, 2021 at 14:31

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.