【问题标题】:assignment expression in ecma262ecma262中的赋值表达式
【发布时间】:2021-10-10 01:54:06
【问题描述】:

考虑下面的代码

var myVar = 'Hola';
{
  let myVar;
  myVar = 'Hello'
}

在第 4 行(myVar = 'Hello')我们使用了赋值运算符

现在当我在Assignment Operators Evaluation 中查看 ecma262 时

它说赋值运算符的左边是LeftHandSideExpression,右边是AssignmentExpression

换句话说,它看起来像这样

LeftHandSideExpression = 赋值表达式

谁能向我解释 myVar 将如何被评估? 如果它应该是 LeftHandSideExpression ?

【问题讨论】:

  • 我认为你需要澄清你的问题是什么。到目前为止,您已经陈述了很多信息,但没有提出任何具体的要求。
  • 现在怎么样?

标签: javascript ecma262


【解决方案1】:

要理解的主要部分是 evaluate 在这种情况下意味着我们正在为语言中的各种语法部分运行这些 Runtime Semantics: Evaluation 部分。在

的情况下
myVar = 'Hello'

如果我们查看13.15.2 Runtime Semantics: Evaluation 以评估AssignmentExpression 这条线

1.a.令 lref 为评估 LeftHandSideExpression 的结果。

将深入了解各个步骤,直到最终运行 13.1.3 Runtime Semantics: Evaluation,它定义了 myVar 的评估行为。

如果您逐步执行此操作,关键是 lref 不会评估为 JS 值,它会评估为 Reference Record 类型,这不是 JS 代码知道的值,而是表示可以分配值的位置。就你的sn-p而言,它基本上是对变量列表的范围的引用,以及变量的名称,所以稍后执行赋值时,它会在以后完全解析。

对于像这样的例子来说,首先评估左侧的行为更为重要:

foo().bar = val();

因为评估左侧意味着 foo()val() 之前运行,这是您所期望的。在这种情况下,foo() 运行,然后我们得到一个 Reference Record,其返回值为 foo() 作为分配的目标,bar 作为要分配的属性名称。

回到13.15.2 Runtime Semantics: Evaluation,我们开始

1.e 执行? PutValue(lref, rval)。

这是最终分配发生的地方。 rval"Hello" 字符串本身,因为它已被评估。如果你看一下6.2.4.6 PutValue ( V, W ),你可能会猜到第三部分是我们最终得到的变量赋值

  • 6.a.设基数为 V.[[Base]]。
  • 6.b.断言:base 是一个环境记录。
  • 6.c.返回 ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]])

所以你的情况是

(<scope with closest `var/let myVar`).SetMutableBinding("myVar", "Hello", false)

【讨论】:

  • 据我了解 LeftHandSideExpression 可以是很多东西,它可以是 identifierReference 它也可以是 this 关键字,在 myVar = 'Hello' 的情况下,它是一个 identifierReference 对吗?因此,您提到的行“1.a. 让 lref 成为评估 LeftHandSideExpression 的结果。”实际上是在进行 identifierReference 评估,即“1. Return ? ResolveBinding(StringValue of Identifier)”。对 ?从中我们得到参考记录
  • 是的,特别是 myVar = 'Hello'; 使用 IdentifierReference。确切的行为取决于右侧的语法,但它们最终都会评估为 Reference Record
【解决方案2】:

在块语句中,所有定义的变量都是局部的,因此块内的myVar 将是"Hello"。在外部,用var 定义的变量是全局变量,它的值从未改变,因为内部myVar 是一个完全不同的变量,只是名称相同。所以用var 定义的外部myVar 从未改变其初始值"Hola"

var myVar = "Hola";
{
  let myVar;
  myVar = "Hello";
  console.log("inside:", myVar);
}
console.log("outside:", myVar);

【讨论】:

    【解决方案3】:

    你可以在左边有不同的东西,比如:

    a = 'foo'
    
    a.b = ['foo','bar']
    
    new Object().b = ['foo','bar']
    
    foo().b = ['foo','bar']
    

    对于a =这个简单的例子,没有什么需要做的。

    但对于a.b =new Object().b =foo().b =,您首先需要评估左侧。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-08-03
      相关资源
      最近更新 更多