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比较文档位置
Apr 08 Javascript
IE6浏览器下resize事件被执行了多次解决方法
Dec 11 Javascript
原始的js代码和jquery对比体会
Sep 10 Javascript
jQuery focus和blur事件的应用详解
Jan 26 Javascript
微信小程序 实现点击添加移除class
Jun 12 Javascript
JS实现留言板功能
Jun 17 Javascript
Vue组件中prop属性使用说明实例代码详解
May 31 Javascript
vue服务端渲染页面缓存和组件缓存的实例详解
Sep 18 Javascript
Vue中axios的封装(报错、鉴权、跳转、拦截、提示)
Aug 20 Javascript
ng-alain的sf如何自定义部件的流程
Jun 12 Javascript
用Javascript实现发送短信验证码间隔功能
Feb 08 Javascript
JS原生实现轮播图的几种方法
Mar 23 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
整理的9个实用的PHP库简介和下载
2010/11/09 PHP
php生成xml时添加CDATA标签的方法
2014/10/17 PHP
ecshop适应在PHP7的修改方法解决报错的实现
2016/11/01 PHP
PHP重置数组为连续数字索引的几种方式总结
2018/03/12 PHP
javascript 中对象的继承〔转贴〕
2007/01/22 Javascript
jQuery Selector选择器小结
2010/05/06 Javascript
JS小功能(操作Table--动态添加删除表格及数据)实现代码
2013/11/28 Javascript
jquery 实现两级导航菜单附效果图
2014/03/07 Javascript
使用AngularJS制作一个简单的RSS阅读器的教程
2015/06/18 Javascript
js图片切换具体实现代码
2016/10/13 Javascript
JS及JQuery对Html内容编码,Html转义
2017/02/17 Javascript
vue中component组件的props使用详解
2017/09/04 Javascript
详解用函数式编程对JavaScript进行断舍离
2017/09/18 Javascript
ES6学习教程之对象字面量详解
2017/10/09 Javascript
详述 Sublime Text 打开 GBK 格式中文乱码的解决方法
2017/10/26 Javascript
angularjs使用gulp-uglify压缩后执行报错的解决方法
2018/03/07 Javascript
vue 组件中slot插口的具体用法
2018/04/03 Javascript
微信小程序使用map组件实现路线规划功能示例
2019/01/22 Javascript
javascript实现对话框功能警告(alert 消息对话框)确认(confirm 消息对话框)
2019/05/07 Javascript
layui 上传插件 带预览 非自动上传功能的实例(非常实用)
2019/09/23 Javascript
[03:56]还原FTP电影首映式 DOTA2群星拼出遗迹世界
2014/03/26 DOTA
python中itertools模块zip_longest函数详解
2018/06/12 Python
Pandas DataFrame数据的更改、插入新增的列和行的方法
2019/06/25 Python
Python OpenCV之图片缩放的实现(cv2.resize)
2019/06/28 Python
解决pycharm每次打开项目都需要配置解释器和安装库问题
2020/02/26 Python
python实现定时发送邮件到指定邮箱
2020/12/23 Python
详解CSS3浏览器兼容
2016/12/14 HTML / CSS
介绍一下Linux中的链接
2016/06/05 面试题
英语专业毕业个人求职自荐信
2013/09/21 职场文书
《日月潭》教学反思
2014/02/28 职场文书
纠风工作实施方案
2014/03/15 职场文书
员工年终自我评价
2014/09/14 职场文书
研究生就业推荐表导师评语
2014/12/31 职场文书
萤火虫之墓观后感
2015/06/05 职场文书
同意报考公务员证明
2015/06/17 职场文书
python使用torch随机初始化参数
2022/03/22 Python