解除 for 循环时 var 和 let 定义变量的困惑

这个问题的产生以及应用场景就很少说了,基本每一个人都会遇到,下面直接上代码。

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i); // i 指向全局的 i,也就是数组中函数全部的i都指向的是同一个变量i
  };
}
a[6](); // 10
复制代码

上面代码中,变量i是var命令声明的,在全局范围内都有效,因此全局只有一个变量i。每一次循环,变量i的值都会自增,而循环内被赋给数组a的函数内部的console.log(i),里面的i指向的就是全局的i。也就是说,全部数组a的成员里面的i,指向的都是同一个i,致使运行时输出的是循环结束以后i的值,也就是 10。数组

若是使用let,声明的变量仅在块级做用域内有效,最后输出的是 6。闭包

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i); //因为 let 建立的变量是块级做用域的,因此在这个函数内每次都保存一个新的 i
  };
}
a[6](); // 6
复制代码

这是由于let 建立的变量是块级做用域的,因此每次循环都是一个新的 i,每次的值都是 i++ 的结果。由于每次循环的 i 都是一个独立的变量(内存里的惟一地址),所以闭包记录的值都是惟一的,因此才能获得最终的结果函数

若是用 var 的话,变量 i 是一个全局变量,虽然循环体内每次都建立了一个函数来打印 i,可是当时当刻仅仅是一个指向全局变量 i 的指针,当循环结束以后不管你用哪个下标去访问循环建立的闭包函数,打印的变量 i 都是全局的那一个,因此所有都是 10。ui

相关文章
相关标签/搜索