js中用函数闭包进行封装---(function($, owner) {}(mui

可以利用js中函数的闭包进行封装

闭包是JavaScript的一个难点,也是JavaScript一个非常重要的特性,可以说如果你没有掌握闭包,你都不好意思说你懂Js函数。
首先,要理解闭包,你首先必须理解JS的变量作用域,这个我在JavaScript作用域和作用域链之前有谈到过。如果你还不熟悉,可以先去看看,我这里就不重复讲了。
JS变量的作用域分为全局作用域和局部作用域。一方面函数内部可以直接读取全局变量,另一方面,在函数外部自然无法读取函数内的局部变量。

通常我们可以用下面这种方法进行一个封装,这样在外部引入我们写的这个js文件后,就可以直接使用export.getUserId()这种形式去调用该函数

1.那么问题来了,我们该如何从外部读取局部变量?

在前面我们已经提到过,正常情况下,这是不可能实现的。但是我们知道,函数内部的函数是可以访问父函数的变量。那么好了,我们看看下面这个例子:

function patty(){
   var sum=666;
   function pattySon(){ 
     alert(sum);
   }
}

在上面的代码中,函数pattySon被包括在函数patty内部,这时patty内部的所有局部变量,对pattySon都是可见的。但是反过来就则不成立。这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然pattySon可以访问patty的内部变量,那我们只要返回pattySon,就可以从外部访问patty中的局部变量了。

function patty(){
   var sum=666;
   function pattySon(){ 
     alert(sum);
    }
   return pattySon;
}

var res=patty();
res();    //666
(function($, owner) {
    /*
     * 中间就可以进行封装操作
     * $就代表mui,owner就代表window的export属性,就是一个传值
     */
    var _userId = 1;
    function converter(userId){
        return  userId;
    }
    owner.getUserId = function(){
        return converter(_userId);
    }
}(mui, window.export = {}));
2.闭包是什么

简而言之,闭包就是一个访问父函数局部变量的函数。

上面写法等价于下面这一种,下面可能更易于理解,但都差不多,这样就进行了封装
然后在其他地方就可以通过window的全局对象来调用(直接用对象名即可),如:
export.getUserId() //得到的值就是1

3.闭包的用途

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。这句话要多读几遍,深刻理解。
怎么来理解这句话呢?请看下面的代码。

function patty(){
   var sum=666;
   add=function(){
   sum =2;
  }
   function pattySon(){ 
     alert(sum);
    }
   return pattySon;
}

var res=patty();
res();    //666
add();
res(); // 668

在这段代码中,res实际上就是闭包pattySon函数。它一共运行了两次,第一次的值是666,第二次的值是668。这证明了,父函数patty中的局部变量n一直保存在内存中,并没有被自动清除。
为什么会这样呢?原因就在于patty是pattySon的父函数,而pattySon被赋给了一个全局变量,这导致pattySon始终在内存中,而pattySon的存在依赖于patty,因此patty也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是"add=function(){sum =2}"这一行,首先在add前面没有使用var关键字,因此add是一个全局变量,而不是局部变量。其次,add的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以add相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。

事实上,通过使用闭包,我们可以做很多事情。比如模拟面向对象的代码风格;更优雅,更简洁的表达出代码;在某些方面提升代码的执行效率。

(1)结果缓存
我们开发中会碰到很多情况,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,
那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,从而函数内部的值可以得以保留。

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();      
           }    
       }    
    };    
})();    

CachedSearchBox.attachSearchBox("input");

(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());

//继承
    var Tom= function(){};
    //继承自Person
    Tom.prototype = new Person();
    //添加私有方法
    Tom.prototype.Say = function(){
        alert("Hello,my name is Tom");
    };
    var a = new Tom();
    Tom.setName("Tom");
   Tom.Say();
    alert(Tom.getName());

我们定义了Person,它就像一个类,我们new一个Person对象,访问它的方法。下面我们定义了Tom,继承Person,并添加自己的方法。
(3)封装

(function() {   
   var _userId = 23492;   
   var _typeId = 'item';    
   var export = {}; 

   function converter(userId) {          
     return  userId; 
   } 
    export.getUserId = function() {         
       return converter(_userId);     
   } 
   export.getTypeId = function() {          
      return _typeId; 
   }         
   window.export = export;   //通过此方式输出
}());
  export.getUserId(); // 23492 
  export.getTypeId();  // item 
  export._userId;    // undefined  
  export._typeId;    // undefined       
  export.converter; // undefined

利用闭包的特性能让我们封装一些复杂的函数逻辑,在这个例子中调用export上的方法(getUserId,getTypeId)间接访问函数里私有变量,但是直接调用export._userId是没法拿到_userId的。这也是Node里面常用到特性吧~

本文由美洲杯赌球发布于计算机教程,转载请注明出处:js中用函数闭包进行封装---(function($, owner) {}(mui

TAG标签: 美洲杯赌球
Ctrl+D 将本页面保存为书签,全面了解最新资讯,方便快捷。