初识闭包:在for循环中的应用
起因是想写两个嵌套的for循环,然后在里层的循环中读取到外层循环的变量值。以为会读取到0 1 2 3 4这样,但结果都是外层循环中最后一次循环到的值。
为了解决这个问题,需要用到匿名函数、立即执行函数与闭包。
- 匿名函数:没有命名的函数,因为直接执行了,所以不需要函数名来调用;
- 立即执行函数:能够立即运行的函数,也叫IIFE;
- 闭包:函数里有函数的函数。
立即执行函数的写法一般为:(fun...)()或者(fun...()),刚好这种函数嵌套函数的写法,也称之为闭包。
初始代码:
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i); // (5)5
}, 1000)
}
使用立即执行函数后:
for (var i = 0; i < 5; i++) {
(function(i) {
setTimeout(function() {
console.log(i); // 0 1 2 3 4
},1000)
})(i);
}
换一种写法:
for (var i = 0; i < 5; i++) {
setTimeout(
(function(i) {
return function (){
return console.log(i) // 0 1 2 3 4
}
})(i)
,1000)
}
无论是写在setTimeout中还是将之包裹起来,初衷都是为了让JS在执行for循环的时候,立即运行带有i参数的函数,从而保存了当时i的值。
在这个问题中主要运用的是立即执行函数,关于立即执行函数的更多写法可以参考这篇文章:浅谈匿名函数和闭包
JavaScript在ES6之后新增了let声明,这样就有了另外一种途径来解决这个广泛的问题:
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i); // 0 1 2 3 4
}, 1000)
}
因为let声明的变量有了自己的块级作用域,并不会因上次的赋值而改变,但是缺点也有:不支持IE11以下的浏览器。
上一篇:居中容器的思考