为什么JS computed 属性语法允许赋值表达式?
Why does JS computed property grammar allow assignment expression?
Javascript 语法允许在计算的 属性 名称 (ComputedPropertyName
) 中使用赋值表达式 (AssignmentExpression
)(请参阅 12.2.6 Object Initializer or ES 2015 Grammarkdown) :
ComputedPropertyName[Yield] :
`[` AssignmentExpression[In, ?Yield] `]`
这允许一个写作例如:
var data;
var a= {
[data="something"]: "x"
}
为什么这有用?为什么用 ConditionalExpression
还不够?这似乎是不必要的语法复杂化。
基本上,这与您的第一个想法相反。 ComputedPropertyName
中允许的表达式类型无需特例,因此语言设计者选择使用 "normal" 表达式,即 AssignmentExpression
.
如果您查看 EcmaScript 语法,您会发现使用 ConditionalExpression
的唯一地方是在 AssignmentExpression
的定义中。在这方面,它类似于 AssignmentExpression
之前文法中定义的所有其他表达式子语法,它们仅用于定义文法的运算符优先顺序。 (基于运算符优先级解析的实用解析器甚至可能没有对应于这些各种非终结符的任何内容。)
基本上,除了定义运算符优先级外,文法中只使用了两个表达式非终结符:AssignmentExpression
和Expression
。差异与 comma operator 不幸的 C 遗留问题有关(它求值然后忘记它的第一个参数)。 Expression
用于允许使用逗号运算符的上下文:
Expression: AssignmentExpression
| Expression ',' AssignmentExpression
包括 Statement
中几乎所有使用表达式的地方。 AssignmentExpression
(并且没有其他表达式子语法)用于 ,
指示表达式列表的上下文中:参数列表、数组文字等。很难证明将赋值表达式的使用仅限于语言的一个模糊角落,而它们在任何其他允许表达式的上下文中都可以很好地使用。
实际上有一个论点使 ComputedPropertyName
语法更加宽松,而不是禁止使用逗号运算符,因为 属性 访问语法 (MemberExpression '[' Expression ']'
) 是逗号运算符 是 允许的众多地方之一,尽管实际上从未使用过。
实际上写 array[i, j]
是——至少恕我直言——糟糕的风格,因为它几乎肯定会让那些没有意识到它与 array[j]
意思相同的天真的读者感到困惑(除非评估 i
有副作用)。在逗号运算符可用的语言(C、C++、EcmaScript 等)中,这种用法主要是一种混淆技术,Whosebug 包含大量混淆有效的证据。我认为,只有保持与混淆代码的向后兼容性的需要才阻止委员会从 属性 访问语法中删除逗号运算符。
由于 ComputedPropertyName
语法基本上类似于 属性 访问语法,因此人们可能希望它也是 Expression
,而不是 AssignmentExpression
。但显然委员会能够抵制诱惑。
Javascript 语法允许在计算的 属性 名称 (ComputedPropertyName
) 中使用赋值表达式 (AssignmentExpression
)(请参阅 12.2.6 Object Initializer or ES 2015 Grammarkdown) :
ComputedPropertyName[Yield] :
`[` AssignmentExpression[In, ?Yield] `]`
这允许一个写作例如:
var data;
var a= {
[data="something"]: "x"
}
为什么这有用?为什么用 ConditionalExpression
还不够?这似乎是不必要的语法复杂化。
基本上,这与您的第一个想法相反。 ComputedPropertyName
中允许的表达式类型无需特例,因此语言设计者选择使用 "normal" 表达式,即 AssignmentExpression
.
如果您查看 EcmaScript 语法,您会发现使用 ConditionalExpression
的唯一地方是在 AssignmentExpression
的定义中。在这方面,它类似于 AssignmentExpression
之前文法中定义的所有其他表达式子语法,它们仅用于定义文法的运算符优先顺序。 (基于运算符优先级解析的实用解析器甚至可能没有对应于这些各种非终结符的任何内容。)
基本上,除了定义运算符优先级外,文法中只使用了两个表达式非终结符:AssignmentExpression
和Expression
。差异与 comma operator 不幸的 C 遗留问题有关(它求值然后忘记它的第一个参数)。 Expression
用于允许使用逗号运算符的上下文:
Expression: AssignmentExpression
| Expression ',' AssignmentExpression
包括 Statement
中几乎所有使用表达式的地方。 AssignmentExpression
(并且没有其他表达式子语法)用于 ,
指示表达式列表的上下文中:参数列表、数组文字等。很难证明将赋值表达式的使用仅限于语言的一个模糊角落,而它们在任何其他允许表达式的上下文中都可以很好地使用。
实际上有一个论点使 ComputedPropertyName
语法更加宽松,而不是禁止使用逗号运算符,因为 属性 访问语法 (MemberExpression '[' Expression ']'
) 是逗号运算符 是 允许的众多地方之一,尽管实际上从未使用过。
实际上写 array[i, j]
是——至少恕我直言——糟糕的风格,因为它几乎肯定会让那些没有意识到它与 array[j]
意思相同的天真的读者感到困惑(除非评估 i
有副作用)。在逗号运算符可用的语言(C、C++、EcmaScript 等)中,这种用法主要是一种混淆技术,Whosebug 包含大量混淆有效的证据。我认为,只有保持与混淆代码的向后兼容性的需要才阻止委员会从 属性 访问语法中删除逗号运算符。
由于 ComputedPropertyName
语法基本上类似于 属性 访问语法,因此人们可能希望它也是 Expression
,而不是 AssignmentExpression
。但显然委员会能够抵制诱惑。