首页 > 代码库 > 闭包及其作用

闭包及其作用

闭包:有权访问其他函数内部变量的函数,在一个函数内部创建一个函数,就形成了闭包,闭包的参数和变量不会被垃圾回收机制回收。闭包可以避免全局变量的污染。

使用场景:

1.闭包的经典应用:绑定事件

假如页面上有5个div,我们通过for循环来给每个div绑定一个事件,每点击一次输出它的索引值。如果没有使用闭包,在循环内部给每个节点添加事件,发现点击后每次输出的值都是一样的。因为onclick事件时异步触发的,当事件触发的时候for循环早就结束了。此时变量i的值是5,。解决办法就是在闭包的帮助下,把每次循环的i值包裹起来:使用立即执行函数将i值作为参数传递进去后再绑定事件

var list=document.getElementById("list");
for (var i = 0; i < list.length; i++) {
    (function(i){
        list[i].onclick=function(){
            console.log(i);
        }
    })(i);
}

2,封装变量:闭包可以帮助把一些不需要暴露在全局的变量封装成私有变量。

在大型项目当中,为了防止命名冲突,一般会把相应的代码用闭包的形式包裹起来,避免暴露在全局作用域下

假如有一个函数接受number类型的参数并返回这些参数的乘积,你应该怎么做。

第一步你应该会写出下面的代码:

var mult=function(){
    var a=1;
    for (var i = 0; i < arguments.length; i++) {
        a=a*arguments[i];
    }
    return a;
};

优化代码:假如缓存机制,如果参数相同直接返回这个缓存后的值

var cache = {};
var mult = function() {
    var args = Array.prototype.join(arguments, ‘,‘);
    if (cache[args]) {
        return cache[args];
    } else {
        var a = 1;
        for (var i = 0; i < arguments.length; i++) {
            a = a * arguments[i];
        }
        return cache[args] = a;
    }

}

继续优化:注意到cache这个变量只在这个函数内部被使用,与其让其和mult函数一起暴露在全局作用域下,还不如把它封装在函数内部,

var mult = (function() {
    var cache = {}; //把原先的cache封装在函数的内部,这样可以减少页面内的全局变量
    return function() {
        var args = Array.prototype.join(arguments, ‘,‘);
        if (cache[args]) {
            return cache.args
        } else {
            var a = 1;
            for (var i = 0; i < arguments.length; i++) {
                a = a * arguments[i];
            }
            return cache[args] = a;
        }

    }
})(); //立即执行函数后return一个function

提炼函数是代码重构中的一种常见技巧。如果在一个大函数中有一些代码块能够独立出来,那么我们将它封装在一个小函数当中,这样有助于代码复用,如果同时小函数有个好名字,那么也起到注释的作用。如果小函数不在程序的其他地方使用,那么将它放在闭包当中。

var mult = (function() {
    var cache = {}; //把原先的cache封装在函数的内部,这样可以减少页面内的全局变量
    var caculate = function() {
        var a = 1;
        for (var i = 0; i < arguments.length; i++) {
            a = a * arguments[i];
        }
        return a;
    }
    return function() {
        var args = Array.prototype.join(arguments, ‘,‘);
        if (cache[args]) {
            return cache[args];
        } 
        cache[args]=caculate.apply(null,arguments);//null指默认的宿主对象

    }
})();

3.延续局部变量的寿命

用img对象来进行数据上报时,把img变量用闭包封闭起来,因为在低版本的浏览器用report函数上报数据时存在bug,会丢失数据。

因为img是局部变量,函数执行完毕后局部变量随即被销毁,以至于来不及发出http请求,导致数据丢失。

var report=(function(){
    var imgs=[];
    return function(src){
        var img=new Image();
        imgs.push(img);
        img.src=src;
    }
})();
report("url");//数据上报

 

闭包及其作用