日期:2014-05-16  浏览次数:20381 次

JavaScript链式调用小结

zYUI3 Node对象实现链式调用的方式如下:

?

Y.one('#id').setStyle('border','1px').setAttribute('title','test');

?

大家都知道,JavaScript链式调用只是语法的招数。依据JavaScript的灵活性,实现的方法也不止一种,一起来看。

注:前两种实现我直接拷贝了 zhouyrt的文章?JavaScript中链式调用之研习?中的代码,在此谢过。

第一种链式调用方法,代码如下。缺点是每个需要链式调用的方法都要返回当前对象。

?

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;  
    }  
}
var obj = new ClassA();  
//链式调用
obj.method1(1).method2(2).method(3); // obj -> prop1=1,prop2=2,prop3=3  

?

第二种方法可以在不改变原有方法的情况下模拟链式调用。无论原有方法是否返回当前对象,都可以使用。

但使用的风格略有不同。如下:

function chain(obj){  
    var fn = function(method){  
        if(arguments.length <= 0){  
            return fn;  
        }  
        var args = Array.prototype.slice.call(arguments, 1);  
        obj[method].apply(obj, args);  
        return fn;  
    }  
    return fn;  
} 
  
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;  
    }  
}
//链式调用模拟方式
var result = chain(obj)('method1',4)('method2',5)('method3',6)();   // result -> prop1=4,prop2=5,prop3=6  
?

接下来介绍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中的方法。

?

?

?

?