重名就会被覆盖?那JavaScript中是如何实现重载的呢?

2018-07-13 admin

大家都知道,所谓重载,就是一组相同的函数名,有不同个数的参数,在使用时调用一个函数名,传入不同参数,根据你的参数个数,来决定使用不同的函数!重载这个在JAVA这些经典的编程语言里面都很好用,可以说调用同一个方法名用不同的参数就可以为所欲为了。

clipboard.png

但是我们知道JavaScript中是没有重载的(为什么没重载?不是JAVA的特性JavaScript也会有的吗?),因为后面定义的函数会覆盖前面的同名函数,但是重载那么好用,我们想在JavaScript实现函数重载该怎么办呢?

clipboard.png

今天就来给大家讲讲在JavaScript里面实现函数重载的两个思路。(零基础的同学打扰了,这篇不太适合你,需要点面向对象基础。)

clipboard.png


第一种方法:

这种方法比较简单,给一个思路,大家肯定都能理解,就是函数内部用switch语句,根据传入参数的个数调用不同的case语句,从而功能上达到重载的效果。 这种方法简单粗暴。但是对于一个正在学习js的人来说,这种方法未免太敷衍了。(那么没技术含量,怎么能让我变成前端开发大神呢?)

clipboard.png

下面重点介绍一下第二种,老实说我第一次看的时候很吃力,看了一个小时才捋清楚,因为有的知识点虽然看过了但是不熟悉。(干货很足,别看走神)

clipboard.png

第二种方法:

我们这个例子,是如果你不传入参数,就会输出所有的人,输入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()。

clipboard.png

然后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);

clipboard.png

old指向的是上次method调用时定义的函数,所以我们就去上一次的找,如果找到了,继续执行 arguments.length === fnc.length 如果找不到,再次调用old 继续向上找,只要你定义过,肯定能找到的。

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

clipboard.png

clipboard.png

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

好了,今天的内容就那么多吧!要是你也喜欢,就转发给更多朋友学习吧! 喜欢的朋友也可以关注我的公众号:网页前端开发学习,发现更多好文哦!

推荐好文:作为一名前端开发工程师,你必须掌握的WEB模板引擎:Handlebars

原文链接:https://segmentfault.com/a/1190000015615011

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-35868.html

文章标题:重名就会被覆盖?那JavaScript中是如何实现重载的呢?

相关文章
html5+JavaScript教程-微信打飞机小游戏源码
js &#x2F;&#x2F; JavaScript Document var c = document.getElementById(&quot;dotu&quot;); var cxt = c.getContext(&quot;2d&q...
2015-11-12
请前往任务中心完善资料即可激活会员
登录后,点击右上角的用户名,在下拉菜单中可以进去“我的任务” 注册自动激活,本站没有VIP!没有充值!没有推广任务等等 回复即可下载 ...
2015-11-18
JavaScript编辑器推荐
主流编辑器有SublimeText,Notepad++,webstorm等,是使用最广泛的编辑器,但也有一些JavaScript编辑器提供有着各自的特性和功能,适应不同人的需求,以下是几款优秀的编辑器,相信你一定能找到自己喜欢的。 1. W...
2015-11-12
js性能优化 如何更快速加载你的JavaScript页面
确保代码尽量简洁 不要什么都依赖JavaScript。不要编写重复性的脚本。要把JavaScript当作糖果工具,只是起到美化作用。别给你的网站添加大量的JavaScript代码。只有必要的时候用一下。只有确实能改善用户体验的时候用一下。 ...
2015-11-12
2015年JavaScript或“亲库而远框架”
2014年过去了,作为一个JavaScript开发者很难满怀信心的去“挽回”一个特定的库或技术,即便是强大的Angular,似乎也因为最近的一些事情而动摇。 2014年10月的ng-europe会议上,Angular开发者团队透露了一个关于...
2015-11-12
10个强大的纯CSS3动画案例分享
我们的网页外观主要由CSS控制,编写CSS代码可以任意改变我们的网页布局以及网页内容的样式。CSS3的出现,更是可以让网页增添了不少动画元素,让我们的网页变得更加生动有趣,并且更易于交互。本文分享了10个非常炫酷的CSS3动画案例,希望大家...
2015-11-16
Android中Okhttp3实现上传多张图片同时传递参数
之前上传图片都是直接将图片转化为io流传给服务器,没有用框架传图片。 最近做项目,打算换个方法上传图片。 Android发展到现在,Okhttp显得越来越重要,所以,这次我选择用Okhttp上传图片。 Okhttp目前已经更新到Okhttp...
2017-03-17
JavaScript实现PC手机端和嵌入式滑动拼图验证码三种效果
PC和手机端网站滑动拼图验证码效果源码,同时包涵了弹出式Demo,使用ajax形式提交二次验证码所需的验证结果值,嵌入式Demo,使用表单形式提交二次验证所需的验证结果值,移动端手动实现弹出式Demo三种效果 首先要确认前端使用页面,比如...
2017-03-17
从2014年的发展来展望JS的未来将会如何
&lt;font face=&quot;寰�杞�闆呴粦, Arial, sans-serif &quot;&gt;2014骞达紝杞�浠惰�屼笟鍙戝睍杩呴€燂紝鍚勭�嶈��瑷€灞傚嚭涓嶇┓锛屼互婊¤冻鐢ㄦ埛涓嶆柇鍙樺寲鐨勯渶姹傘€傝繖浜涜��...
2015-11-12
JavaScript常用特效chm下载
下载地址:JavaScript常用特效chm下载 对了,如果打开空白,在手册上右键属性解除锁定即可。 ...
2015-11-12
回到顶部