JavaScript 通过模式匹配实现重载

正好infinte同学提出“更优雅的兼容”其实也和这个问题有一定的关联(我们后面会看到)

在youa的脚本库中Function的Helper中,添加支持重载的模式匹配


代码如下:

/**
* 函数参数重载方法 overload,对函数参数进行模式匹配。默认的dispatcher支持*和...以及?,"*"表示一个任意类型的参数,"..."表示多个任意类型的参数,"?"一般用在",?..."表示0个或任意多个参数
* @method overload
* @static
* @optional {dispatcher} 用来匹配参数负责派发的函数
* @param {func_maps} 根据匹配接受调用的函数列表
* @return {function} 已重载化的函数
*/
overload: function(dispatcher, func_maps) {
if (! (dispatcher instanceof Function)) {
func_maps = dispatcher;
dispatcher = function(args) {
var ret = [];
return map(args, function(o) {return getType(o)}).join();
}
}

return function() {
var key = dispatcher([].slice.apply(arguments));
for (var i in func_maps) {
var pattern = new RegExp("^" + i.replace("*", "[^,]*").replace("...", ".*") + "$");
if (pattern.test(key)) {
return func_maps[i].apply(this, arguments);
}
}
};
},

FunctionH.overload 包括两个参数,一个是负责处理匹配条件的dispatcher函数(可缺省),另一个是一组函数映射表,默认dispatcher函数是根据实际调用的参数类型生成一个字符串,例如调用的三个参数依次为10、”a”、[1,2]将生成”number,string,array”,具体实现模式匹配的时候,将根据函数映射表的每一个”key”生成一个正则表达式,用这个正则表达式匹配dispatcher函数的返回值,如果匹配,则调用这个key对应的处理函数,否则依次匹配下一个key,例如:


代码如下:

getEx: function(obj, prop, returnJson) {
var ret, propType = ObjectH.getType(prop);
if (propType == 'array') {
if (returnJson) {
ret = {};
for (var i = 0; i & lt; prop.length; i++) {
ret[prop[i]] = ObjectH.getEx(obj, prop[i]);
}
} else {
//getEx(obj, props)
ret = [];
for (var i = 0; i & lt; prop.length; i++) {
ret[i] = ObjectH.getEx(obj, prop[i]);
}
}
} else {
//getEx(obj, prop)
var keys = (prop + "").split(".");
ret = obj;
for (var i = 0; i & lt; keys.length; i++) {
ret = ret[keys[i]];
}
if (returnJson) {
var json = {};
json[prop] = ret;
return json;
}
}
return ret;
},

上面这种情况下“万恶”的 if 可以优化为:


代码如下:

getEx: FunctionH.overload({
"*,array,*": function(obj, prop, returnJson) {
if (returnJson) {
ret = {};
for (var i = 0; i & lt; prop.length; i++) {
ret[prop[i]] = ObjectH.getEx(obj, prop[i]);
}
} else {
ret = [];
for (var i = 0; i & lt; prop.length; i++) {
ret[i] = ObjectH.getEx(obj, prop[i]);
}
}
return ret;
},
"*,string,*": function(obj, prop, returnJson) {
var keys = (prop + "").split(".");
ret = obj;
for (var i = 0; i & lt; keys.length; i++) {
ret = ret[keys[i]];
}
if (returnJson) {
var json = {};
json[prop] = ret;
return json;
}
return ret;
}
}),

OK,这种形式在一些人看来或许已经比原来看起来好一些了,但是其实还可以更进一步的——


代码如下:

getEx: FunctionH.overload(function(args) {
return "prop is " + ObjectH.getType(args[1]);
},{
"prop is array": function(obj, prop, returnJson) {
if (returnJson) {
ret = {};
for (var i = 0; i & lt; prop.length; i++) {
ret[prop[i]] = ObjectH.getEx(obj, prop[i]);
}
} else {
//getEx(obj, props)
ret = [];
for (var i = 0; i & lt; prop.length; i++) {
ret[i] = ObjectH.getEx(obj, prop[i]);
}
}
return ret;
},
"prop is string": function(obj, prop, returnJson) {
var keys = (prop + "").split(".");
ret = obj;
for (var i = 0; i & lt; keys.length; i++) {
ret = ret[keys[i]];
}
if (returnJson) {
var json = {};
json[prop] = ret;
return json;
}
return ret;
}
}),

