一,定义
闭包可以简单理解成:定义在一个函数内部的函数,其中一个内部函数在包含它们的外部函数之外被调用时,并且内部函数能够访问到外部函数的变量,就会形成闭包
例如:
function foo(){
var a = 1
return function (){
console.log(a)
}
}
foo()()
内部函数能够被foo函数调用,且内部函数能够使用外部函数的变量
特点:
1:函数嵌套函数。
2:函数内部可以引用外部的参数和变量。
3:参数和变量不会被垃圾回收机制回收。
使用:
1:读取函数内部的变量
2:变量的值始终保持在内存中,不会在外层函数调用后被自动清除
优点:
1:变量长期驻留在内存中
2:避免全局变量的污染
缺点:
会造成内存泄漏
二,分析
function foo(){
var count = 0;
return function(){
count++
console.log(count)
}
}
var bar = foo();
bar();
bar();
bar();
var res = foo();
res();
res(); // 输出2还是5? 为什么?
res();
分析代码回答问题
1.看外部函数执行了几次,执行几次就形成了几个空间,也就是这段代码里声明的bar和res两个变量,这两个变量就是执行了外层函数,就会形成两个不同的空间
2.内部函数执行时,先去找执行的是哪个空间里的函数,比如我们的问题,第二个res(),是在声明的第二个变量里的函数,那就去第二个函数里找变量count,我们发现,内部函数在这个空间里被执行了两次,所以,输出的count就是2
三,内存泄漏
如上边的代码,我们声明的bar和res变量返回了内部的匿名函数,而内部函数引用了该闭包函数上下文活动对象count,如果内部函数不能被销毁,则该闭包函数的活动对象就不会被销毁,因此就会造成内存泄漏
四,垃圾回收机制
标记清除法:
setTimeout(() => {
// 垃圾回收机制会检测到bar---> 不引用内部函数了,也就说,这个内部函数形成的空间中的变量 一定不会被使用了.所以变量就会销毁,从而释放空间
bar = null;
}, 10000)