闭包
在了解闭包之前,来点【作用域】以及【作用域链】。如果你知道请跳过这弱鸡的一段。
作用域链:[[scope]]中所存储的【执行期上下文】对象的集合,这个集合呈链式链接,我们把这个链式链接叫做作用链接。
一段没什么用话
[[scope]](隐式属性):仅供JS引擎自己存取,[[scope]]指的就是作用域,其中存储了运行期上下文的集合。
执行期上下文:函数执行时对应的执行上下文都是独一无二的,当函数执行完毕,它所产生的执行上下文被销毁。
function a(){
function b(){
...
}
}
var glob=100;
a();
复制代码
作用链解析
a的函数被定义:a.[[scope]]-->0:GO{}
a被执行: a.[[scope]]-->0:a.AO{}
1:GO{}
b函数被定义:b.[[scope]]-->0:a.AO{}
1:GO{}
b被执行: b.[[scope]]-->0:b.AO {}
1:a.AO {}
2:GO{}
*查找变量:从作用域链的顶端依次向下查找。
复制代码
【闭包】是一个函数外加上该函数创建时建立的作用域。也就是说当一个内部函数被保存到外部,将生成闭包。闭包会导致原有作用域链不释放,造成内存泄露。
function a(){
var num = 100;
function b(){
num ++;
console.log(num);
}
return b;
}
var demo = a();
//将函数a 的返回值(函数b)赋值给一个变量。把函数b保存到了外部。
demo();//101
demo();//102
复制代码
闭包解析
a的函数被定义:a.[[scope]]-->0:GO{}
【第1个demo()执行】
a被执行: a.[[scope]]-->0:a.AO{num:100}
1:GO{}
b函数被定义:b.[[scope]]-->0:a.AO{num:100}
1:GO{}
b被执行: b.[[scope]]-->0:b.AO {num:101}
1:a.AO {num:101}
2:GO{}
demo()执行后 b.AO {}被销毁
a.AO{num : 101}不释放
【第2个demo()执行】
a被执行: a.[[scope]]-->0:a.AO{num:101}
1:GO{}
b函数被定义:b.[[scope]]-->0:a.AO{num:101}
1:GO{}
b被执行: b.[[scope]]-->0:b.AO {num:102}
1:a.AO {num:102}
2:GO{}
demo()执行后 b.AO {}被销毁
a.AO{num : 102}不释放
...(以此类推)
复制代码
闭包的作用
1.实现公有变量;
2.可以做缓存(存储结构);
3.可以实现封装、属性私有化;
4.模块化开发,防止污染全局变量。
复制代码
1) 实现公有变量 -- 例子:累加器
function accumulator(){
var count = 0;
function add(){
count ++;
console.log(count);
}
return add;
}
var counter = accumulator();
counter();//1
counter();//2
复制代码
2) 可以做缓存 -- 例子:签到
function signIn(){
var who = "";
var obj = {
check : function (){
if(who == ""){
console.log( "You've already signed it");
}else{
console.log( who + " finished the check-in");
who = "";
}
},
person : function (name){
who = name;
}
}
return obj;
}
var signed = signIn();
signed.person('kiwi');
signed.check(); //kiwi finished the check-in
signed.check(); //You've already signed it
复制代码
3) 可以实现封装、属性私有化
4) 模块化开发,防止污染全局变量
var name = "coco";
var init = (function () {
var name = "kiwi";
function callName() {
console.log(name);
}
return function () {
callName();
}
}());
init();//kiwi
复制代码
这是一篇凑不要脸的整理,可能有错且不全面!