ecma262 中的赋值表达式
assignment expression in ecma262
考虑以下代码
var myVar = 'Hola';
{
let myVar;
myVar = 'Hello'
}
在第 4 行(myVar = 'Hello'
)我们使用赋值运算符
现在,当我在 Assignment Operators Evaluation
中查看 ecma262 时
表示赋值运算符左边是LeftHandSideExpression,右边是AssignmentExpression
换句话说看起来像那样
LeftHandSideExpression = AssignmentExpression
任何人都可以向我解释 myVar 将如何评估吗?
如果它应该是 LeftHandSideExpression ?
在块语句中,所有定义的变量都是局部变量,因此块中的 myVar
将是 "Hello"
。在外部,用 var
定义的变量是全局变量,它的值永远不会改变,因为内部 myVar
是一个完全不同的变量,只是名称相同。所以用 var
定义的外部 myVar
从未改变其初始值 "Hola"
.
var myVar = "Hola";
{
let myVar;
myVar = "Hello";
console.log("inside:", myVar);
}
console.log("outside:", myVar);
您可以在左侧放置不同的东西,例如:
a = 'foo'
a.b = ['foo','bar']
new Object().b = ['foo','bar']
foo().b = ['foo','bar']
对于 a =
的简单情况,不需要做太多事情。
但对于 a.b =
、new Object().b =
和 foo().b =
,您首先需要评估左侧。
要理解的主要部分是 evaluate
在这种情况下意味着我们 运行 这些 Runtime Semantics: Evaluation
部分用于语言中的各种语法部分。在
的情况下
myVar = 'Hello'
如果我们查看 13.15.2 Runtime Semantics: Evaluation 以评估 AssignmentExpression
行
1.a. Let lref be the result of evaluating LeftHandSideExpression.
将深入了解各个步骤,直到您最终得到 运行 13.1.3 Runtime Semantics: Evaluation,它定义了 myVar
.
的评估行为
如果你逐步完成这个,关键是 lref
不会评估为 JS 值,它评估为 Reference Record
类型,这不是 JS 代码知道的值, 但表示可以分配值的位置的概念。对于您的代码段,它基本上是对变量列表所在范围和变量名称的引用,因此稍后执行赋值时,它会在稍后完全解析。
这是先评估左侧的行为,对于这样的示例更重要:
foo().bar = val();
因为评估左侧意味着 foo()
在 val()
之前运行,这正是您所期望的。在这种情况下 foo()
运行,然后我们得到一个 Reference Record
,foo()
的 return 值作为赋值的目标,bar
作为 属性 要分配的名称。
回到13.15.2 Runtime Semantics: Evaluation,我们到达
1.e Perform ? PutValue(lref, rval).
这是最终分配发生的地方。 rval
是 "Hello"
字符串本身,因为它已被评估。如果你看一下 6.2.4.6 PutValue ( V, W ),你可能会猜到第 3 部分是我们最终得到的变量赋值
- 6.a。假设 base 为 V.[[Base]].
- 6.b。断言:base 是一个环境记录。
- 6.c。 Return ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]])
所以在你的情况下是
(<scope with closest `var/let myVar`).SetMutableBinding("myVar", "Hello", false)
考虑以下代码
var myVar = 'Hola';
{
let myVar;
myVar = 'Hello'
}
在第 4 行(myVar = 'Hello'
)我们使用赋值运算符
现在,当我在 Assignment Operators Evaluation
中查看 ecma262 时表示赋值运算符左边是LeftHandSideExpression,右边是AssignmentExpression
换句话说看起来像那样
LeftHandSideExpression = AssignmentExpression
任何人都可以向我解释 myVar 将如何评估吗? 如果它应该是 LeftHandSideExpression ?
在块语句中,所有定义的变量都是局部变量,因此块中的 myVar
将是 "Hello"
。在外部,用 var
定义的变量是全局变量,它的值永远不会改变,因为内部 myVar
是一个完全不同的变量,只是名称相同。所以用 var
定义的外部 myVar
从未改变其初始值 "Hola"
.
var myVar = "Hola";
{
let myVar;
myVar = "Hello";
console.log("inside:", myVar);
}
console.log("outside:", myVar);
您可以在左侧放置不同的东西,例如:
a = 'foo'
a.b = ['foo','bar']
new Object().b = ['foo','bar']
foo().b = ['foo','bar']
对于 a =
的简单情况,不需要做太多事情。
但对于 a.b =
、new Object().b =
和 foo().b =
,您首先需要评估左侧。
要理解的主要部分是 evaluate
在这种情况下意味着我们 运行 这些 Runtime Semantics: Evaluation
部分用于语言中的各种语法部分。在
myVar = 'Hello'
如果我们查看 13.15.2 Runtime Semantics: Evaluation 以评估 AssignmentExpression
行
1.a. Let lref be the result of evaluating LeftHandSideExpression.
将深入了解各个步骤,直到您最终得到 运行 13.1.3 Runtime Semantics: Evaluation,它定义了 myVar
.
如果你逐步完成这个,关键是 lref
不会评估为 JS 值,它评估为 Reference Record
类型,这不是 JS 代码知道的值, 但表示可以分配值的位置的概念。对于您的代码段,它基本上是对变量列表所在范围和变量名称的引用,因此稍后执行赋值时,它会在稍后完全解析。
这是先评估左侧的行为,对于这样的示例更重要:
foo().bar = val();
因为评估左侧意味着 foo()
在 val()
之前运行,这正是您所期望的。在这种情况下 foo()
运行,然后我们得到一个 Reference Record
,foo()
的 return 值作为赋值的目标,bar
作为 属性 要分配的名称。
回到13.15.2 Runtime Semantics: Evaluation,我们到达
1.e Perform ? PutValue(lref, rval).
这是最终分配发生的地方。 rval
是 "Hello"
字符串本身,因为它已被评估。如果你看一下 6.2.4.6 PutValue ( V, W ),你可能会猜到第 3 部分是我们最终得到的变量赋值
- 6.a。假设 base 为 V.[[Base]].
- 6.b。断言:base 是一个环境记录。
- 6.c。 Return ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]])
所以在你的情况下是
(<scope with closest `var/let myVar`).SetMutableBinding("myVar", "Hello", false)