JavaScript 语法中有效的左侧表达式是什么?

IT技术 javascript 语法 ecma262
2021-02-23 04:01:53

好的,我们都知道有效的左侧表达式是什么。的种类。*

但是,查看ECMA-Script 标准中的定义,我很困惑:

LeftHandSideExpression :
    NewExpression
    CallExpression

这只是定义中的错误,还是我在这里弄错了?我的意思是,这不是真的意味着

new Object = 1; // NewExpression AssignmentOperator PrimaryExpression
function () { return foo; }() = 1;// CallExpression AssignmentOperator PrimaryExpression

应该是有效的赋值表达式吗?


* 根据我的拙见,这会更有意义:

LeftHandSideExpression :
    Identifier
    MemberExpression [ Expression ]
    MemberExpression . IdentifierName
    CallExpression [ Expression ]
    CallExpression . IdentifierName

2个回答

为了简明扼要地回答您的问题,作品下方的所有内容LeftHandSideExpression都是有效的LeftHandSideExpression.


我认为你真正要问的问题是:

什么是有效LeftHandSideExpression且可分配的?

答案是任何可以解析为 a 的东西,Reference这是规范中定义明确的概念。在你的例子中

new Object = 1;

new Object是有效的LeftHandSideExpression,但它不能解决的Reference

(new Object).x = 1;

左侧是 aMemberExpression . IdentifierName根据规范,最后一步是:

返回一个引用类型的值...


如果您将其视为 2 个独立的属性,则它更有意义。

  1. 它是一个有效的 LeftHandSideExpression 吗?
  2. 它是一个有效的参考吗?

属性 1 在句法分析阶段确定,属性 2 在语义分析阶段确定。查看8.7.2 PutValue (V, W)了解更多详情。

这是规范本身的完整解释:

8.7 参考规范类型

Reference 类型用于解释诸如 delete、typeof 和赋值运算符等运算符的行为。例如,赋值的左侧操作数预计会产生一个引用。相反,赋值的行为可以完全通过对赋值运算符左侧操作数的句法形式的案例分析来解释,但有一个困难:允许函数调用返回引用。承认这种可能性纯粹是为了宿主对象。本规范定义的内置 ECMAScript 函数没有返回引用,也没有规定用户定义的函数返回引用。(不使用句法案例分析的另一个原因是它会冗长而笨拙,会影响规范的许多部分。)


看了你的建议后,我相信它会抛弃某些有效的表达方式(注意:我不宽恕这一点。)

function OuterObj() {
    this.Name = "Outer";
    this.InnerObj = function() {
        this.Name = "Inner";
    }
}

var obj; (obj = new new OuterObj().InnerObj).Name = "Assigned";

这是一个NewExpression很重要的案例

真的。我一直认为第 2 阶段是在运行时执行的,而第 1 阶段发生在解析时。因此,if (false) { new Object = 1; }应该不是语法错误,并且在 Safari 中确实可以工作。查看 Firefox 源代码后,我想到了这一点:Firefox 将此视为一种特殊情况。(有趣的事实:错误代码被称为JSMSG_BAD_LEFTSIDE_OF_ASS
2021-04-27 04:01:53
@Pumbaa80 - 我认为在动态语言中这样做真的很有意义。
2021-05-11 04:01:53
为什么规范将生产 ClassHeritage 设置为“扩展”LeftHandSideExpression?不应该是 BindingIdentifier 吗?我发现这非常复杂。想象一个类定义,如 class X extends (new Y) 或 class X extends (function() {})!世界上谁会需要这样的功能?事实上,firefox 甚至指责第一种情况无效。
2021-05-13 04:01:53

这是另一种 JavaScript 语法,它只匹配有效的 LeftHandSideExpressions,即实际可赋值的 LeftHandSideExpressions。

NewExpression :
    PrimaryExpression
    new NewExpressionQualifier Arguments
    new NewExpressionQualifier

NewExpressionQualifier :
    NewExpressionQualifier Qualifier
    NewExpression

CallExpression :
    NewExpression
    CallExpressionQualifier Arguments

CallExpressionQualifier :
    CallExpression
    CallExpressionQualifier Qualifier

LeftHandSideExpression :
    LeftHandSideExpression Qualifier
    CallExpression Qualifier
    Identifier
    ( LeftHandSideExpression )
    ( Expression , LeftHandSideExpression )

Qualifier :
    . IdentifierName
    [ Expression ]

关联的 new 或 call 表达式的选择不明确的每个 Arguments 应与最接近的可能的 new 表达式相关联,否则将没有相应的 Arguments。我认为这是 JavaScript 语法中同时存在 NewExpression 和 MemberExpression 非终结符的原因之一。

根据您对LeftHandSideExpressionI的定义得出结论,这(a = 1, b)将是一个可分配的LeftHandSideExpression. 但是,在赋值中使用它会(a = 1, b) = 2导致Uncaught ReferenceError: Invalid left-hand side in assignment.
2021-04-23 04:01:53
逗号运算符不是左侧表达式,因为它不返回引用 (4. Return GetValue(rref))。但是,它可能包含一个简单的赋值表达式作为右操作数。a = 1, b = 2可能被分组为(a = 1) , (b = 2),但(a = 1, b) = 2会导致GetValue(b) = 2
2021-05-04 04:01:53