当函数可以记住并访问所在的词法作用域时,就产生了闭包,即使函数是在当前词法作用
域之外执行。
我来对这个定义进行解释下
函数要在执行后不被垃圾回收机制回收,并且可以访问当前作用域中的属性和方法. 函数在当前作用域外也可以被调用!
let message = "Cicaba"
function foo(){
console.log(message) //是一个 RHS 引用查询
}
foo()//Cicaba
上面代码并不是真正意义上的闭包.
函数内部作用域只是引用了函数外部作用域的变量.(只是作用域链的一种体现)
function foo() {
var a = 2;
function baz() {
console.log( a ); // 2
}
bar( baz );
}
function bar(fn) {
fn(); // 妈妈快看呀,这就是闭包!
}
闭包和作用域链有着密切的关系.闭包就是突破作用域链的一种方式!
看一个金典的例子:
for(var i = 0; i<6; i++){
setTimeout(function timer(){
console.log(i)
},1000)
}
上面代码每隔一秒会输出6个5,为什么乐?
要理解这个问题必须你先理解词法作用域(作用域)
我们来看上面代码发生了什么.
for循环中定义了一个全局变量i, 每次循环都在改变i的值.
而setTimeout是在循环结束后才被执行(延迟回调函数(异步执行)).
每次循环都在当前作用域声明一个定时器函数, 都共享一个作用域里的资源, 所以打印了6个5.
解决办法
for(var i = 0; i<6; i++){
let j = i;
setTimeout(function timer(){
console.log(j)
},1000)
}
解决思路在每次循环中创建一个词法作用域,
for(let i = 0; i<6; i++){
setTimeout(function timer(){
console.log(i)
},1000)
}
//for循环的let声明, 会有一个特殊的行为, 会在每次循环迭代时重新声明, 并且会把上次迭代的值初始化当前变量!
评论 (0)