为什么 JS 计算属性语法允许赋值表达式?



Javascript语法允许在计算的属性名称(ComputedPropertyName(中使用赋值表达式(AssignmentExpression((参见12.2.6对象初始值设定项或ES 2015 Grammarkdown(:

ComputedPropertyName[Yield] :
`[` AssignmentExpression[In, ?Yield]  `]`

这允许一个人写作,例如:

var data;
var a= {
[data="something"]: "x"
}

为什么这很有用?为什么有ConditionalExpression还不够?这似乎是语法不必要的复杂化。

基本上,它与你第一个想法相反。没有必要对ComputedPropertyName内允许的那种表达式进行特殊处理,所以语言设计者选择使用"normal"表达式,这是一个AssignmentExpression

如果您浏览 EcmaScript 语法,您会发现唯一使用ConditionalExpression的地方是在AssignmentExpression的定义中。在这方面,它类似于AssignmentExpression之前在语法中定义的所有其他表达式子语法,它们的存在只是为了定义语法的运算符优先级顺序。(基于运算符优先级解析的实用解析器甚至可能没有任何对应于这些各种非终端的内容。

基本上,除了定义运算符优先级之外,语法中只使用两个表达式非终端:AssignmentExpressionExpression。这种差异与逗号运算符的不幸的 C 遗留问题有关(它计算然后忘记其第一个参数(。Expression用于允许使用逗号运算符的上下文中:

Expression: AssignmentExpression
| Expression ',' AssignmentExpression

包括Statement中几乎所有使用表达式的地方。AssignmentExpression(而不是其他 Expression 子语法(用于,表示表达式列表的上下文中:参数列表、数组文本等。很难证明将赋值表达式的使用限制在语言的一个晦涩角落是很困难的,而它们在任何其他允许表达式的上下文中都可以很好地使用。

实际上有一个论点是使ComputedPropertyName语法更加宽松,而不是禁止使用逗号运算符,因为属性访问语法(MemberExpression '[' Expression ']'(是允许逗号运算符的众多地方之一,尽管它实际上从未被使用过。

实际上,写array[i, j]是 - 至少恕我直言 - 糟糕的风格,因为它几乎肯定会让天真的读者感到困惑,他们没有意识到它与array[j]的意思相同(除非评估i有副作用(。在逗号运算符可用的语言(C,C++,EcmaScript等(中,这种用法主要是一种混淆技术,而StackOverflow包含大量混淆工作的证据。我想只有需要保持与混淆代码的向后兼容性才能阻止 Comittee 从属性访问语法中删除逗号运算符。

由于ComputedPropertyName语法基本上类似于属性访问语法,人们可能期望它也Expression,而不是AssignmentExpression。但显然,委员会能够抵制住这种诱惑。

最新更新