ES6中for循环的作用范围是什么? [英] What's the action scope of for-loop in ES6?
问题描述
JavaScript的for循环中let
的确切作用范围是什么?
What's exactly the action scope of let
in a for-loop in JavaScript?
for (let i = 0; i < 3; i++) {
let i = 4;
console.log(i);
}
console.log(i);
外部console.log
引发错误:
未捕获的引用错误:我未定义"
"Uncaught Reference Error: i is not defined"
证明i
在块操作范围内,但是,为什么在for循环中定义的i
不会引发任何重复的定义错误?
It proves i
is in a block action scope, however, why doesn't the i
defined in the for-loop throw any duplicate definition error?
推荐答案
for
循环的主体(带有let
变量声明)具有两个范围(或LexicalEnvironments):一个作用域是迭代环境,它包含在for
循环声明中用let
声明的变量,内部作用域包含在for循环体内(在{
之后)声明的变量.在规范中对此进行了描述,从 13.7.4.7运行时语义:LabelledEvaluation
The body of a for
loop (with a let
variable declaration) has two scopes (or LexicalEnvironments): one scope is the iteration environment, which contains the variables declared with let
in the for
loop declaration, and the inner scope contains variables declared inside the for loop body (after the {
). This is described in the specification, starting at 13.7.4.7 Runtime Semantics: LabelledEvaluation
IterationStatement:用于(LexicalDeclaration表达式; Expression)语句
IterationStatement : for ( LexicalDeclaration Expression; Expression ) Statement
(这是用for
声明变量的for
循环的意思.)
(this is what a for
loop which declares a variable with let
is.)
评估以上内容最终会使您:
Evaluating the above eventually gets you to:
- 让bodyResult为ForBodyEvaluation(第一个表达式,第二个表达式,语句,perIterationLets,labelSet).
请注意,声明"可以是一个块(可以像大多数for
循环主体那样,以{
开头并以}
结尾)-这非常重要,因为块会创建另一个词汇环境.
Note that "Statement" can be a block (can start with {
and end with }
, as most for
loop bodies do) - this is very important, because a block creates another lexical environment.
13.7.4.8运行时语义:ForBodyEvaluation 说:
-
执行? CreatePerIterationEnvironment(perIterationBindings).
Perform ? CreatePerIterationEnvironment(perIterationBindings).
重复
b.令result为评估stmt的结果.
b. Let result be the result of evaluating stmt.
...
e.履行 ? CreatePerIterationEnvironment(perIterationBindings).
e. Perform ? CreatePerIterationEnvironment(perIterationBindings).
其中CreatePerIterationEnvironment
创建包含变量的环境在for
循环声明中用let
声明:
where CreatePerIterationEnvironment
creates an environment containing the variables declared with let
in the for
loop declaration:
g.对于perIterationBindings的每个元素bn,执行
g. For each element bn of perIterationBindings, do
i.履行 ! thisIterationEnvRec.CreateMutableBinding(bn,false).
i. Perform ! thisIterationEnvRec.CreateMutableBinding(bn, false).
ii.让lastValue为? lastIterationEnvRec.GetBindingValue(bn,true).
ii. Let lastValue be ? lastIterationEnvRec.GetBindingValue(bn, true).
< iii.执行thisIterationEnvRec.InitializeBinding(bn,lastValue).
iii. Perform thisIterationEnvRec.InitializeBinding(bn, lastValue).
因此,有两个作用域:一个作用域由CreatePerIterationEnvironment
创建,另一个作用域由stmt
所在的块创建.
So, there are two scopes: one created by CreatePerIterationEnvironment
, and one created by the block that the stmt
is.
for (let i = 0; i < 3; i++) {
let foo = 'f';
}
在这里,i
包含在外部迭代环境中,而foo
包含在内部块中,这是一个不同的环境.如果使这两个变量名称相同,则不会引发错误,因为该块内的let <variableName>
会创建一个作用于该块的变量 ,并且不会尝试覆盖变量名相同的变量. 迭代环境.
Here, i
is contained in the outer iteration environment, and foo
is contained in the inner block, which is a different environment. If you made those two variable names names the same, no error is thrown because let <variableName>
inside the block creates a variable scoped to that block, and does not try to overwrite the variable with the same name in the iteration environment.
这篇关于ES6中for循环的作用范围是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!