【本文已过时,请参阅最新的重载实现方式】
接触过Java、C#的人应该都比较了解重载函数。
但是JavaScript中并没有这样的机制是不是令人倍感烦恼呢?
不用怕!因为解决方法来啦!~
你没用过Java、C#?你问我什么是重载函数?
嘛~那我就举一个简单的栗子好了~
fn("nivk", 21); // 我叫nivk,我今年21岁
fn("nivk"); // 我叫nivk,不过年龄保密哦!
fn("nivk", "温暖"); // 我叫nivk,我喜欢的人叫温暖^_^
从上面的效果简单来看,就是传入不同参数、不同数量,或者不同参数、相同数量,输出不同结果的东东就叫重载函数了!~
实际上我们很可能已经通过不同方法实现这个效果了,这里再举个栗子~
function fn () {
switch(arguments.length) {
case 1:
// 做只有一个参数的事
break;
case 2:
// 做两个参数参与的事
break;
}
}
如果你觉得这就够了~哼哼,图样图森破。
我现在想要一个函数10个用法,其中三个参数数量是重叠的,但是参数类型是不同的。来实现一下~~~~
你是不是想一口老血喷涌而出呢?
好了,既然作用我们都知道了,那么开始讲最无聊的原理了,可不要因为无聊就睡着了啊!~
一个函数重载实现我们需要两个数组来保存,分别是:
参数列表:["Number", "String, Number", "Number, String"]
函数列表:[function(){}, function(){}, function(){}]
参数列表[n] 对应的执行函数是 函数列表[n]
这可千万不能错了!
我们再以最上面的几个栗子来举例一下:
fn("nivk", 21); // 对应 "String, Number"
fn("nivk"); // 对应 "String"
fn("nivk", "温暖"); // 对应 "String, String"
这样就应该很明了了吧!~哈哈~原来是这么简单的说~
好了,最苦逼的一刻终于到来了,那么我如何知道 ("nivk",21)这两个参数的类型?如何与 "String, Number" 对应起来呢?
额………………今天的教程到此结束……永别了~
哈哈,开个玩笑。
其实一点也不难,不过我们首先得看看另一个问题。
“String, Number”.toLowerCase().trim().split(","); // ["string", "number"]
typeof "nivk"; // "string"
typeof 21; // "number"
咦?!对上了!大赞啊!
我们再试试别的!
"Array".toLowerCase().trim().split(","); // ["array"]
typeof []; // "object"
这……这不是坑爹嘛?!这叫我怎么区分数组和普通对象啊!~~~
再试试别的方法
[] instanceof Array; // true
这……竟然可以这样知道类型。。。真是无语了。
现在有两条路可走,一个是typeof ,另一个是 instanceof……
好吧,为了性能和其他的考虑,我们双管齐下!
Number、String、 Boolean、 Function、 Object 、Null 统统 typeof
其他的一律 instanceof!
Ok,知道这一点以后,我们需要就好办多了。
因为代码过于冗长,所以这里只讲讲思路罢了。
“String, Array”.trim().split(","); // ["String", "Array"]
switch (type) {
case "Number":
case "String":
case "Boolean":
case "Function":
case "Object":
return str.toLowerCase();
case "Null":
return Object;
case "undefiend":
throw new Error("Invalid type");
case "any":
return "[object Unkonw]";
default:
return eval(str);
}
这样,"String"就会变成 "string",而"Array"则会变成 Array的类型对象。
在调用重载函数的时候首先判断存储的类型是否为string,如果为true,则将传入的参数使用typeof进行判断。
否则就用instanceof进行判断类型。
若所有参数类型及数量判断无误则调用相关的函数。
原理简单,不算很复杂。但是实现起来无比冗长。
放出所有代码,因为未经过优化,所有请自行斟酌是否需要直接使用,当然啦!~你直接使用也是没什么问题的。
(function (window, document, undefiend) {
"use strict";
window.any = "[object Unkonw]";
function getType(str) {
/// <summary>根据字符串获取Js可用于判断的类型</summary>
/// <param name="str" type="String"></param>
/// <returns type="any" />
if (!str || !str.toString().trim()) return undefiend;
str = str.toString().trim();
switch (str) {
case "Number":
case "String":
case "Boolean":
case "Function":
case "Object":
return str.toLowerCase();
case "Null":
return Object;
case "undefiend":
throw new Error("Invalid type");
case "any":
return any;
//case "Object":
//case "Function":
default:
return eval(str);
}
}
function processParams(s) {
/// <summary>处理参数</summary>
var pList = null;
if (s) {
pList = s.split(",");
for (var i = pList.length; i--;) {
pList[i] = getType(pList[i]);
}
}
return pList;
}
window.overload = function () {
/// <summary>创建重载对象</summary>
/// <returns type="Function" />
var _paramList = [],
_functionList = [];
var overloadFunction = function () {
/// <summary>调用重载函数</summary>
var len = _paramList.length,
pList = null;
if (!len) throw new Error("Function not implemented");
while (len--) {
pList = _paramList[len];
if (pList !== null && !(pList instanceof Array)) {
pList = _paramList[len] = processParams(pList);
}
if (!arguments.length && !pList) return _functionList[len].apply(this, arguments);
else if (arguments.length && !pList || arguments.length != pList.length) continue;
for (var i = 0; i < arguments.length; i++) {
var isOK = typeof pList[i] === "string";
if (!isOK) isOK = !(arguments[i] instanceof pList[i]);
if (pList[i] !== any && typeof arguments[i] !== pList[i] && isOK) break;
if (i === arguments.length - 1) return _functionList[len].apply(this, arguments);
}
}
throw new Error("Invalid parameter");
};
overloadFunction.add = function (str, fun) {
/// <summary>添加重载函数</summary>
/// <param name="str" type="String">参数列表字符串</param>
/// <param name="fun" type="Function">重载调用的函数</param>
/// <returns type="OverloadFunction" />
_paramList.push(str);
_functionList.push(fun);
return overloadFunction;
};
return overloadFunction;
};
})(window, document);
用法如下:
var fn = overload().
add("String, Number", function (name, age) {
alert("我叫" + name + ",我今年" + age + "岁");
}).
add("String, String", function (name, like) {
alert("我叫" + name + ",我喜欢的人叫" + like + "^_^");
}).
add("String", function (name) {
alert("我叫" + name + ",不过年龄保密哦!");
});
fn("nivk", 21);
fn("nivk");
fn("nivk", "温暖");
终于结束了痛苦的介绍……写博客真的是需要不少的口才(手才)呢……