9.5 循环头中的 letconst

在以下循环头中允许声明变量:

  • for
  • for-in
  • for-of

声明一个变量,你可以使用 varlet 或者 const。每一种方式有不一样的效果,下面我将进行解释。

9.5.1 for 循环

for 循环头中使用 var 创建的变量只创建单个绑定(binding):

let arr = [];
for (var i=0; i < 3; i++) {
    arr.push(() => i);
}
arr.map(x => x()); // [3,3,3]

在代码块中的三个箭头函数中的 i 都指向了同一个 binding,这就是为什么他们都返回相同的值。

如果你使用 let 声明变量,循环的每一次都会创建一个 binding :

let arr = [];
for (let i=0; i < 3; i++) {
    arr.push(() => i);
}
arr.map(x => x()); // [0,1,2]

这一次,每个 i 指向一个循环体中的 binding 并且保持当时的值。因此,每个箭头函数都返回不同的值。

const 工作方式与 var 类似,但是不能改变 const 声明变量时初始化的值。

刚开始也许会觉得在每个循环中获取新的 binding 似乎很奇怪,但是当你使用循环创建指向循环变量的函数(例如事件处理的回调)时它非常有用。

for 循环:规范中的迭代绑定
The evaluation of the for 循环 在第二例介绍 var 并且在第三例介绍 let/const。 仅仅 let 定义的变量被加到 perIterationLets 列表(步骤 9), 作为传递给 ForBodyEvaluation() 的第一个之后的参数 perIterationBindings

9.5.2 for-of 循环和 for-in 循环

In a for-of loop, var creates a single binding:

for-of 循环头中使用 var 创建的变量只创建单个绑定(binding):

let arr = [];
for (var i of [0, 1, 2]) {
    arr.push(() => i);
}
arr.map(x => x()); // [2,2,2]

let 在循环的每一次都会创建一个 binding :

let arr = [];
for (let i of [0, 1, 2]) {
    arr.push(() => i);
}
arr.map(x => x()); // [0,1,2]

const 也会在循环的每一次都会创建一个 binding ,但是创建的 bindings 是不可变的。

for-in 循环与 for-of 工作方式类似.

for-of 循环:规范中的迭代绑定
ForIn/OfBodyEvaluation 中介绍了 for-of 的迭代绑定。 在步骤 5.b 中, 创建一个新的环境,并且绑定通过 BindingInstantiation 被增加。当前的迭代值存入变量 nextValue ,并且在如下两种方式中用于初始化绑定:

results matching ""

    No results matching ""