在Node.js的REPL中(也已在SpiderMonkey中进行了测试)
var foo = null;
(foo) = "bar";
是有效的,
foo
随后等于"bar"
,而不是null
。这似乎违反直觉,因为人们会认为括号至少会取消引用
bar
并在赋值中抛出无效的左侧。可以理解,当您做任何有趣的事情时,它确实会以上述方式失败。
(foo, bar) = 4
(true ? bar : foo) = 4
根据ECMA-262 on LeftHandExpressions(据我所知),没有有效的非终结符会导致括号被接受。
有没有我看不到的东西吗?
最佳答案
确实是有效的。您可以在括号中包装任何简单的分配目标。
正确识别的=
操作的左侧部分是 LeftHandSideExpression
。可以通过各种优先级别( NewExpression
, MemberExpression
)追踪到 PrimaryExpression
,而 CoverParenthesizedExpressionAndArrowParameterList
可以是 PrimaryExpression
:
(Expression [In,?Yield])
(实际上,当与目标ParenthesizedExpression
一起解析时,它是early errors for assignment expressions)。
因此,至少在语法上是有效的。 JS语法是否真正有效取决于另一个因素:早期错误静态语义。这些基本上是散文或算法规则,在某些情况下会使某些生产扩展无效(语法错误)。例如,这允许作者重用数组和对象初始化程序语法进行解构,但仅应用某些规则。在evaluation of assignment expressions中,我们发现
我们还可以在IsValidSimpleAssignmentTarget中看到这种区别,在own IsValidSimpleAssignmentTarget rule中,将简单的分配目标评估为可以分配给的引用,而不用获取诸如对象和数组文字之类的破坏性模式。
那么,CoveredParenthesizedExpression operation对LeftHandSideExpressions有什么作用?基本上,它允许对属性访问的分配,而不允许对调用表达式的分配。它没有声明具有Identifiers的普通PrimaryExpressions的任何内容。它所做的就是通过ojit_a提取括号之间的表达式,然后再次检查该表达式的IsValidSimpleAssignmentTarget。简而言之:(…) = …
有效时,… = …
有效。它只会为ojit_a(如您的示例中)和属性生成true
。