闭包概念
闭包:当内部函数被保存到外部时,将会生成闭包。
闭包会导致原有的作用域链不释放,造成内存泄漏(作用域链一直不释放,占用内存,可用内存就小了,指内存泄漏)。
例子说明
利用上一节的作用域链可以非常好理解闭包,下面来看一个例子:
function a() {
function b() {
var bbb = 234;
console.log(aaa); //打印123
}
var aaa = 123;
return b;
}
var glob = 100;
var demo = a();
demo();
- 首先生成GO:
GO: {
glob:undefined,
a: function a() {……函数里面的代码……},
demo: undefined
}
接着给glob赋值100,之后,给demo赋值,执行a函数前,对a进行预b编译,得到a-AO:
a-AO: {
aaa:undefined,
b: function b() {……函数里面的代码……}
}
接着执行a函数,此时,a函数的作用域链为:
a.[[scope]]---->scopechain[0]---->a-AO;
---->scopechain[1]---->GO;
给a赋值123后,返回b函数体,此时b函数的作用域链为:
b.[[scope]]---->scopechain[0]---->a-AO;
---->scopechain[1]---->GO;
b函数体返回后,a函数执行完毕,a函数作用域链被销毁,但注意,只是解除了对a-AO及GO的引用,并没有销毁a-AO。但由于在a函数结束前返回了b函数,b函数包含了对a-AO及GO的引用,也即b“继承”了a的作用域链,即使a函数执行完毕,但其作用域链仍不会释放。
扫描二维码关注公众号,回复:
9856377 查看本文章
- 最后,回到全局环境,执行demo(),即执行b函数,在执行b函数前,对b进行预编译,得到b-AO:
b-AO: {
bbb:undefined
}
然后执行b函数,此时b函数作用域链为:
b.[[scope]]---->scopechain[0]---->b-AO;
---->scopechain[1]---->a-AO;
---->scopechain[2]---->GO;
得 :
b-AO: {
bbb:234
}
因此 ,打印aaa回到a-AO中寻找aaa的值,打印为123。