var和let的区别,为什么这两个函数执行的结果不一样呢

var arr = [];
for(**var** i = 0; i < 10; i++){
        arr[i] = function(){
        return i;
    };
}
for(var j = 0; j < arr.length; j++){
    console.log(arr[j]() + " ");     
} //10个10

var和let的区别在哪呢,为什么声明不一样就会变成不一样的结果呢?还有第一个函数为什么i最后都等于10了?i这里是局部变量还是全局变量呢?局部变量不应该for循环完就自动被GC了吗 还是说第一个函数存在闭包所以保留了对i的引用,所以i不会被GC了

var arr = [];
for(**let** i = 0; i < 10; i++){
    arr[i] = function(){
        console.log(i);
    };
}
for(var j = 0; j < arr.length; j++){
    console.log(arr[j]());
}//0-9
阅读 2.6k
4 个回答

var 存在变量提升,所以你写的

for(var i = 0; i < 10; i++){
        arr[i] = function(){
        return i;
    };
}

等同于

var i
for(i = 0; i < 10; i++){
        arr[i] = function(){
        return i;
    };
}

实际上就是定义了一个全局变量。

虽然你return的是i,但是你在调用arr[i]这个函数的时候,会沿着作用域链找到arr[i]这个函数的上一层作用域,在这里即是全局作用域。所以你调用的时候var已经是10了,可以在 for循环后面添加一个console.log(i)验证。

let 会创建一个作用域。则,这里就会形成一个闭包
所以,使用let定义时,则分成了三层 Global --> Closure --> Local 作用域
所以你在调用arr[i]这个函数时,其实会根据作用域链找到Closure(闭包)中的 变量 i 。
使用下面这行代码,打开浏览器中的Source面板并查看右侧的Scope(作用域链)验证。


        var arr = []
        for(let i = 0 ;i<10 ;i++){
            arr[i] = function(){
                debugger
                console.log(i);
            };


        }


        for(var j = 0; j < arr.length; j++){
            console.log(arr[j]());
        }//0-9

ps:个人理解,如有错误,希望指出

这种问题请去baidu 作用域与闭包
var变量提升,第一个里循环结束i=10,所以会打印10个10
第二个是典型的闭包,每一个闭包引用内部的i变量,所以是0-9

for(var i =0....)
这里的 i 是全局变量
arr[i] 的赋值 是一个 函数表达式 在定义的时候不存在作用域引用关系
let 存在块级作用域
所以在 函数表达式定义的时候存在块级作用域的引用关系 这里每循环一次都会创建一个作用域

总结下来大概是:一个函数表达式在 定义的时候 如果存在 函数/块级作用域变量的引用 那么 这个作用域就自动创建并一直保存

第二个 for循环中 属于立刻执行的一段代码 因此可以实施取到j的值

推荐问题
宣传栏