在 Node.js 的 REPL 中(也在 SpiderMonkey 中测试过)序列
var foo = null;
(foo) = "bar";
有效,foo
随后等于 "bar"
而不是 null
。
这似乎违反直觉,因为人们会认为括号至少会取消引用 bar
并抛出 Invalid left-hand side in assignment`。
可以理解,当你做任何有趣的事情时,它确实会以上述方式失败。
(foo, bar) = 4
(true ? bar : foo) = 4
根据 ECMA-262 on LeftHandExpressions (据我所知)没有有效的非终结符会导致括号被接受。
有什么我没看到的吗?
最佳答案
这确实有效。您可以将任何简单的赋值目标括在括号中。
=
操作的左侧部分是 LeftHandSideExpression
正如您正确识别的那样。这可以通过各种优先级别( NewExpression
, MemberExpression
)追踪到 PrimaryExpression
,这又可能是一个 CoverParenthesizedExpressionAndArrowParameterList
:
( Expression[In, ?Yield] )
(实际上,当用目标 PrimaryExpression
解析时,它是一个 ParenthesizedExpression
)。
所以它至少在语法上是有效的。它是否实际上是有效的 JS 语法取决于另一个因素:早期错误静态语义。这些基本上是散文或算法规则,在某些情况下会使某些生产扩展无效(语法错误)。例如,这允许作者重用数组和对象初始化语法进行解构,但只应用某些规则。在early errors for assignment expressions我们发现
It is an early
Reference Error
if LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral and IsValidSimpleAssignmentTarget of LeftHandSideExpression isfalse
.
我们也可以在 evaluation of assignment expressions 中看到这种区别,其中简单的赋值目标被评估为可以分配给的引用,而不是获取对象和数组文字等解构模式的东西。
那是什么 IsValidSimpleAssignmentTarget对 LeftHandSideExpressions 做什么?基本上,它允许对属性访问进行赋值,而不允许对调用表达式进行赋值。它没有说明任何关于普通 PrimaryExpressions 的信息,它们有自己的 own IsValidSimpleAssignmentTarget rule .它所做的只是通过 CoveredParenthesizedExpression operation 提取括号之间的 Expression ,然后再次检查它的 IsValidSimpleAssignmentTarget。简而言之:(…) = …
有效时 … = …
有效。它只会为 Identifiers 产生 true
(如您的示例)和属性。
关于javascript - 为什么 `(foo) = "bar"` 在 JavaScript 中是合法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43969489/