js中闭包的理解、用途场景、优缺点及解决办法

280 阅读3分钟
一、闭包的含义

官方对闭包的解释:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。

二、闭包的特点:
  1. 作为一个函数变量的一个引用,当函数返回时,其处于激活状态。
  2. 一个闭包就是当一个函数返回时,一个没有释放资源的栈区。
    简单的闭包如下:
    function f1(){
    var n = 100;
    return function f2(){
    alert(++n);
    }
    }

函数执行时创建了一个内部函数,这个内部函数作为返回值,或以某种方式保留下来(属性),之后才会调用,这就会形成了闭包。通俗来讲,JS所有的function都是一个闭包。


三、用途场景
  1. 匿名自执行函数
    我们创建了一个匿名的函数,并立即执行它,由于外部无法引用它内部的变量,因此在函数执行完后会立刻释放资源,关键是不污染全局对象。
    代码如下:
    (function() {
    var days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    today = new Date(),
    msg = 'Today is ' + days[today.getDay()] + ', ' + today.getDate();
    alert(msg);
    } ());

  2. 结果缓存

我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。
var CachedSearchBox = (function(){
var cache = {},
count = [];
return {
attachSearchBox : function(dsid){
if(dsid in cache){//如果结果在缓存中
return cache[dsid];//直接返回缓存中的对象
}
var fsb = new uikit.webctrl.SearchBox(dsid);//新建
cache[dsid] = fsb;//更新缓存
if(count.length > 100){//保正缓存的大小<=100
delete cache[count.shift()];
}
return fsb;
},

       clearSearchBox : function(dsid){    
            if(dsid in cache){    
            cache[dsid].clearSelection();      
            }    
       }    
    };    
})();
  1. 封装
    var person = function(){
    //变量作用域为函数内部,外部无法访问
    var name = "default";
    return {
    getName : function(){
    return name;
    },
    setName : function(newName){
    name = newName;
    }
    }
    }();

  2. 实现类和继承
    function Person(){
    var name = "default";
    return {
    getName : function(){
    return name;
    },
    setName : function(newName){
    name = newName;
    }
    }
    };

var p = new Person();
p.setName("Tom");
alert(p.getName());//Tom

var Jack = function(){};
//继承自Person
Jack.prototype = new Person();
//添加私有方法
Jack.prototype.Say = function(){
    alert("Hello,my name is Jack");
};
var j = new Jack();
j.setName("Jack");
j.Say();
alert(j.getName());//Jack
四、优缺点
  • 优点
    1.可以读取函数内部的变量
    2.可以让这些局部变量保存在内存中,实现变量数据共享。
  • 缺点
    1.由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
    2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

转自www.jianshu.com/p/8376170fb…