Использование оператора распространения несколько раз в JavaScript?

Почему оператор распространения не может использоваться несколько раз?

let arr = [[[1, 2, 3]]];

console.log(arr); // Array [ Array[1] ]
console.log(...arr); // Array [ Array[3] ]
console.log(...(...arr));
// SyntaxError: expected '=>' after argument list, got ')'

Я бы ожидал:

console.log(...(...arr)); // Array [ 1, 2, 3 ]

4 ответа

Решение

Почему оператор распространения не может использоваться несколько раз?

... не оператор. (...arr) не является допустимым 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 :
  ( )
  ( ArgumentList )

ArgumentList :
  AssignmentExpression
  ... AssignmentExpression
  ArgumentList , AssignmentExpression
  ArgumentList , ... AssignmentExpression

В соответствии с этим, входной сигнал с расширенным синтаксисом является итеративным (например, массивом), но его выходной результат является не повторяемым (например, не массивом). Так что проблема в том, что во внешнем синтаксисе распространения ... в качестве входных данных вы положили непеременную вещь (...arr), которые вызывают SyntaxError. Чтобы выровнять массив, вы можете использовать flat (если вместо Infinity поставить 2, вы упакуете любой вложенный массив).

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));

Почему нельзя использовать оператор спреда несколько раз?

Может. Но для этого нужно понимать, что он делает.

Эти три точки ...синтаксис может применяться только к итерируемому объекту - массиву или подобному массиву объекту .


Ссылка:

Преобразование аргументов в массив

Потому что... arr не похож на функцию, которая возвращает значение в нормальных сценариях (вы можете проверить это, просто набрав...[[1,2,3]] в консоли, если... работает как обычная функция мы ожидаем возврата [1 2 3]. По этой причине вы не можете цепочки спредов. Из MDN:

Оператор распространения позволяет развернуть выражение в местах, где ожидаются несколько аргументов (для вызовов функций) или несколько элементов (для литералов массива).

Следовательно, спреды должны происходить внутри литералов массива, литералов объектов (если используется obj spread, то есть ES7) или внутри вызовов функций. Поэтому вы можете сделать console.log(...[]. Concat(...arr))

Другие вопросы по тегам