还有“讨厌”的第三个参数,干脆也一并处理了——


代码如下:

getEx: FunctionH.overload(function(args) {
return "prop is " + ObjectH.getType(args[1]) + " and returnJson is " +args[2];
},{
"prop is array and returnJson is true": function(obj, prop, returnJson) {
ret = {};
for (var i = 0; i & lt; prop.length; i++) {
ret[prop[i]] = ObjectH.getEx(obj, prop[i]);
}
return ret;
},
"prop is array and returnJson is false": function(obj, prop, returnJson) {
ret = [];
for (var i = 0; i & lt; prop.length; i++) {
ret[i] = ObjectH.getEx(obj, prop[i]);
}
return ret;
},
"prop is string and returnJson is true": function(obj, prop, returnJson) {
var keys = (prop + "").split(".");
ret = obj;
for (var i = 0; i & lt; keys.length; i++) {
ret = ret[keys[i]];
}
var json = {};
json[prop] = ret;
return json;
},
"prop is string and returnJson is false": function(obj, prop, returnJson) {
var keys = (prop + "").split(".");
ret = obj;
for (var i = 0; i & lt; keys.length; i++) {
ret = ret[keys[i]];
}
return ret;
}
}),

例如说浏览器嗅探和特性探测之类种种,同理也能采用这个模式(当然这种形式有利有弊,使用者自己权衡吧)——


代码如下:

foo = FunctionH.overload(function() {
return MSIE ? "IE": "NotIE";
},{
"IE": function() {...}
"NotIE": function() {...}
});

(0)

