84669 personnes étudient
152542 personnes étudient
20005 personnes étudient
5487 personnes étudient
7821 personnes étudient
359900 personnes étudient
3350 personnes étudient
180660 personnes étudient
48569 personnes étudient
18603 personnes étudient
40936 personnes étudient
1549 personnes étudient
1183 personnes étudient
32909 personnes étudient
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: