zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    狭隘试试
    安装django
    青岛大学开源OJ以及部署
    十三、用户名密码管理
    十二、文件权限及所属主组的修改
    十一、tar打包命令的使用
    十、文件管理、属性、查找和软硬链接
    九、系统优化方法(基础优化)
    八、系统登陆信息的显示和硬件信息等
    七、常用基础配置
  • 原文地址:https://www.cnblogs.com/youxin/p/3410185.html
Copyright © 2011-2022 走看看