首页 > 解决方案 > ecma262中的赋值表达式

问题描述

考虑以下代码

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

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

现在,当我在赋值运算符评估中查看 ecma262 时

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

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

LeftHandSideExpression = 赋值表达式

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

标签: javascriptecma262

解决方案


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

myVar = 'Hello'

如果我们看一下13.15.2 运行时语义:评估AssignmentExpression行的评估

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

将深入了解各个步骤,直到您最终运行13.1.3 运行时语义:评估,它定义了myVar.

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

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

foo().bar = val();

因为评估 left 意味着foo()运行 before val(),这是您所期望的。在这种情况下foo()运行,然后我们得到一个Reference Record带有返回值的foo()作为赋值的目标,并bar作为要赋值的属性名称。

回到13.15.2 运行时语义:评估,我们开始

1.e 执行?放置值(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)

推荐阅读