问题写法
for(var i = 1; i <= 5; i++) {
setTimeout( function(){
console.log(i);
},i*1000);
}
console.log(i);
// 先输出环境运行产生的一个6,每隔1s,再输出一个6,连续输出5个6
- 解析:
- 此处的i是由var定义在全局作用域内,输出值i属于全局作用域的值
- setTimeout()函数运行机制是,等全局环境运行完成后,再运行回调函数
- 因此,i的终值是都是全局变量i的值
- 因为回调函数并不是随着环境一起运行的,而是等到环境函数运行完成后再集中运行的
- 因此,五次循环相当于一起执行五次setTimeout()函数
- 所以累加的秒数就相当于,每隔一秒执行一次
let定义写法
for(let i = 1; i <= 5; i++) {
setTimeout( function(){
console.log(i);
},i*1000);
}
console.log(i);
// 先输出i未定义,再每隔1s输出累加值
- 解析:
- 此处的i是由let定义在块级作用域内,输出值i属于块级作用域的值
- 因此当i值出现变化时,是属于内部作用域的变化
- 而setTimeout()函数运行机制是,等环境运行完成后,再运行回调函数
- 因此,当i值出现变化时,已经没有环境程序在运行了
- 所以,此时for循环是跟着setTimeout()函数运行的
- 因此,i的输出值是for循环的累加值
立即函数写法
for(var i = 1; i <= 5; i++) {
(function(i){
setTimeout( function(){
console.log(i);
},i*1000);
})(i);
}
console.log(i);
// 先输出i未定义,再每隔1s输出累加值
- 解析:
- 此处的i是由var定义在全局作用域内,输出值i属于全局作用域的值
- 虽然,setTimeout()函数运行机制是,等全局环境运行完成后,再运行回调函数
- 但是,每次的for循环运行时,内部的立即函数都会执行
- 而且,i的值会由形参i传入到setTimeout()函数内部
- 从而形成关于i的私有作用域
- 因此此时的setTimeout()函数是和环境程序一起行动的
- 而最外围的i的输出没有时延,因此会先输出
闭包函数写法
for (var i = 1; i <= 5; i++) {
setTimeout(function(i) {
return function(){
console.log(i);
}
}(i), i*1000);
}
console.log(i);
// 先输出i未定义,再每隔1s输出累加值
- 解析:
- 此处的i是由var定义在全局作用域内,输出值i属于全局作用域的值
- setTimeout()函数运行机制是,等全局环境运行完成后,再运行回调函数
- 而此处的闭包写法,已然将for循环中i的变量值通过形参i保存于return机制中
- 形成私有作用域
- 待setTimeout()进行回调函数运行时,i将输出私域内的累加值
错误写法
for(var i = 1; i <= 5; i++) {
setTimeout(function(i){
console.log(i);
}(i),i*1000);
}
console.log(i);
- 解析:
- 此处的setTimeout()函数内的回调函数
- 在主程序运行时,已经随着主程序一起执行完毕
- 待setTimeout()异步运行时,已无回调函数可用