JS:闭包

185 阅读2分钟

闭包

在了解闭包之前,来点【作用域】以及【作用域链】。如果你知道请跳过这弱鸡的一段。
作用域链:[[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

这是一篇凑不要脸的整理,可能有错且不全面!