// 来自 《你不知道的JavaScript(上卷)》
// 5.4 循环和闭包
// p48-p51页的整理
/**
* 希望隔特定秒数打印 每个i
* 但是打印出来的是 5
* 为什么会是5呢?
* 因为 循环的终止条件是 i<5
* 而 延迟函数的回调 会在 循环结束时 才执行
* 所以 输出显示的 i=5 是循环结束时的最终值
* ======
* 但为什么偏偏是最终值呢?
* 因为是 var i;
* for(..)中的 var 其实是创建的全局变量
* 所以看似每个 i 都不同, 实际上整个作用域里只有一个 i
* 而 延迟函数 又是在 循环结束时 才执行
* 那延迟函数找到的值自然是整个作用域里最后剩下的 i=5
*/
for (var i = 0; i < 5; i++) {
setTimeout( function timer(){
console.log( i ); // 5,5,5,5,5
}, i*1000);
}
for (var i = 0; i < 5; i++) {
(function(){
setTimeout( function timer(){
console.log( i ); // 5,5,5,5,5
}, i*1000);
})();
}
/**
* 它需要有自己的变量, 迭代一次存储一次
*/
for (var i = 0; i < 5; i++) {
(function(){
var j = i; // 写在了 setTimeout 外面,所以 for(..)一次,赋值一次
setTimeout( function timer(){
console.log( j ); // 0,1,2,3,4
}, j*1000);
})();
}
// 可以用传参的方式达到同样的效果
for (var i = 0; i < 5; i++) {
(function( j ){
setTimeout( function timer(){
console.log( j ); // j:0,1,2,3,4
console.log( i ); // i:5,5,5,5,5
}, i*1000);
// 看到这里的时间间隔时, 我发现漏了个地方
// 时间间隔里的 i 很奇怪,它还是每隔一秒出
// 根据结果来推断, 它并不在 timer()里
// 也就是 时间间隔 里的变量是属于外部的
// 很简单.. 没毛病的
// 但我想岔了... 想了好一会儿...
})( i ); // 这个是外部的 i
}
for (var i = 0; i < 5; i++) {
let j = i; // 每次迭代都会声明,每个迭代都会使用上一个迭代结束时的值来初始化这个变量
setTimeout( function timer(){
console.log( j ); // 0,1,2,3,4
}, j*1000);
}
// 怕是最简单的写法了
for (let i = 0; i < 5; i++) {
setTimeout( function timer(){
console.log( i ); // 0,1,2,3,4
}, i*1000);
}
/**
* 如果奇怪为什么是每隔一秒才打印 i 的话,看这:
* for 是一瞬间执行完的
* setTimeout 也是
* 所以, setTimeout( ... , i*1000 ) 就是 1*1000 2*20000 ~
* 在一开始就执行过了
* 于是达到了每隔一秒出一个 i 的效果
*/