为什么JavaScript中的(foo)="bar"是合法的? [英] Why is `(foo) = "bar"` legal in JavaScript?

查看:80
本文介绍了为什么JavaScript中的(foo)="bar"是合法的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Node.js的REPL中(同样也在SpiderMonkey中进行了测试)

In Node.js's REPL (tested in SpiderMonkey as well) the sequence

var foo = null;
(foo) = "bar";

有效,并且 foo 随后等于"bar" ,而不是 null .

is valid, with foo subsequently equal to "bar" as opposed to null.

这似乎是违反直觉的,因为人们会认为括号至少会取消引用 bar 并抛出赋值无效的左侧.

This seems counterintuitive because one would think the parenthesis would at least dereference bar and throw Invalid left-hand side in assignment`.

可以理解,当您做任何有趣的事情时,它确实会以上述方式失败.

Understandably, when you do anything interesting it does fail in aforementioned way.

(foo, bar) = 4
(true ? bar : foo) = 4

根据 ECMA-根据我的理解,LeftHandExpressions上的262 不是有效的非终结符,会导致括号被接受.

According to ECMA-262 on LeftHandExpressions (so far as I can interpret) are no valid non-terminals that would lead to a parenthetical being accepted.

有什么我没看到的东西吗?

Is there something I'm not seeing?

推荐答案

这确实有效.您可以将任何简单的分配目标放在括号中.

It's valid indeed. You're allowed to wrap any simple assignment target in parenthesis.

= 操作的左手部分是 LeftHandSideExpression .可以通过各种优先级别( NewExpression MemberExpression )到 PrimaryExpression ,它可能又是 Cover­ Parenthesized­ Expression­ And­ Arrow­ Parameter­ List :

The left hand part of the = operation is a LeftHandSideExpression as you correctly identified. This can be tracked down through the various precendence levels (NewExpression, MemberExpression) to a PrimaryExpression, which in turn might be a Cover­Parenthesized­Expression­And­Arrow­Parameter­List:

( Expression[In, ?Yield] )

(实际上,当与目标 PrimaryExpression 进行解析时,它是

(actually, when parsed with target PrimaryExpression, it's a ParenthesizedExpression).

因此,至少在语法上是有效的.JS语法是否真正有效取决于另一个因素:早期错误静态语义.这些基本上是散文或算法规则,在某些情况下会使某些生产扩展无效(语法错误).例如,这允许作者重用数组和对象初始化程序语法进行解构,但仅应用某些规则.在早期错误发现赋值表达式

So it's valid by the grammar, at least. Whether it's actually valid JS syntax is determined by another factor: early error static semantics. Those are basically prose or algorithmic rules that make some production expansions invalid (syntax errors) in certain cases. This for example allowed the authors to reuse the array and object initialiser grammars for destructuring, but only applying certain rules. In the early errors for assignment expressions we find

如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral ,则这是早期的 Reference Error . LeftHandSideExpression 的IsValidSimpleAssignmentTarget false .

It is an early Reference Error if LeftHandSideExpression is neither an ObjectLiteral nor an ArrayLiteral and IsValidSimpleAssignmentTarget of LeftHandSideExpression is false.

我们还可以在赋值表达式的求值,其中将简单的赋值目标求值到可以分配给它的引用,而不用获取诸如对象和数组文字之类的破坏性模式.

We can also see this distinction in the evaluation of assignment expressions, where simple assignment targets are evaluated to a reference that can be assigned to, instead of getting the destructuring pattern stuff like object and array literals.

那么

So what does that IsValidSimpleAssignmentTarget do to LeftHandSideExpressions? Basically it allows assignments to property accesses and disallows assignments to call expressions. It doesn't state anything about plain PrimaryExpressions which have their own IsValidSimpleAssignmentTarget rule. All it does is to extract the Expression between the parentheses through the Covered­Parenthesized­Expression operation, and then again check IsValidSimpleAssignmentTarget of that. In short: (…) = … is valid when … = … is valid. It'll yield true only for Identifiers (like in your example) and properties.

这篇关于为什么JavaScript中的(foo)="bar"是合法的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