Nea*_*eal 50 javascript closures scope
2每次都会发出以下警报.
function timer() {
for (var i = 0; i < 3; ++i) {
var j = i;
setTimeout(function () {
alert(j);
}, 1000);
}
}
timer();
Run Code Online (Sandbox Code Playgroud)
不应该var j = i;设置j进入setTimeout的个别范围?
如果我这样做:
function timer() {
for (var i = 0; i < 3; ++i) {
(function (j) {
setTimeout(function () {
alert(j);
}, 1000);
})(i);
}
}
timer();
Run Code Online (Sandbox Code Playgroud)
它提醒0,1,2像它应该.
有什么我想念的吗?
Ing*_*ürk 30
Javascript具有功能范围.这意味着
for(...) {
var j = i;
}
Run Code Online (Sandbox Code Playgroud)
相当于
var j;
for(...) {
j = i;
}
Run Code Online (Sandbox Code Playgroud)
实际上,这就是Javascript编译器实际处理此代码的方式.而且,当然,这会导致你的小"技巧"失败,因为j在setTimeout调用函数之前会增加,即j现在并没有真正做任何不同的事情i,它只是具有相同范围的别名.
如果Javascript具有块范围,那么你的技巧就可以了,因为j在每次迭代中它都是一个新的变量.
您需要做的是创建一个新范围:
for(var i = ...) {
(function (j) {
// you can safely use j here now
setTimeout(...);
})(i);
}
Run Code Online (Sandbox Code Playgroud)
IIFE的替代方法是功能工厂:
function timer() {
for (var i = 0; i < 3; ++i) {
setTimeout(createTimerCallback(i), 1000);
}
}
function createTimerCallback(i) {
return function() {
alert(i);
};
}
timer();
Run Code Online (Sandbox Code Playgroud)
话虽如此,这是javascript标记中最常问到的问题之一。看到:
| 归档时间: |
|
| 查看次数: |
1079 次 |
| 最近记录: |