javascript - 为什么 `(foo) = "bar"` 在 JavaScript 中是合法的?

标签 javascript ecma

在 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正如您正确识别的那样。这可以通过各种优先级别( NewExpressionMemberExpression )追踪到 PrimaryExpression ,这又可能是一个 Cover­Parenthesized­Expression­And­Arrow­Parameter­List :

( 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 is false.

我们也可以在 evaluation of assignment expressions 中看到这种区别,其中简单的赋值目标被评估为可以分配给的引用,而不是获取对象和数组文字等解构模式的东西。

那是什么 IsValidSimpleAssignmentTargetLeftHandSideExpressions 做什么?基本上,它允许对属性访问进行赋值,而不允许对调用表达式进行赋值。它没有说明任何关于普通 PrimaryExpressions 的信息,它们有自己的 own IsValidSimpleAssignmentTarget rule .它所做的只是通过 Covered­Parenthesized­Expression operation 提取括号之间的 Expression ,然后再次检查它的 IsValidSimpleAssignmentTarget。简而言之:(…) = … 有效时 … = … 有效。它只会为 Identifiers 产生 true (如您的示例)和属性。

关于javascript - 为什么 `(foo) = "bar"` 在 JavaScript 中是合法的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43969489/

相关文章:

javascript - React 将普通事件处理程序委托(delegate)给文档,绑定(bind)函数怎么样?

javascript - 检查日期是否在过去的 Javascript

javascript - 浏览器 intl.NumberFormat 未正确显示货币符号

javascript - 这段代码如何查找两个对象数组之间的差异?

javascript - javascript promise中的 "then block"和 "then handler"有什么区别?

javascript - 如何停止使用 javascript 传播滚动事件?

javascript - RequireJS 路径中具有一个标识符的多个文件

javascript - 如何比较忽略特殊字符的javascript中的字符串

javascript - 从 TypeScript 对象中删除动态键

javascript - 令人困惑的 EcmaScript 规范 - 声明绑定(bind)实例化