相关推荐

  • js正则表达式学习笔记

    正则表达式:对字符串中的信息实现查找.替换和提取操作.(不支持注释和空白,必须写在一行内) 正则表达式的创建:包含在一对斜杠之间的字符(直接量语法) 例如: var pattern = /s$/; // 创建一个正则来匹配所有以字母s结尾的字符串,并赋值给pattern 一 .字符类 将直接量字符单独放进方括号内就组成了字符类. 一个字符类可以匹配它所包含的任意字符. 正则表达式的字符类: [...]      方括号内的任意字符 [^...]    不在方括号内的任意字符 .         

  • 正则表达式模式匹配的String方法

    在JavaScript代码中使用正则表达式进行模式匹配经常会用到String对象和RegExp对象的一些方法,例如replace.match.search等方法,以下是对一些方法使用的总结. String对象中支持正则表达式有4种方法,分别是:search.replace.match.split str.search(regexp) 定义:search()方法将在字符串str中检索与表达式regexp相匹配的字串,并且返回第一个匹配字串的第一个字符的位置.如果没有找到任何匹配的字串,则返回-1.

  • JavaScript学习笔记整理_用于模式匹配的String方法

    用于模式匹配的String方法: String支持4种使用正则表达式的方法: seach()用于检索,参数是一个正则表达式,返回第一个与之匹配的子串的位置,找不到则返回-1,如果参数不是正则表达式,则首先会通过RexExp构造函数将它转换成正则表达式,seach()方法不支持全局搜索,它忽略修饰符g: replace()用于检索与替换操作,第一个参数是一个正则表达式,第二个参数是要进行替换的字符串.它对调用该方法的字符串检索,按照模式匹配子串替换成第二个参数,若包含修饰符g则全文匹配.若第一个参

  • js 正则表达式学习笔记之匹配字符串

    今天看了第5章几个例子,有点收获,记录下来当作回顾也当作分享. 关于匹配字符串问题,有很多种类型,今天讨论 js 代码里的字符串匹配.(因为我想学完之后写个语法高亮练手,所以用js代码当作例子) 复制代码 代码如下: var str1 = "我是字符串1哦,快把我取走", str2 = "我是字符串2哦,快把我取走"; 比如这样一个字符串,匹配起来很简单 /"[^"]*"/g 即可.   PS: 白色截图是 chrome 34 控制台中

  • JavaScript 通过模式匹配实现重载

    正好infinte同学提出"更优雅的兼容"其实也和这个问题有一定的关联(我们后面会看到) 在youa的脚本库中Function的Helper中,添加支持重载的模式匹配 复制代码 代码如下: /** * 函数参数重载方法 overload,对函数参数进行模式匹配.默认的dispatcher支持*和...以及?,"*"表示一个任意类型的参数,"..."表示多个任意类型的参数,"?"一般用在",?..."表示0个

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

    JavaScript支持重载吗? JavaScript支持函数重载吗?可以说不支持,也可以说支持.说不支持,是因为JavaScript不能好像其它原生支持函数重载的语言一样,直接写多个同名函数,让编译器来判断某个调用对应的是哪一个重载.说支持,是因为JavaScript函数对参数列表不作任何限制,可以在函数内部模拟对函数重载的支持. 实际上,在很多著名的开源库当中,我们都可以看到函数内部模拟重载支持的设计.例如说jQuery的jQuery.extend方法,就是通过参数类型判断出可选参数是否存在

  • JavaScript中的方法重载实例

    .NET里面的方法重载用着的确很方便,哪Javascript里面能不能也哪样做呢? Javasciprt里面本生是没有方法重载的功能,以前很多人的做法可能是直接少传参数过去,然后在根据参数是否为 "undefined" 未定义来决定怎么处理,从而实现类似方法重载的功能. 例如: 复制代码 代码如下: var showMessage = function(name,value,id){     if(id != "undefined"){         alert(

  • 让 JavaScript 轻松支持函数重载 (Part 2 - 实现)

    识别文本签名 我们先来回顾一下上一篇文章中提到的Overload用例: 复制代码 代码如下: var extend = Overload .add("*, ...", function(target) { }) .add("Boolean, *, ...", function(deep, target) { }); 我们允许用户输入一个字符串,表示某一个重载的签名.在用户调用函数时,我们需要拿着用户输入的参数实例去跟签名上的每一个参数类型作比较,因此我们需要先把这个

  • JavaScript中的函数重载深入理解

    在JavaScript中有一种特殊的数据类型---Function类型,JavaScript的每个函数都是Function类型的实例.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定. <pre name="code" class="html">function sum(num1,num2) { return num1 +num2; } alert(sum(10,10)); //20 var other = sum; ale

  • 通过实例理解javascript中没有函数重载的概念

    将函数名想象为指针,也有助于理解为什么ECMAScript中没有函数重载的概念.如下例子: 复制代码 代码如下: function addSomeNum(num) {     return num+100; } function addSomeNum(num) {     return num+200; } var result=addSomeNum(100);//300 显然,这个例子中声明了两个同名函数,而结果则是后面的函数覆盖了前面的函数.以上代码实际上与下面的代码是一致的. 复制代码 代

  • JavaScript重载函数实例剖析

    1.javascript 中是没有重载函数这个概念的! 首先javascript是没有重载函数这个概念的,很久以前,我用javascript做网页的时候,写一些简单的效果,根本不需要用到重载函数,当写游戏的时候,有大量的函数的时候,就想用重载函数了,没想到javascript不支持. 我们来简单用两种方式来"模拟"下重载函数. 2.根据参数的个数来判断 javascript的函数中有一个叫arguments的变量,是记录参数的一个数组,我们可以用这个来判断参数的个数,然后分别执行不同的

  • Javascript面向对象编程

    Javascript的重要性 使用率 1.在web应用中,涉及到前端界面编程基本上都要用到javascript语言: 2.Web2.0及Ajax推动了javascript语言. 3.随着大量的c/s应用转向b/s,富客户端技术的不断推广,javascript语言的应用范围还将不断加大: javascript的特点 简单 动态 基于对象(面向对象) Javascript面向对象概述 Javascript是一种面向(基于)对象的动态脚本语言,是一种基于对象(Object)和事件驱动(EventDri

  • 浅谈javascript对象模型和function对象

    javascript中,函数就是对象 复制代码 代码如下: <html> <head> <script type="text/javascript"> function add(number){     alert(number+20); } var add=function(number){ alert(number+20); } function add(number,number1){     alert(number+30); } var a

  • 利用javascript的面向对象的特性实现限制试用期

    下边是我自己写的一个类,类中有字段.方法 复制代码 代码如下: //构造函数 function Person(name,sex,age) { this.name = name; this.sex = sex; this.age = age; }; Person.prototype.getName = function () { return this.name; }; Person.prototype.getSex=function(){ return this.sex; }; Person.p

随机推荐