DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> JavaScript 通過模式匹配實現重載
JavaScript 通過模式匹配實現重載
編輯:關於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() {...}
});
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved