小编典典

是传播“语法”还是传播“运算符”?

javascript

我听说过...这两种语言都称为“传播语法”和“传播算子”,后者更为流行。有关MDN文档的URL表明,它最初被称为扩展运算符,但后来更改为扩展语法,而MDN的运算符列表未提及它。

Google似乎建议使用术语“运营商”来普及和接受,例如Microsoft文档和[es6-features.org]等网站都将其称为“运营商”。

在ECMAScript的上下文中,哪一个术语最正确(如果有),为什么?数组销毁分配又如何呢?


阅读 343

收藏
2020-04-25

共1个答案

小编典典

它不是运算符。

从所有意义上说,这不是一个。自引入以来,这一直是一个巨大的误解,尽管受到了大众的欢迎-这不是一个错误,并且有一些客观要点:

  • 它不符合运算符的定义
  • 不能用作运算符
  • 语言规范暗示它不是运算符

应该提到的是,扩展语法具有不同的“风味”,在不同的上下文中使用,并且在使用相同的标点符号时通常以不同的名称进行引用。传播语法基本上是...标点符号应用的总称,详细介绍了所有用法和名称。关于这些个人用途的更多解释在补充答案中给出。

什么是运算符?

从语义上讲,在ECMAScript上下文中,运算符只是内置函数,这些函数接受参数并求值为单个值
-以前缀,中缀或后缀表示法编写,通常使用诸如+或的符号名/

简而言之,以某种方式评估涉及运算符的表达式,结果值可能只是一个值(一个r值),或者可能是一个允许赋值的对象(一个l值)。

例如,+运算符将得出一个值为2的值,它是一个右侧表达式,.运算符将得出一个对象,该对象允许赋值,例如foo.bar左侧表达式。

在表面上,...标点符号1看起来像是前缀一元运算符:

const baz = [foo, ...bar];

但是该论点的问题在于,...bar它的求值结果不是奇异的。它bar逐一散布了iterable 的元素。传播参数也是如此:

foo(...bar);

在这里,从iterable foo接收单独的参数bar。它们是传递给的单独值foo,而不仅仅是一个值。它不符合运算符的定义,因此不是一个。

为什么它不是运算符?

需要指出的另一点是,运算符应独立并且返回单个值。例如:

const bar = [...foo];

如前所述,这很好。当您尝试执行此操作时会出现问题:

const bar = ...foo;

如果将扩展语法用作运算符,则后者会很好用,因为运算符将表达式评估为单个值,但是扩展则不会,因此失败。扩展语法和扩展参数仅在数组和函数调用的上下文中起作用,因为这些结构会接收由扩展数组元素或参数提供的多个值。评估多个值超出了操作员的能力范围。

标准怎么说?

ECMAScript 2015语言规范的第12.5至§12.15节中列出了运算符的完整列表...,其中未提及引入的规范...。也可以推断出它不是运算符。下面描述了此答案中提到的两种主要情况,其中在函数中使用了扩展语法,分别是函数调用(扩展参数)或数组文字(扩展语法):

ArrayLiteral :
[ Elisionopt ]
[ ElementList ]
[ ElementList , Elisionopt ]

ElementList :
Elisionopt AssignmentExpression
Elisionopt SpreadElement
ElementList , Elisionopt AssignmentExpression
ElementList , Elisionopt SpreadElement

Elision :
,
Elision ,

SpreadElement :
... AssignmentExpression

对于函数调用:

CallExpression :
  MemberExpression Arguments

Arguments :
  ( )
  ( ArgumentList )

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

在这些作品中,可以得出一个结论:传播的“经营者”不存在。如前所述,运算符应该是独立的,const bar = ...foo并且应评估为一个单一值。该语言的语法阻止了这种情况,这意味着散布语法从来都不是独立的。它是 数组初始化程序和函数调用的扩展,是它们语法的扩展。

为什么传播“语法”?

语法,由Wikipedia定义:

在计算机科学中,计算机语言的语法是一组规则,这些规则定义了符号的组合,这些符号被认为是该语言中结构正确的文档或片段。

语法基本上是语言的“形式”,是控制有关代码外观和代码编写方式的合法性或不合法性的规则。在这种情况下,ECMAScript的语法专门将...标点符号定义为仅在函数调用和数组文字中作为扩展出现这是一个规则,用于定义...foo被认为合法的符号()的组合,因此其语法类似于箭头函数(=>)的作用方式不是运算符,而是语法2。

呼叫...接线员是错误的说法。运算符是一个内置函数,它接受参数(操作数),并且采用前缀,中缀或后缀表示法的形式,并且其计算结果恰好是一个值。...,虽然满足前两个条件,但不满足最后一个条件。...而是语法,因为它是在语言的语法中明确定义的。因此,“散布算子”在客观上更正确地称为“散布语法”。


1术语“标点符号”是指ECMAScript2015及更高版本规范中的标点符号。这些符号包括语法组件和运算符,并且是语言的标点符号。...是标点符号本身,但术语“扩展语法”是指标点符号的整个应用程序。

2 =>本身就是一个 标点符号,...但是我具体要指的是箭头函数语法,即=>标点符号((…) => { … })的应用,就像传播语法_ 指的是...标点符号的应用一样。

2020-04-25