JavaScript 通过模式匹配实现重载


Posted in Javascript onAugust 12, 2010

正好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() {...} 
});
Javascript 相关文章推荐
javascript生成/解析dom的CDATA类型的字段的代码
Apr 22 Javascript
js下利用控制器载入对应脚本
Jul 17 Javascript
jquery入门—编写一个导航条(可伸缩)
Jan 07 Javascript
javascript文件中引用依赖的js文件的方法
Mar 17 Javascript
jquery实现的判断倒计时是否结束代码
Feb 05 Javascript
jQuery获取attr()与prop()属性值的方法及区别介绍
Jul 06 Javascript
移动端网页开发调试神器Eruda的介绍与使用技巧
Oct 30 Javascript
jquery点击回车键实现登录效果并默认焦点的方法
Mar 09 jQuery
微信小程序如何利用getCurrentPages进行页面传值
Jul 01 Javascript
解决layUI的页面显示不全的问题
Sep 20 Javascript
深入了解Vue.js 混入(mixins)
Jul 23 Javascript
解决VueCil代理本地proxytable无效报错404的问题
Nov 07 Javascript
js更优雅的兼容
Aug 12 #Javascript
页面只有一个text的时候,回车自动submit的解决方法
Aug 12 #Javascript
javascript闭包的理解和实例
Aug 12 #Javascript
javascript 词法作用域和闭包分析说明
Aug 12 #Javascript
判断客户端浏览器是否安装了Flash插件的多种方法
Aug 11 #Javascript
基于JQuery的数字改变的动画效果--可用来做计数器
Aug 11 #Javascript
JQuery最佳实践之精妙的自定义事件
Aug 11 #Javascript
You might like
PHP 递归效率分析
2009/11/24 PHP
初学PHP的朋友 经常问的一些问题。不断更新
2011/08/11 PHP
PHP 日,周,月点击排行统计
2012/01/11 PHP
PHP __autoload()方法真的影响性能吗?
2012/03/30 PHP
解析PHP中数组元素升序、降序以及重新排序的函数
2013/06/20 PHP
php生成验证码函数
2015/10/20 PHP
基于jQueryUI和Corethink实现百度的搜索提示功能
2016/11/09 PHP
php中的抽象方法和抽象类
2017/02/14 PHP
PHP多进程编程之僵尸进程问题的理解
2017/10/15 PHP
thinkPHP事务操作简单案例分析
2019/10/17 PHP
简单的jquery拖拽排序效果实现代码
2011/09/20 Javascript
Ajax异步提交表单数据的说明及方法实例
2013/06/22 Javascript
js+css实现的简单易用兼容好的分页
2013/12/30 Javascript
JQuery复制DOM节点的方法
2015/06/11 Javascript
JS 对象(Object)和字符串(String)互转方法
2016/05/20 Javascript
js实现千分符和保留几位小数的简单实例
2016/08/01 Javascript
Javascript中作用域的详细介绍
2016/10/06 Javascript
详解node如何让一个端口同时支持https与http
2017/07/04 Javascript
Vue的MVVM实现方法
2017/08/16 Javascript
react-native使用react-navigation进行页面跳转导航的示例
2017/09/07 Javascript
Vue中自定义全局组件的实现方法
2017/12/08 Javascript
跟老齐学Python之通过Python连接数据库
2014/10/28 Python
在Python中使用HTML模版的教程
2015/04/29 Python
简单了解Python下用于监视文件系统的pyinotify包
2015/11/13 Python
Python之web模板应用
2017/12/26 Python
django反向解析URL和URL命名空间的方法
2018/06/05 Python
[原创]Python入门教程3. 列表基本操作【定义、运算、常用函数】
2018/10/30 Python
python如何获取列表中每个元素的下标位置
2019/07/01 Python
python对输出的奇数偶数排序实例代码
2020/12/04 Python
班主任个人工作反思
2014/04/28 职场文书
公司股份合作协议书
2014/12/07 职场文书
校长个人总结
2015/03/03 职场文书
学校中秋节活动总结
2015/03/23 职场文书
五星红旗迎风飘扬观后感
2015/06/17 职场文书
《颐和园》教学反思
2016/02/19 职场文书
毕业欢送晚会主持词
2019/06/25 职场文书