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]
4 Answers 4
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 :
[ Elision_opt ]
[ ElementList ]
[ ElementList , Elision_opt ]
ElementList :
Elision_opt SpreadElement
ElementList , Elision_opt SpreadElement
SpreadElement:
... AssignmentExpression
Arguments :
( )
( ArgumentList )
ArgumentList :
AssignmentExpression
... AssignmentExpression
ArgumentList , AssignmentExpression
ArgumentList , ... AssignmentExpression
6 Comments
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.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));
Comments
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))
Comments
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.
Comments
Explore related questions
See similar questions with these tags.
...(arr)works. it is the same as...arrarre.g....arr. Withconsole.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-listsconsole.log(...[].concat(...arr))(or any otherflattening function)