温故知新(八八)javaScript 中如何模拟实现方法的重载,动手实现下

javaScript 中如何模拟实现方法的重载,动手实现下

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

一、背景知识

JavaScript 不支持重载的语法,它没有重载所需要的的函数签名。ECMAScript 函数不能向传统意义上那样实现重载。而在其他语言(如Java)中,可以为一个函数编写多个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可。如前所述,ECMAScript 函数没有签名,因为其参数是由包含零活多个值得数组来表示的。而没有函数签名,真的的重载是不可能做到的。

二、什么是函数重载

重载函数时函数的一种特殊情况,为方便使用,允许在同一范围中声明几个功能类似的同名函数,但是这些同名函数的形式参数(值参数的个数、类型或者顺序)必须不同,也就是说同一个函数完成不同的功能。这就是重载函数。

三、模拟实现

利用闭包特性
addMethod 函数接受 3 个参数:目标对象、目标方法名、函数体,当函数被调用时:
1.先将目标 object[name] 的值存入变量 old 中,因此起初 old 中的值可能不是一个函数;
2.接着向 object[name] 赋值一个代理函数,并且由于变量 old 、 fnt 在代理函数中被引用,所以 old、fnt 将常驻内存不被回收

代理函数被调用时:
1. 先判断传入参数与其父级作用域中 fn 期望接收参数的个数是否一致,若是则调用该 fn;
2. 若否,则判断其父级作用域中 old 值类型是否为函数,若是则调用该 old;
3. 当 old 中存有上一次生成的代理函数时,则会重复前面两个步骤,直至 old 值不为代理函数。

function addMethod(object, name, fnt) {
    // 保存前一个值,以便后续调用
    var old = object[name];
    object[name] = function () { 
        // 向object[name]赋值一个代理函数
        // 判断fnt期望接收的参数与传入参数个数是否一致
        if (fnt.length === arguments.length) {
            // 若是,则调用fnt
            return fnt.apply(this, arguments)
        } else if (typeof old === 'function') {
            // 若否,则判断old的值是否为函数
            // 若是,则调用old
            return old.apply(this, arguments);
        }
    };
}
//模拟重载add
var methods = {};
//添加方法,顺序无关
addMethod(methods, 'add', function () {
    return 0
});
addMethod(methods, 'add', function (a, b) {
    return a + b
});
addMethod(methods, 'add', function (a, b, c) {
    return a + b + c
});
//执行
console.log(methods.add()); //0
console.log(methods.add(10, 20)); //30
console.log(methods.add(10, 20, 30)); //60

我再再来一个投机取巧易理解的方式:

function addMethod(obj, name, fn) {
    //形参数量
    let len = fn.length;
    //根据形参记录fn
    obj._overLoad_ ? obj._overLoad_[len] = fn : obj._overLoad_ = {
        [len]: fn
    };
    //重载名
    !obj[name] && (obj[name] = function () {
        //实参数量
        let tLen = arguments.length;
        //赋值方法
        return obj._overLoad_[tLen] ? obj._overLoad_[tLen].apply(this, arguments) : undefined;
    })
}

//模拟重载add
var methods = {};
//添加方法,顺序无关
addMethod(methods, 'add', function () {
    return 0
});
addMethod(methods, 'add', function (a, b, c) {
    return a + b + c
});
addMethod(methods, 'add', function (a, b) {
    return a + b
});

//执行
console.log(methods.add()); //0
console.log(methods.add(10, 20)); //30
console.log(methods.add(10, 20, 30)); //60

 

 

 

 

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值