84669 orang belajar
152542 orang belajar
20005 orang belajar
5487 orang belajar
7821 orang belajar
359900 orang belajar
3350 orang belajar
180660 orang belajar
48569 orang belajar
18603 orang belajar
40936 orang belajar
1549 orang belajar
1183 orang belajar
32909 orang belajar
function test() { for(var i=0; i<10; i++) { setTimeout(function(){ (function (m) { console.log(m); })(i) }, 500) } } test();
认证高级PHP讲师
直接在setTimeout()里用即时执行封装下回调就行了,你封包在setTimeout()的里边跟没封区别不大:
setTimeout()
function test() { for(var i=1; i<11; i++) { setTimeout((function(){ console.log(i); })(), 500) } } test();
补充:
如果想做成间隔500ms一次console.log,那我觉得不如直接写成:
var i = 1; var ii = setInterval(function(){ if (i<11) { console.log(i); i++; } else { clearInterval(ii); } }, 500);
题主之所以会出现此问题,完全是由于没有理解闭包
es5之前js是没有块级作用域这个说法的
可以通过()()来模拟块级作用域
for(var i = 0; i < 10; i++) { setTimeout((function(){ console.log(i) })(),500) } // 0 1 2 3 4 5 6 7 8 9
es6通过let命令,声明变量只在书写的let命令代码块内有效所以 @radius 写的就复杂了
for(let i=0; i<10; i++) { setTimeout(function(){ console.log(i); }, 500) } // 0 1 2 3 4 5 6 7 8 9
阮一峰es6块级作用域
function test() { for(var i=0; i<10; i++) { (function(i){ setTimeout(function(){ console.log(i); },500); })(i) } } test(); 这个是循环0-9 1-10你自己改
function test() { for(var i = 1 ;i<=10;i++){
(function(i){ setTimeout(function(){ console.log(i) },500) })(i);
}}test();
function test(){
for(var i = 0 ;i<10 ;i++){ setTimeout((function(m){ return function(){ console.log(m)} })(i),500); }
}
test();
function test() { for(var i=1; i<=10; i++) { setTimeout((function(m){ return function () { console.log(m); } })(i), 500 * i) } } test();
function count() { var arr = []; for (var i=1; i<=3; i++) { arr.push(function () { return i * i; }); } return arr; } var results = count(); var f1 = results[0]; var f2 = results[1]; var f3 = results[2];
在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都添加到一个Array中返回了。
你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是:
f1(); // 16 f2(); // 16 f3(); // 16
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。廖雪峰教程:闭包
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
function test() { for(let i=0; i<10; i++) { setTimeout(function(){ (function (m) { console.log(m); })(i) }, 500) } } test();
只把var改成let就行了
setTimeout上修改:
setTimeout(function(m) { console.log(m); })(i), 500);
es2016 or typescript:
async function test() { var i = 0; for (i = 0; i < 10; i++) { await new Promise(resolve => setTimeout(resolve, 500)); console.log(i); } } test();
直接在
setTimeout()
里用即时执行封装下回调就行了,你封包在setTimeout()
的里边跟没封区别不大:补充:
如果想做成间隔500ms一次console.log,那我觉得不如直接写成:
题主之所以会出现此问题,完全是由于没有理解闭包
es5之前js是没有块级作用域这个说法的
可以通过()()来模拟块级作用域
es6通过let命令,声明变量只在书写的let命令代码块内有效
所以 @radius 写的就复杂了
阮一峰es6块级作用域
function test() {
for(var i = 1 ;i<=10;i++){
}
}
test();
function test(){
}
test();
在上面的例子中,每次循环,都创建了一个新的函数,然后,把创建的3个函数都添加到一个Array中返回了。
你可能认为调用f1(),f2()和f3()结果应该是1,4,9,但实际结果是:
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
廖雪峰教程:闭包
只把var改成let就行了
setTimeout上修改:
es2016 or typescript: