[TOC]

当内部函数被保存到外部时 将会生成闭包
闭包会导致原有作用域链不释放 造成内存泄露(相当于手里拽着一把沙子 拽得越紧 手里的沙子越少 即泄露得多剩下的就少)

例:
image.png
XMX{TJLZ7MCKJ8}0(W}EQ}3.png
此时当a执行完毕后 a的作用域链就断开了
但是a执行结束前把b返回出来给了demo 所以此时b还链着a的AO
如下所示:
(D{JVU$T@U)Y6HU)7VPZ[Q3.png](https://cdn.nlark.com/yuque/0/2021/png/12773302/1618969421001-cee9b6d2-e047-47a0-8a0f-89e02303721a.png#align=left&display=inline&height=345&margin=%5Bobject%20Object%5D&name=%28D%7BJVU%24T%40U%29Y6HU%297VPZ%5BQ3.png&originHeight=530&originWidth=742&size=288382&status=done&style=none&width=483)<br />所以当b执行时  b的作用域如下:<br />![Q60PEPO3%56{](W~93N_VBI.png
所以此时执行demo就相当于b执行了
所以输出 123;

闭包的作用

1 实现公有变量
如 函数累加器
function add() {
var num = 0;
function a() {
console.log(++num);
}
return a;
}
var myAdd = add();
myAdd();
myAdd();
//这里myAdd每执行一次 num就++
2 可以做缓存(存储结构)
如:

3 可以实现封装,属性私有化

//divorce函数与Person函数形成了闭包 divorce函数与Person共用一个AO
//所以divorce函数可以找得到prepareWife这个变量
//但是如果是person对象就找不到prepareWife这个变量
//因为 return this; 中 this = { wife : wife , divorce : function(){…} } 此时person对象即为this 在this中prepareWife是不存在的
//所以person.prepareWife会给你返回undefined 相当于属性私有化了
4 管理变量 防止污染全局 适用于模块化开发

var init1 = (function (){
var name = ‘haha’;
function callName(){
console.log(name);
}
return function (){
callName();
}
}( ) )
var init2 = (function (){
var name = ‘hehe’;
function callName(){
console.log(name);
}
return function (){
callName();
}
}( ) )
//利用闭包 init1();与init2(); 即使函数里面的命名完全一样 也互不影响 各自实现各自的功能
//所以将全局要实现的功能放到局部里面 就是为了让它们互不污染