【问题标题】:Using spread operator multiple times in javascript?在javascript中多次使用扩展运算符?
【发布时间】:2016-05-03 08:29:09
【问题描述】:

为什么spread算子不能多次使用?

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 ]

【问题讨论】:

  • ...(arr) 有效。同...arr
  • 根据 ES6 规范,当遇到扩展运算符时,会从扩展对象创建迭代器,该对象是评估工作示例 arr 中的赋值表达式的结果,例如...arr。使用console.log(...(...arr));,您试图将展开运算符 + 赋值表达式作为赋值表达式传递给另一个展开运算符。见ecma-international.org/ecma-262/6.0/#sec-argument-lists
  • 您可能想尝试console.log(...[].concat(...arr))(或任何其他flattening 函数)

标签: javascript ecmascript-6 spread-syntax


【解决方案1】:

为什么spread算子不能多次使用?

... 不是运算符。 (...arr) 不是有效的 JavaScript。 ... 只允许在数组字面量和参数列表中使用,但它们是特殊形式的语法(请注意下面生产规则中的 ...)。

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

【讨论】:

  • 我确信传播一个已经传播的数组不会评估,但事实证明我错了,因为它确实如此。这似乎是唯一正确的答案。 +1
  • @madox2:是的。我不知道谁提出了“扩展运算符”这个术语,但它肯定不是 JavaScript 意义上的运算符。这只是一个令牌。
  • @FelixKling 你能解释一下吗?你的答案我看了很多遍,但我不明白。
  • 您可能愿意支持我为澄清“运营商”一词而提出的问题:What, actually, is and is not an operator?
  • @madox2:如果我们将运算符视为一种特殊形式的函数(在其他语言中也是如此),那么我们可以说我们可以在任何地方使用运算符,只要我们可以使用函数调用。例如。而不是var foo = add(1, 2);,我们可以写var foo = 1 + 2;。但是,我们不能用var foo = ...arr; 替换var foo = spread(arr);。没有独立的扩展运算符之类的东西,它只是数组初始值设定项和参数列表语法的扩展。当查看语言语法时,这一点就变得清晰了。
【解决方案2】:

因为 ...arr 不像在正常情况下返回值的函数(您可以通过在控制台中键入 ...[[1,2,3]] 来测试它,如果 ... 操作如下一个正常的函数,我们期望返回 [1 2 3]。因此,您不能链接价差。来自 MDN:

展开运算符允许表达式在某些地方展开 其中多个参数(用于函数调用)或多个元素 (对于数组文字)是预期的。

因此,传播需要发生在数组字面量、对象字面量(如果使用 obj spread,即 ES7)或函数调用中 所以你可以做 console.log(...[].concat(...arr))

【讨论】:

    【解决方案3】:

    根据this,扩展语法输入是可迭代的(例如数组),但它产生的输出是不可迭代的(例如非数组)。所以问题在于,在外部扩展语法... 作为输入中,您放置了导致 SyntaxError 的不可迭代的东西 (...arr)。要扁平化你的数组,你可以使用 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));

    【讨论】:

      【解决方案4】:

      不回答您的问题,但是 - 一般来说,三个点 ... 语法可以 应用于可迭代对象 - 数组类数组对象

      为什么spread算子不能多次使用?

      我不会回答这个问题为什么
      但是下面的 sn-p 表明 ...[].concat(...arr) 实现了你的目标 预计通过...(...arr) 获得。 它的灵感来自this comment

      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: expect...
      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; }

      【讨论】:

        猜你喜欢
        • 2020-10-22
        • 1970-01-01
        • 2019-06-15
        • 2020-12-22
        • 1970-01-01
        • 1970-01-01
        • 2018-05-13
        • 1970-01-01
        相关资源
        最近更新 更多