javascript鏈式調用實現方式總結


方法鏈一般適合對一個對象進行連續操作(集中在一句代碼)。一定程度上可以減少代碼量,缺點是它占用了函數的返回值。

 

一、方法體內返回對象實例自身(this)

function ClassA(){
    this.prop1 = null;
    this.prop2 = null;
    this.prop3 = null;
}
ClassA.prototype = {
    method1 : function(p1){
        this.prop1 = p1;
        return this;
    },
    method2 : function(p2){
        this.prop2 = p2;
        return this;
    },
    method3 : function(p3){
        this.prop3 = p3;
        return this;
    }
}

定義了function/類ClassA。有三個屬性/字段prop1,prop2,prop3,三個方法methed1,method2,method3分別設置prop1,prop2,prop3。

鏈式調用如下:

 
  1. var obj = new ClassA();  
  2. obj.method1(1).method2(2).method3(3); // obj -> prop1=1,prop2=2,prop3=3  

 

可以看到對obj進行了連續三次操作,只要願意ClassA的N多方法都這樣定義,調用鏈會一直延續。


方式缺點是鏈方法唯一地綁定於一種對象類型(ClaaaA),按這種方式實現鏈式操作,每定義一個類,其方法體中都要返回this。第二種方式可以解決這個問題。

 

二、對象傳入后每次調用返回函數自身

 

/**
 * chain 最易讀版
 * @param {Object} obj
 */

function singleChain1(obj){
    function chain(){
        if (arguments.length == 0){
            return chain.obj;
        }
        var methodName = arguments[0], methodArgs = [].slice.call(arguments,1);
        chain.obj[methodName].apply(chain.obj,methodArgs);
        return chain;
    }
    chain.obj = obj;
    return chain;
}
/**
 * chain 易讀版
 * @param {Object} obj
 */
function singleChain2(obj){
    return function(){
        var Self = arguments.callee; Self.obj = obj;
        if(arguments.length==0){
            return Self.obj;
        }     
        var methodName = arguments[0], methodArgs = [].slice.call(arguments,1);
        Self.obj[methodName].apply(Self.obj,methodArgs);
        return Self;
    }
}
/**
 * chain 精簡版
 * @param {Object} obj
 */
function singleChain3(obj){
    return function(){
        var Self = arguments.callee; Self.obj = obj;
        if(arguments.length==0){
            return Self.obj;
        } 
        Self.obj[arguments[0]].apply(Self.obj,[].slice.call(arguments,1));
        return Self;
    }
}

使用:

/**
 * chain 精簡版
 * @param {Object} obj
 */
function chain(obj){
    return function(){
        var Self = arguments.callee; Self.obj = obj;
        if(arguments.length==0){
            return Self.obj;
        } 
        Self.obj[arguments[0]].apply(Self.obj,[].slice.call(arguments,1));
        return Self;
    }
}

//定義的function/類ClassB
function ClassB(){
    this.prop1 = null;
    this.prop2 = null;
    this.prop3 = null;
}
ClassB.prototype = {
    method1 : function(p1){
        this.prop1 = p1;
    },
    method2 : function(p2){
        this.prop2 = p2;
    },
    method3 : function(p3){
        this.prop3 = p3;
    }
}

注意ClassB的method1,method2,method3中不再返回this了。

 

鏈式調用如下:

Js代碼   收藏代碼
  1. var obj = new ClassB();  
  2. chain(obj)('method1',4)('method2',5)('method3',6); // obj -> prop1=4,prop2=5,prop3=6  

 

第一種方式3次調用后返回了對象自身,這里使用一個空"()"取回對象

Js代碼   收藏代碼
  1. // result -> prop1=4,prop2=5,prop3=6  
  2. var result = chain(obj)('method1',4)('method2',5)('method3',6)();  

 

這種方式寫類時方法體中無須返回this,且可以對任何對象進行鏈式調用。

 

接下來介紹YUI中Node類實現的鏈式調用方法。

在YUI3中,Node類的基礎是Dom,很多Node類的方法都是調用Dom類的同名方法,如上面提到的setAttribute、setStyle等,

在Dom類源碼中也未設置返回本對象,在Node類提供了importMethods方法來導入Dom中相同的方法並支持鏈式調用。示例代碼如下:

 

//Dom類及靜態方法
function Dom(id){
    this.dom = document.getElementById(id);
} 

Dom.setStyle = function(node,name,value){
    node.dom.style[name] = value;
}

Dom.setAttribute = function(node,name,v){
    node.dom.setAttribute(name,v);
}


//Node類
function Node(id){
    this.dom = document.getElementById(id);
}

//添加方法的函數
Node.addMethod = function(method,fn){//,context

    Node.prototype[method] = function(){
        var me = this;
        //Array.prototype.unshift.call(arguments,me);
        //or                                               
        arguments = Array.prototype.slice.call(arguments);
        arguments.unshift(me);
        fn.apply(me,arguments);
        return me;
    }     

}


//批量添加方法的函數
Node.importMethods = function(host,methods){
    for(var i in methods){
                var m = methods[i];
        var fn = host[m];
        Node.addMethod(m,fn);
    }
}


//定義需要給Node類添加的方法名 列表
var methods = ['setStyle','setAttribute'];

//使用批量添加方法的函數將Dom中的相關方法添加到Node中 
Node.importMethods(Dom,methods); 

//可以在Node中進行鏈式調用
var n = new Node('log').setStyle('border','2px solid red').setAttribute('t',22);

   

在實際使用中,可以對原有的對象方法(如Dom中的方法)擴展到另一個類中(如Node類),在Node類中進行鏈式調用。當然也可以使用同樣的方式(importMethods)不擴展而是覆蓋Dom中的方法。

轉自:http://houfeng0923.iteye.com/blog/1139525


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM