你们都知道,所谓重载,就是一组相同的函数名,有不一样个数的参数,在使用时调用一个函数名,传入不一样参数,根据你的参数个数,来决定使用不一样的函数!重载这个在JAVA这些经典的编程语言里面都很好用,能够说调用同一个方法名用不一样的参数就能够随心所欲了。前端
可是咱们知道JavaScript中是没有重载的(为何没重载?不是JAVA的特性JavaScript也会有的吗?),由于后面定义的函数会覆盖前面的同名函数,可是重载那么好用,咱们想在JavaScript实现函数重载该怎么办呢?编程
今天就来给你们讲讲在JavaScript里面实现函数重载的两个思路。(零基础的同窗打扰了,这篇不太适合你,须要点面向对象基础。)数组
这种方法比较简单,给一个思路,你们确定都能理解,就是函数内部用switch语句,根据传入参数的个数调用不一样的case语句,从而功能上达到重载的效果。
这种方法简单粗暴。可是对于一个正在学习js的人来讲,这种方法未免太敷衍了。(那么没技术含量,怎么能让我变成前端开发大神呢?)闭包
下面重点介绍一下第二种,老实说我第一次看的时候很吃力,看了一个小时才捋清楚,由于有的知识点虽然看过了可是不熟悉。(干货很足,别看走神)app
咱们这个例子,是若是你不传入参数,就会输出全部的人,输入firstname,就会输出匹配的人,若是输入全名的人,也会输出匹配的人。若是用重载的话,用户体验确实会很好(这个例子是我之前学习时从网上扒下来的,很经典,具备表明性,可是他们都没有写实现过程,因此今天我来给你们说讲一下)编程语言
//第二种实现重载的方法 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","Wang wu"] }; //重载无参数查找方法,会输出全部人 method(people,"find",function(){ console.log("无参数"); return this.values; }) //重载1个参数查找方法,输入firstname参数,找打匹配firstname的人 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; }) //重载2个参数查找方法,输入全名,找到对应的人 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"));
思路:这段代码第一眼看的时候确定是懵的,再看一次好像有点思路,再看就又懵了。
其实呢,这种方法巧妙的运用了JavaScript的闭包原理(重点),既然js后面的函数会覆盖前面的同名函数,我就强行让全部的函数都留在内存里,等我须要的时候再去找它。
有了这个想法,是否是就想到了闭包,函数外访问函数内的变量,从而使函数留在内存中不被删除。这就是闭包的核心做用。函数
实现过程:
咱们看一下上面这段代码,最重要的是method方法的定义:这个方法中最重要的一点就是这个old,这个old真的很巧妙。它的做用至关于一个指针,指向上一次被调用的method函数,这样说可能有点不太懂,咱们根据代码来讲,js的解析顺序从上到下为。
1.解析method(先无论里面的东西)
2.method(people,"find",function() ) 执行这句的时候,它就回去执行上面定义的方法,而后此时old的值为空,由于你尚未定义过这个函数,因此它此时是undefined。
而后继续执行,这时候咱们才定义 obj[name] = function()。学习
而后js解析的时候发现返回了fnc函数,更重要的是fnc函数里面还调用了method里面的变量,这不就是闭包了!
由于fnc函数的实现是在调用时候才会去实现,因此js就想,这我执行完也不能删除啊,要不外面那个用啥,就留着吧先(此处用apply函数改变了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); this
old指向的是上次method调用时定义的函数,因此咱们就去上一次的找,若是找到了,继续执行 arguments.length === fnc.length 若是找不到,再次调用old 继续向上找,只要你定义过,确定能找到的。spa
总结:运用闭包的原理使三个函数共存于内存中,old至关于一个指针,指向上一次定义的function,每次调用的时候,决定是否须要寻找。
最后来看看执行输出结果:
执行过程很容易说明这一点:首先第一次调用的时候 old确定不是函数,因此instance判断是false,继续调用的话就会为true。
而后,咱们调用method的顺序,是从没有参数到两个参数,因此咱们最早调用find方法,是最后一次method调用时定义的,因此fnc的length长度是2.而后向上找,length为1,最后终于找到了length为0的而后执行,输出。
好了,今天的内容就那么多吧!要是你也喜欢,就转发给更多朋友学习吧!
喜欢的朋友也能够关注个人公众号:网页前端开发学习,发现更多好文哦!