当函数可以记住并访问所在的词法作用域,就产生了闭包
循环中闭包问题的解决
for (var i = 0; i <= 5; i++) {
setTimeout( function timer () {
console.log(i)
}, i * 1000)
}
这里就涉及到事件的轮询机制。异步事件和同步事件,异步事件会在最后执行。
要解决上面的问题有两种方法,分别是使用立即执行函数和块级作用域来解决,都为函数创建了一个块级作用域。这样内部的timer
函数就能引用到块级作用域中的变量,而不会被销毁
立即执行函数
for (var i = 0; i <= 5; i++) {
setTimeout( (function timer () {
console.log(i)
})(i), i * 1000)
}
这里立即函数会立即执行,但是由于内部的timer
引用了i
所以立即执行函数的作用域不会被销毁
块级作用域
for (var i = 0; i <= 5; i++) {
let j = i
setTimeout( function timer () {
console.log(j)
}, i * 1000)
}
利用let
对作用域的劫持,但是上面的let
每次都会声明,并且使用上次结束的值初始化下一次的声明,可以像下面这样来
for (let i = 0; i <= 5; i++) {
setTimeout( function timer () {
console.log(i)
}, i * 1000)
}
模块
其实模块也是使用的闭包来实现的