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: