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 相关文章推荐
IE下写xml文件的两种方式(fso/saveAs)
Aug 05 Javascript
JavaScript对象学习经验整理
Oct 12 Javascript
easyui form validate总是返回false的原因及解决方法
Nov 07 Javascript
vuejs通过filterBy、orderBy实现搜索筛选、降序排序数据
Oct 26 Javascript
Vue.js实战之组件之间的数据传递
Apr 01 Javascript
Ionic3 UI组件之Gallery Modal详解
Jun 07 Javascript
js学习总结之DOM2兼容处理this问题的解决方法
Jul 27 Javascript
微信小程序实现授权登录
May 15 Javascript
自定义Vue组件打包、发布到npm及使用教程
May 22 Javascript
微信小程序实现录制、试听、上传音频功能(带波形图)
Feb 27 Javascript
JavaScript实现轮播图特效
Apr 10 Javascript
jQuery加PHP实现图片上传并提交的示例代码
Jul 16 jQuery
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
国产动画《伍六七》原声大碟大卖,啊哈娱乐引领音乐赋能IP的新尝试
2020/03/08 国漫
PHP提示Deprecated: mysql_connect(): The mysql extension is deprecated的解决方法
2014/08/28 PHP
smarty自定义函数htmlcheckboxes用法实例
2015/01/22 PHP
php给图片添加文字水印方法汇总
2015/08/27 PHP
Thinkphp5框架使用validate实现验证功能的方法
2019/08/27 PHP
用roll.js实现的图片自动滚动+鼠标触动的特效
2007/03/18 Javascript
getAsDataURL在Firefox7.0下无法预览本地图片的解决方法
2013/11/15 Javascript
js获取通过ajax返回的map型的JSONArray的方法
2014/01/09 Javascript
javascript实现鼠标拖动改变层大小的方法
2015/04/30 Javascript
基于jquery实现瀑布流布局
2020/06/28 Javascript
Bootstrap Table从零开始
2017/06/30 Javascript
AngularJS使用ocLazyLoad实现js延迟加载
2017/07/05 Javascript
vue实现搜索功能
2019/05/28 Javascript
详解vue父子组件关于模态框状态的绑定方案
2019/06/05 Javascript
详解vue 自定义组件使用v-model 及探究其中原理
2019/10/11 Javascript
js实现计算器功能
2020/08/10 Javascript
Django学习笔记之Class-Based-View
2017/02/15 Python
使用C++扩展Python的功能详解
2018/01/12 Python
python jieba分词并统计词频后输出结果到Excel和txt文档方法
2018/02/11 Python
使用pandas批量处理矢量化字符串的实例讲解
2018/07/10 Python
基于python3实现socket文件传输和校验
2018/07/28 Python
pandas dataframe添加表格框线输出的方法
2019/02/08 Python
python查看数据类型的方法
2019/10/12 Python
python 调整图片亮度的示例
2020/12/03 Python
web字体加载方案优化小结
2019/11/29 HTML / CSS
naturalizer加拿大官网:美国娜然女鞋
2017/04/04 全球购物
毕业生找工作推荐信
2013/11/21 职场文书
《美丽的公鸡》教学反思
2014/02/25 职场文书
国际贸易毕业生自荐书
2014/06/22 职场文书
社区志愿者活动方案
2014/08/18 职场文书
2014财务年度工作总结
2014/11/11 职场文书
2014年保洁工作总结
2014/11/24 职场文书
MongoDB数据库的安装步骤
2021/06/18 MongoDB
SpringBoot实现异步事件驱动的方法
2021/06/28 Java/Android
Redis Cluster 集群搭建你会吗
2021/08/04 Redis
Mysql中where与on的区别及何时使用详析
2021/08/04 MySQL