正好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中的prototype属性实例分析说明
在Javascript中,一切都是对象,字符串是对象,数组是对象,变量是对象,函数也是对象,所以才会允许['a','b','c'].push('d');这样的操作存在。类本身也是一个对象,也可以定义属性和方法: 复制代码 代码如下: fu>>>详细阅读
本文标题:JavaScript 通过模式匹配实现重载
地址:http://www.17bianji.com/kaifa2/JS/25892.html
1/2 1