`

JavaScript函数重载模拟

阅读更多
转自:http://www.cnblogs.com/simayixin/archive/2011/03/28/1997519.html


我们从结果向实现推,首先看我们要实现什么样的效果:

css(hi,"color","red")
css([hi,hello],"color","red")
css(hi,{"border":"1px solid #000","width":"200px"})
var color = css(hi,"color")

这是很常见的写法,然后看我们希望怎么写:

Overload("css",window,
         {
             "object,string,string" : function(el,key,val){
                 el.style[key] = val;
             }
             ,"array,string,string" : function(els,key,val){
                 for(var i=0;i<els.length;i++){
                    els[i].style[key] = val;
                 }
             }
             ,"object,object" : function(el,kv){
                for(var i in kv){
                    el.style[i] = kv[i];   
                }
             }
             ,"object,string" : function(el,key){
                 return el.style[key];
             }
});
接下来,看实现:

/*
    JavaScript函数重载模拟
    name : 函数名
    bind : 函数需要绑定到的对象
    fn_objs : 键值对函数对象,键位以逗号隔开的类型(number,string,object,undefined,boolean,array,*)字符串,其中*为万能类型,值为对应的函数,
    如:{"string,string":function(x,y){},"string,number":functioin(x,y){}}
*/
var Overload = function(name,bind,fn_objs){
    var dict_name = "_"+name+"_dict",dict;
    dict = bind[dict_name] = bind[dict_name] || {};
    
    for(var i in fn_objs){
        dict[i] = fn_objs[i];  
    }
    
    var is_match = function(x,y){
        if(x==y)return true;
        if(x.indexOf("*")==-1)return false;
    
        var x_arr = x.split(","),y_arr = y.split(",");
        if(x_arr.length != y_arr.length)return false;
    
        while(x_arr.length){
            var x_first =  x_arr.shift(),y_first = y_arr.shift();
            if(x_first!="*" && x_first!=y_first)return false;
        }
        return true;
    };
    
    bind[name] = function(){
        var args = arguments,args_len = args.length,args_types=[],args_type,match_fn = function(){};
        for(var i=0;i<args_len;i++){
            var type = typeof args[i];
            type=="object" &&  (args[i] instanceof Array) && (type="array");
            args_types.push(type);
        }
        args_type = args_types.join(",");
        for(var k in dict){
            if(is_match(k,args_type)){
                match_fn = dict[k];
                break;
            }
        }
        return match_fn.apply(this,args);
    };
};
因为采用typeof来动态监测参数类型,而typeof又只能检测到的值只有(number,string,object,undefined,boolean),所以类型的制定只能从这些值中设定,实现中还加入了万能类型"*",由于array属于常用类型, 所以又特别添加了对array类型的支持。

基本原理是:将以类型串为键,函数为值的字典挂到需要绑定的对象上,命名为"_"+fn_name+"_dict",可用bind["_"+fn_name_"_dict"]来访问此对象,接着生成一个函数,在函数里靠判断arguments生成的类型串来从上述字典中匹配到相应的函数。

------------------------------------------------------------------------------------------------------------------

上面的写法 ,始终不好看,有如下改进:

Overload = function(fn_objs){
    var is_match = function(x,y){
        if(x==y)return true;
        if(x.indexOf("*")==-1)return false;
    
        var x_arr = x.split(","),y_arr = y.split(",");
        if(x_arr.length != y_arr.length)return false;
    
        while(x_arr.length){
            var x_first =  x_arr.shift(),y_first = y_arr.shift();
            if(x_first!="*" && x_first!=y_first)return false;
        }
        return true;
    };
    var ret = function(){
        var args = arguments
        ,args_len = args.length
        ,args_types=[]
        ,args_type
        ,fn_objs = args.callee._fn_objs
        ,match_fn = function(){};
        
        for(var i=0;i<args_len;i++){
            var type = typeof args[i];
            type=="object" && (args[i].length>-1) && (type="array");
            args_types.push(type);
        }
        args_type = args_types.join(",");
        for(var k in fn_objs){
            if(is_match(k,args_type)){
                match_fn = fn_objs[k];
                break;
            }
        }
        return match_fn.apply(this,args);
    };
    ret._fn_objs = fn_objs;
    return ret;
};

String.prototype.format = Overload({
    "array" : function(params){
        var reg = /{(\d+)}/gm;
        return this.replace(reg,function(match,name){
            return params[~~name];
        });
    }
    ,"object" : function(param){
        var reg = /{([^{}]+)}/gm;
        return this.replace(reg,function(match,name){
            return param[name];
        });
    }
});
分享到:
评论

相关推荐

    javascript函数重载解决方案分享

    本文主要介绍了javascript函数重载解决方案,利用JavaScript中的特殊对象arguments来模拟函数重载。用它来判断传入参数的个数或类型以区分重载

    让JavaScript 轻松支持函数重载 (Part 1 – 设计)

    说支持,是因为JavaScript函数对参数列表不作任何限制,可以在函数内部模拟对函数重载的支持。 实际上,在很多著名的开源库当中,我们都可以看到函数内部模拟重载支持的设计。例如说jQuery的jQuery.extend方法,就是...

    JavaScript重载函数实例剖析

    我们来简单用两种方式来”模拟”下重载函数。 2.根据参数的个数来判断 javascript的函数中有一个叫arguments的变量,是记录参数的一个数组,我们可以用这个来判断参数的个数,然后分别执行不同的内容,就是同一个...

    详解JS函数重载

    本文主要介绍了利用JavaScript中的特殊对象arguments来模拟函数重载的解决方案,非常的实用,给需要的小伙伴参考下

    overload-js:javascript中的函数重载

    JavaScript 中的函数重载为 3.9KB,压缩为 1.4KB。 提供工具来模拟大多数严格类型语言中存在的。 防止难以阅读和维护的混乱、冗长、if 语句、类型检查函数。 受和启发的样式和 API。 npm install overload-js ...

    为JavaScript添加重载函数的辅助方法

    大家都习惯了重载带来的便利。JavaScript有没有重载呢?有人会回答没有,因为函数会被覆盖;有人说有,我们可以模拟重载这 一操作。

    javascript中通过arguments参数伪装方法重载

    而javascript没有方法重载这个概念。但是我们可以通过arguments这个参数来伪装成函数的重载 在模拟之前我们先看一下代码: 代码如下: //表面上没有声明形式参数的函数 function fun() { alert&#40;“示例代码”&#...

    JavaScript王者归来part.1 总数2

     6.2.2.3 一个使用Arguments对象模拟函数重载的例子   6.2.3 参数类型匹配--一个利用arguments实现函数重载机制的例子   6.3 函数的调用者和所有者   6.3.1 函数的调用者   6.3.2 函数的所有者--一个为函数...

    源文件程序天下JAVASCRIPT实例自学手册

    6.3.3 模拟堆栈和队列操作的方法 6.3.4 使用splice()方法添加和删除数组元素 6.3.5 修改length属性更改数组 6.3.6 调用Array对象的方法生成字符串 6.3.7 连接两个数组 6.3.8 常见属性和方法汇总 6.4 Date对象 6.4.1 ...

    Javascript 面向对象 重载

    假如 我这样定义: 代码如下: function getDate(){... 那么JavaScript是怎么实现(准确地讲应该叫“模拟”)的呢?。 答案很简单:arguments arguments是JavaScript里的一个内置对象,包含了调用者传递的实际参数,但不

    Javascript数组操作高级心得整理

     模拟函数重载 10 (3) Function对象(类) 10  Function对象的使用 10  使用Function类的length属性 11  使用Function类的valueOf()方法和toString()方法 11 (4) 闭包 11 8. 循环语句 11 (1) for循环 12  ...

    JavaScript基础和实例代码

    6.3.3 模拟堆栈和队列操作的方法 6.3.4 使用splice()方法添加和删除数组元素 6.3.5 修改length属性更改数组 6.3.6 调用Array对象的方法生成字符串 6.3.7 连接两个数组 6.3.8 常见属性和方法汇总 6.4 Date对象 6.4.1 ...

    javascript 面向对象编程基础 多态

    Javascript已经可以模拟出面向对象的封装和继承特性,但是不幸的是Javascript对多态特性的支持非常弱!其它面向对象语言的多态一般都由方法重载和虚方法来实现多态,Javascript也通过这两种途径来实现! 重载:由于...

    Javascript中的arguments对象

    但可用arguments对象模拟重载效果。 arguments对象:函数对象内,自动创建的专门接收所有参数值得类数组对象。 arguments[i]: 获得传入的下标为i的参数值 arguments.length: 获得传入的参数个数! 重载:  程序...

    JavaScript高级教程

    2.11.1 无重载..............................................53 2.11.2 arguments 对象..............................................53 2.11.3 Function 类..............................................54 ...

    C-Sharp-Promise:用于C#的Promises库,用于管理异步操作

    由使用,用于在Unity3d上构建严肃的游戏和模拟。 如果您对使用诺言进行游戏开发和Unity感兴趣,请参阅。最近更新v3.0(2018年2月15日) 最后经过修改,使其工作方式与JavaScript中的一致。 增加了对在诺言中报告...

    ExtAspNet v2.2.1 (2009-4-1) 值得一看

    +为TabStrip的GetAddTabReference函数增加重载方法,以便指定Tab的图标(feedback:mmdcup)。 -修正此函数通过PageContext.RegisterStartupScript调用时不能正确显示Icon的BUG(feedback:zhaowenke)。 -修正basic/...

    jasq:与 Jasmine 集成的 AMD 依赖注入器

    贾斯克 与集成的依赖注入器。 Jasq 通过重载 Jasmine 的describe和it来... 为了实现依赖注入,Jasq 包装了 Jasmine 的describe & it全局函数,并额外提供了重载版本,它们接受的参数不同。 这些作为 Jasmine 内置功能的

    ExtAspNet_v2.3.2_dll

    +为TabStrip的GetAddTabReference函数增加重载方法,以便指定Tab的图标(feedback:mmdcup)。 -修正此函数通过PageContext.RegisterStartupScript调用时不能正确显示Icon的BUG(feedback:zhaowenke)。 -修正basic/...

Global site tag (gtag.js) - Google Analytics