闭包的概念
函数对象可以通过作用域i链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性在计算机科学文献中称为"闭包"。
我的理解是,只要是内部的函数被保存到了外部,就一定会生成闭包。或者说只要是能访问其他函数内部的变量的函数就是闭包。
举个例子:
function a(){
function b(){
console.log(aaa)
}
var aa = 123;
return b;
}
var demo = a();
demo();
闭包的好处
-
可以读取函数内部的变量
-
可以让变量是始终保存在内存中,比如:单例
var Singleton = function(name) { this.name = name; }; Singleton.prototype.getName = function() { alert(this.name); }; Singleton.getInstance = (function() { var instance = null; return function(name) { if (!instance) { instance = new Singleton(name); } return instance; } }()); Singleton.getInstance("12312").getName()
闭包的危害
- 使用不当则会产生内存泄漏
理解
我们知道为什么了闭包的好处与危害,那么为什么闭包可以让变量始终保存在内存中,为什么会产生内存泄漏呢?
1. 为什么闭包可以让变量始终保存在内存?
function a(){
function b(){
var c = 0
console.log(aaa)
}
var aa = 123;
return b;
}
var demo = a();
demo();
a函数被执行时会产生自己AO,当b函数被执行时也会产生自己的AO同时拥有a函数的AO。正常情况下a函数执行完以后,会释放自己的AO,b函数执行完以后也会释放自己的AO。但是现在b函数被a函数返回出来了,同时赋值给了demo,那么现在在demo就拥有了b的AO,如果demo一直不被销毁,那么b的作用域链就会一直存在内存中。
a.[[scope]] = [
// AO
{
this:window,
aa:123,
b:(function)
},
// GO
{
this:window
window:(Object),
document:(Object)
a:(function),
demo: (function),
}
]
b.[[scope]] = [
// AO
{
this:window,
c:0
},
// AO
{
this:window,
aa:123,
b:(function)
},
// GO
{
this:window
window:(Object),
document:(Object)
a:(function),
demo: (function),
}
]
-
为什么会产生内存泄漏?
如果闭包一直占用内存不被释放,会导致系统占用的内存越多,可以使用的内存越少,这也是一种内存泄漏。
网友评论