为什么在JavaScript中`(foo)=“ bar”`是合法的?

术语:

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

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

有效,foo其后等于"bar"相对于null

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

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

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

根据ECMA-262上的LeftHandExpressions(据我所能解释的),没有有效的非终结符会导致括号被接受。

有什么我没看到的吗?

贝尔吉:

确实是有效的。您可以在括号中包装任何简单的分配目标。

操作的左手部分=LeftHandSideExpression正确识别的a。可以通过各种优先级别(NewExpressionMemberExpression跟踪到a PrimaryExpression,而这又可能是Cover­Parenthesized­Expression­And­Arrow­Parameter­List

 表达式[In,?Yield]  

(实际上,当与target一起解析时PrimaryExpression,它是一个ParenthesizedExpression)。

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

这是一个早期的Reference Error,如果LeftHandSideExpression既不是ObjectLiteral也不是ArrayLiteralIsValidSimpleAssignmentTargetLeftHandSideExpressionfalse

我们还可以在赋值表达式求值中看到这种区别,在赋值表达式中,将简单的赋值目标求值到可以分配给其的引用,而不用获取诸如对象和数组文字之类的解构模式。

那么IsValidSimpleAssignmentTargetLeftHandSideExpressions做了什么?基本上,它允许对属性访问的分配,而不允许对调用表达式的分配。它没有声明任何具有自己的IsValidSimpleAssignmentTarget规则的普通PrimaryExpression它所做的就是通过CoveredParenthesizedExpression操作提取括号之间Expression,然后再次检查该对象的IsValidSimpleAssignmentTarget。简而言之:有效时有效。这将产生唯一的标识符(如在你的例子)和属性。(…) = …… = …true

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

嵌套参数扩展:为什么 ${foo%"$bar"} 合法,而 ${$bar} 不合法?

typedef struct foo {int bar};的合法性;

为什么foo = bar与foo = bar不同?

为什么在bash中[“ $ foo” ==“ $ bar”]始终为true?

为什么字符串索引在JavaScript数组中合法?

为什么 println!(foo.bar()?) 移动 foo?

为什么不要求在赋值`foo = $ bar`中双引号`$ bar`?

为什么在JS中,“ function(){{”是合法的?

Clojure中的:foo,:: foo,:: bar / foo和:bar / foo有什么区别?

为什么使用Foo [T <:Bar]要求Foo [_ <:Bar]而不是Foo [_]

发现这是一个旧的代码库,并且想知道它是否合法:if($ foo =〜“ bar” and“ baz”){

为什么在ES6中,“ foo” .bar = 42;在严格模式下抛出TypeError?

在PHP中,当类不存在时,为什么\ Foo \ Bar :: class不会生成错误?

为什么FOO = bar; 将变量导出到我的环境中

Rust中的Foo(bar)= zar是什么?

python中装饰器中的foo=bar(foo)和something=bar(foo)有什么区别?

“ lambda不能有赋值语句”-那么“ foo = lambda x:x * 2”为什么合法?

为什么“ gcc -E”之后“ foo \\ <NEWLINE> bar”变成“ foo \ bar”?

为什么是“ Foo f(Bar());” 可以是采用Bar类型并返回Foo类型的函数的声明?

foo =“ bar”; if(foo ==“ bar”){doX(); }其他{“但是这总是运行”}为什么?

域foo.bar指向127.0.53.53-为什么?

为什么object [bar]与object [foo]具有相同的输出?

为什么 ++var++ 不是合法的 Javascript 表达式?

从函数的输出创建 Bash 关联数组:为什么“declare -A foo=$(bar)”有效,但“declare -A foo; foo=$(bar)”无效?

什么是`int foo :: * bar :: *`?

“后卫让foo = foo”何时合法?

为什么grep 不匹配单词边界处的正斜杠(例如`import baz from './foo/bar/baz';` 中的`/baz`)?

为什么以下注释在Java中合法但在Groovy中不合法?

为什么在 C 中重新声明函数是合法的?