下面的代码如果使用var,最后输出的是9。
var a = [];
for (var i = 0; i < 10; i++) {
var c = i;
a[i] = function () {
console.log(c);
};
}
a[6](); // 9为什么一直输出是9??
求高手详解,谢谢
var a = [];
for (var i = 0; i < 10; i++) {
let c = i;
a[i] = function () {
console.log(c);
};
}
a[6](); // 6 //为什么这次是6??
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
很多答案說是 因爲 閉包,這是錯誤的。
即便沒有閉包,由於
var
的自動提前,得到的結果仍舊是 9。所以閉包並不是出現這種情況的原因。正確的原因在於 javascript 的
var
的作用域是函數,而非 block。let
就是讓作用域成爲 block 的。樓下說只有 IE11 支持,這也是錯的。
引用 mdn:
可見目前使用 let 還需要額外的配置,但不代表瀏覽器不支持。
參見:http://stackoverflow.com/questions/762011/javascript-let-keyword-vs-var-keyword
var
的作用域是函數,而let
的作用域是 statement group。因此,使用
var
的版本,閉包中原先的數值被循環改變;而使用
let
的版本,閉包中的數值的作用域小於循環的作用域,沒有被改變,從而保留了原始值。無論
var
還是let
,都會自動被提前。實際上等價於
var a; a = b
; 提前的只是var a
。所以你在for
裏面var a
跟在外面是一樣的。也可以認爲使用
let
等價於這樣:注:標準當中,
let
是不會提前的,但似乎並沒有被很好地支持。注意 let 为 ECMAScript 6新增的命令,在部分低版本浏览器不支持;
let 起到的作用就是申明了块范围变量;
这样console.log(c);就输出了 块范围变量 c
使用var方式定义的c 在for循环结束之后,已经变成了9;
而 a[0]-a[9] 方法中的 console.log(c); 这里的c 又指向了全局变量,所以就一直输出9了;
那么问题来了,这不是我想要的,我那个for循环有屁用啊!!
所以我们要让 console.log(c); 指向局部变量,这就要用到闭包了,
推荐看下变量对象的概念:变量对象(Variable Object)
因为闭包
var a = [];
for (var i = 0; i < 10; i++) {
var c = i;
a[i] = (function (u) {
return function(){
console.log(u);
}
}(c));
}
闭包的关系,赋值的时候自成作用域.
这样更好理解一点:
var a = [];
for (var i = 0; i < 10; i++) {
(function() {
var c = i;
a[i] = function() {
console.log(c);
};
})();
}