闭包,原来因为垃圾回收机制的,没有被使用的变量会被回收,而闭包因为占用了某个变量,使原来本应该被回收的变量没有被回收。
下面看一个没有使用闭包的for循环例子,大家应该日常中经常用到:
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}
这段代码输出的是 五个5,因为var 没有块级作用域,使用了setimeout后,宏任务执行console的时候,i在主线程结束时已经变成了5,所以最后输出五个5。
而要解决这个问题可以使用最简单的方法,就是把var改为let,因为let有自己的块级作用域,故执行setimeout的时候,会有五个独立的i,就会正常输出0,1,2,3,4。
这里讲一下使用闭包的方法实现:
for (var i = 0; i < 5; i++) {
(function (i) {
setTimeout(() => {
console.log(i)
}, 0)
}
)(i)
}
相信很多人用过这段代码,但是可能不太理解,这里说一下:
因为刚才说了,这是闭包的方式,使用了自执行函数,原本在setimeout里的 i 会因为被执行函数当作参数引用着, 所以不会被回收,会一直保留在setimeout里,每个setimeout里都会有各自的i,所以会正常输出0,1,2,3,4