JavaScript的重载

函数的重载:理论上来说,函数的重载就是两个及两个人以上的同名函数,而这些函数的参数的个数、类型或者顺序必须不同,也就是相同的函数完成不同的功能。
理论上JavaScript是不存在重载的,或者说js函数不能被重载。如下例子:

function add(a,b){
		var sum=a+b;
		console.log(sum);
}
add(1,1);//输出结果为2

但只有一个函数的时候,正常运行,其在控制台打印的结果为2;

function add(a,b){
		var sum=a+b;
		console.log(sum);
}
function add(a,b,c){
		var sum1=a+b+c;
		console.log(sum1);
}
add(1,1);//输出结果为NaN
add(1,1,1);//输出结果为3

这两个函数的函数名相同但参数的个数不同,表面上符合重载的定义,但是输出结果却不是我们预想的结果,它把第一个函数给覆盖了;所以得出一个结论:**JavaSrcipt不存在重载。**而JS如何去是现实重载,实际上就需要去模拟重载。

方法一:
第一种方法就是利用arguments存放参数,并用switch来判断参数得个数来实现模拟重载。这种方法简单粗暴,但是太过于敷衍:

function overLoad(){
		switch(arguments.length){
				case 0:console.log("参数个数为0个!");break;
				case 1:console,log("参数个数为1个!");break;
				/*后面还有很多case*/
		}
}
overLoad();//输出结果为(参数个数为0个!)
overLoad(1);//输出结果为(参数个数为1个!)

方法二:
利用闭包机制实现JavaSrcipt重载:

function method(obj,name,fnc){
            var old = obj[name];
            console.log(old instanceof Function);
            obj[name] = function(){
                console.log(arguments.length+" "+fnc.length);
                if(arguments.length === fnc.length){
                    return fnc.apply(this,arguments);
                }else if(typeof old === "function"){
                    return old.apply(this,arguments);
                }
            }
        }
        var people = {
            values:["Zhang san","Li si"]
        };
        method(people,"find",function(){
            console.log("无参数");
            return this.values;
        })
        method(people,"find",function(firstname){
            console.log("一个参数");
            var ret = [];
            for(var i = 0;i < this.values.length;i++){
                if(this.values[i].indexOf(firstname) === 0){
                    ret.push(this.values[i])
                }
            }
            return ret;
        })
        method(people,"find",function(firstname,lastname){
            console.log("两个参数");
            var ret = [];
            for(var i = 0;i < this.values.length;i++){
                if(this.values[i] == firstname + " " + lastname){
                    ret.push(this.values[i])
                }
            }
            return ret;
        })
        console.log(people.find());
        console.log(people.find("Zhang"));

思路:这段代码第一眼看到我是懵逼的,再看有点思路,再看又懵了。这种方法巧妙的运用了闭包原理,既然js后面的函数会覆盖前面的同名函数,我就强行让所有的函数都留在内存里,等我需要的时候再去找它。有了这个想法,是不是就想到了闭包,函数外访问函数内的变量,从而使函数留在内存中不被删除。就是闭包。

实现过程:我们看一下上面这段代码,最重要的是method方法的定义:这个方法中最重要的一点就是这个old,这个old真的很巧妙。它的作用相当于一个指针,指向上一次被调用的method函数,这样说可能有点不太懂,我们根据代码来说,js的解析顺序从上到下为。

1.解析method(先不管里面的东西)

2.method(people,“find”,function() 执行这句的时候,它就回去执行上面定义的方法,然后此时old的值为空,因为你还没有定义过这个函数,所以它此时是undefined,然后继续执行,这是我们才定义 obj[name] = function(),然后js解析的时候发现返回了fnc函数,更重要的是fnc函数里面还调用了method里面的变量,这不就是闭包了,因为fnc函数的实现是在调用时候才会去实现,所以js就想,这我执行完也不能删除啊,要不外面那个用啥,就留着吧先(此处用call函数改变了fnc函数内部的this指向)

3.好了第一次method的使用结束了,开始了第二句,method(people,“find”,function(firstname) 然后这次使用的时候,又要执行old = obj[name]此时的old是什么,是函数了,因为上一条语句定义过了,而且没有删除,那我这次的old实际上指向的是上次定义的方法,它起的作用好像一个指针,指向了上一次定义的 obj[name]。然后继续往下解析,又是闭包,还得留着。

4.第三此的method调用开始了,同理old指向的是上次定义的 obj[name] 同样也还是闭包,还得留着。

5.到这里,内存中实际上有三个 obj[name],因为三次method的内存都没有删除,这是不是实现了三个函数共存,同时还可以用old将它们联系起来是不是很巧妙

6.我们 people.find() 的时候,就会最先调用最后一次调用method时定义的function,如果参数个数相同 也就是 (arguments.length === fnc.length) 那么就执行就好了,也不用找别的函数了,如果不相同的话,那就得用到old了 return old.apply(this,arguments); old指向的是上次method调用时定义的函数,所以我们就去上一次的找,如果找到了,继续执行 arguments.length === fnc.length 如果找不到,再次调用old 继续向上找,只要你定义过,肯定能找到的,对吧!

总结:运用闭包的原理使三个函数共存于内存中,old相当于一个指针,指向上一次定义的function,每次调用的时候,决定是否需要寻找。

输出结果
在这里插入图片描述
执行过程很容易说明这一点:首先第一次调用的时候 old肯定不是函数,所以instance判断是false,继续调用的话就会为true。然后,我们调用method的顺序,是从没有参数到两个参数,所以我们最先调用find方法,是最后一次method调用时定义的,所以fnc的length长度是2.然后向上找,length为1,最后终于找到了length为0的然后执行,输出。

注:后半文出自http://www.cnblogs.com/pianruijie/p/7997914.html;

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值