JavaScript的重载函数实现

【本文已过时,请参阅最新的重载实现方式】

最新版本的文章链接


接触过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", "温暖");


终于结束了痛苦的介绍……写博客真的是需要不少的口才(手才)呢……

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值