JavaScript函数重载操作实例浅析


Posted in Javascript onMay 02, 2020

本文实例讲述了JavaScript函数重载操作。分享给大家供大家参考,具体如下:

上个星期四下午,接到了网易的视频面试(前端实习生第二轮技术面试)。面了一个多小时,自我感觉面试得很糟糕的,因为问到的很多问题都很难,根本回答不上来。不过那天晚上,还是很惊喜的接到了HR面电话。现在HR面试的结果还没有出来,听说要等到下周二才出,所以再好好等几天哈。

前面说了这多的废话,现在是时候和伙伴们分享一下面试干货哈。因为二面问到的内容还挺多的,所以这里就不全部列举出来了。这里只讨论一下函数的重载。

下面是面试时的对话,“面”指面试官,“我”就是我~

面:你能说说JS怎么实现函数的重载吗?
我:因为JS的参数是可变长度的,是没有重载的!也是没必要用重载的!
面:怎么没必要使用重载?你先告诉什么是重载?
我: 重载就是一组具有相同名字、不同参数列表的函数(方法)。
面:对的,那为什么你还说JS没有重载,也没必要使用重载呢?

我当时一脸懵逼了,因为不知道面试官到底是想要考我什么,因为我记得《JS高级程序设计》里是提到过函数是没有重载的啊(后来查了一下,在第三版的66页,亲们可以自己翻开书本看看),但是现在面试官不同意我的回答啊,就是说在他看来,JS是有重载的,我不能坚持说没有重载啊。所以我就往重载的概念方向静静的思考了片刻,然后想到了使用arguments对象进行判断。于是:
我:我觉得,如果JS函数需要实现重载的话,可以根据arguments对象的length值进行判断。
面: 你可以写个例子出来给我看吗?
然后,我就在输入框里面写了如下的代码:

function overLoading() {
// 根据arguments.length,对不同的值进行不同的操作

switch(arguments.length) {


case 0:



/*操作1的代码写在这里*/



break;


case 1:



/*操作2的代码写在这里*/



break;


case 2:



/*操作3的代码写在这里*/
 




//后面还有很多的case......
}
 
}

我把代码发给了面试官。

面:对,这就是重载的一种实现的方法!不过你能不能想出一个更好的方法呢?
我: 暂时就想到这一种方法了。

好吧,跟面试官的对话就写这么多了。他说问我能不能想出一个更好的办法,意味着肯定还有其他我不知道的方法。所以,后来就开始翻书本查找。哈哈,终于在JQuery之父John Resig写的《secrets of the JavaScript ninja》找到了一个绝佳巧妙的方法!那种方法充分的利用了闭包的特性!

在介绍这个方法之前,我们先来看看外国人名字组成哈,比如,John Resig,John是first-name,Resig是last-name,就相当于我们的姓名由姓和名组成一样。

我们现在有这样的一个需求,有一个people对象,里面存着一些人名,如下:

var people = {
 values: ["Dean Edwards", "Sam Stephenson", "Alex Russell", "Dean Tom"]
};

我们希望people对象拥有一个find方法,当不传任何参数时,就会把people.values里面的所有元素返回来;当传一个参数时,就把first-name跟这个参数匹配的元素返回来;当传两个参数时,则把first-name和last-name都匹配的才返回来。因为find方法是根据参数的个数不同而执行不同的操作的,所以,我们希望有一个addMethod方法,能够如下的为people添加find的重载:

addMethod(people, "find", function() {}); /*不传参*/
addMethod(people, "find", function(a) {}); /*传一个*/
addMethod(people, "find", function(a, b) {}); /*传两个*/

这时候问题来了,这个全局的addMethod方法该怎么实现呢?John Resig的实现方法如下,代码不长,但是非常的巧妙:

function addMethod(object, name, fn) {
var old = object[name]; //把前一次添加的方法存在一个临时变量old里面

object[name] = function() { // 重写了object[name]的方法


// 如果调用object[name]方法时,传入的参数个数跟预期的一致,则直接调用


if(fn.length === arguments.length) {



return fn.apply(this, arguments);


// 否则,判断old是否是函数,如果是,就调用old


} else if(typeof old === "function") {



return old.apply(this, arguments);


}

}
}

现在,我们一起来分析一个这个addMethod函数,它接收3个参数,第一个为要绑定方法的对象,第二个为绑定的方法名称,第三个为需要绑定的方法(一个匿名函数)。函数体的的分析已经在注释里面了。

OK,现在这个addMethod方法已经实现了,我们接下来就实现people.find的重载啦!全部代码如下:

//addMethod
function addMethod(object, name, fn) {
var old = object[name];

object[name] = function() {


if(fn.length === arguments.length) {



return fn.apply(this, arguments);


} else if(typeof old === "function") {



return old.apply(this, arguments);


}

}
}
var people = {

values: ["Dean Edwards", "Alex Russell", "Dean Tom"]
};
 
/* 下面开始通过addMethod来实现对people.find方法的重载 */
 
// 不传参数时,返回peopld.values里面的所有元素
addMethod(people, "find", function() {

return this.values;
});
 
// 传一个参数时,按first-name的匹配进行返回
addMethod(people, "find", function(firstName) {

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;
});
 
// 传两个参数时,返回first-name和last-name都匹配的元素
addMethod(people, "find", function(firstName, lastName) {

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()); //["Dean Edwards", "Alex Russell", "Dean Tom"]
console.log(people.find("Dean")); //["Dean Edwards", "Dean Tom"]
console.log(people.find("Dean Edwards")); //["Dean Edwards"]

好啦,实现JS函数重载就写这么多啦,如果亲们有更好的实现方法,欢迎评论交流哈~

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
Javascript仿PHP $_GET获取URL中的参数
May 12 Javascript
JavaScript中合并数组的N种方法
Sep 16 Javascript
JavaScript监听和禁用浏览器回车事件实例
Jan 31 Javascript
jquery实现简单的banner轮播效果【实例】
Mar 30 Javascript
浅谈JavaScript的自动垃圾收集机制
Dec 15 Javascript
Bootstarp 基础教程之表单部分实例代码
Feb 03 Javascript
js实现图片左右滚动效果
Feb 27 Javascript
QRCode.js:基于JQuery的生成二维码JS库的使用
Jun 23 jQuery
webpack 4.0.0-beta.0版本新特性介绍
Feb 10 Javascript
axios发送post请求springMVC接收不到参数的解决方法
Mar 05 Javascript
微信小程序点击图片实现长按预览、保存、识别带参数二维码、转发等功能
Jul 20 Javascript
Vue——前端生成二维码的示例
Dec 19 Vue.js
有趣的JavaScript隐式类型转换操作实例分析
May 02 #Javascript
react-router-dom 嵌套路由的实现
May 02 #Javascript
在react中使用vue的状态管理的方法示例
May 02 #Javascript
JS表单验证插件之数据与逻辑分离操作实例分析【策略模式】
May 01 #Javascript
javascript实现的图片预览和上传功能示例【兼容IE 9】
May 01 #Javascript
jQuery实现的移动端图片缩放功能组件示例
May 01 #jQuery
jQuery实现移动端图片上传预览组件的方法分析
May 01 #jQuery
You might like
php在线打包程序源码
2008/07/27 PHP
yii的CURD操作实例详解
2014/12/04 PHP
iOS10推送通知开发教程
2016/09/19 PHP
使用JQUERY Tabs插件宿主IFRAMES
2010/01/01 Javascript
jquery 最简单易用的表单验证插件
2010/02/27 Javascript
JQuery制作的放大效果的popup对话框(未添加任何jquery plugin)分享
2013/04/28 Javascript
浅析tr的隐藏和显示问题
2014/03/05 Javascript
JavaScript前补零操作实例
2015/03/11 Javascript
javascript封装 Cookie 应用接口
2015/08/07 Javascript
JavaScript中innerHTML,innerText,outerHTML的用法及区别
2015/09/01 Javascript
关于安卓手机微信浏览器中使用XMLHttpRequest 2上传图片显示字节数为0的解决办法
2016/05/17 Javascript
基于AngularJs + Bootstrap + AngularStrap相结合实现省市区联动代码
2016/05/30 Javascript
js无提示关闭浏览器窗口的两种方法分析
2016/11/06 Javascript
jquery实现折叠菜单效果【推荐】
2017/03/08 Javascript
网页中的图片查看器viewjs使用方法
2017/07/11 Javascript
javascript实现QQ空间相册展示源码
2017/12/12 Javascript
在vue项目中使用Nprogress.js进度条的方法
2018/01/31 Javascript
VUE v-for循环中每个item节点动态绑定不同函数的实例
2018/09/26 Javascript
小程序按钮避免多次调用接口和点击方案实现(不用showLoading)
2020/04/15 Javascript
[13:38]2015国际邀请赛中国战队出征仪式
2015/05/29 DOTA
Python使用面向对象方式创建线程实现12306售票系统
2015/12/24 Python
Python之web模板应用
2017/12/26 Python
Python解析命令行读取参数--argparse模块使用方法
2018/01/23 Python
详解tensorflow训练自己的数据集实现CNN图像分类
2018/02/07 Python
Python 多线程搜索txt文件的内容,并写入搜到的内容(Lock)方法
2019/08/23 Python
python GUI库图形界面开发之PyQt5 UI主线程与耗时线程分离详细方法实例
2020/02/26 Python
次世代生活态度:Hypebeast
2018/07/05 全球购物
生物科学系大学生的自我评价
2013/12/20 职场文书
高职教师岗位职责
2013/12/24 职场文书
女生节标语
2014/06/26 职场文书
俞敏洪一分钟演讲稿
2014/08/26 职场文书
大学校园招聘会感想
2015/08/10 职场文书
七年级英语教学反思
2016/02/15 职场文书
react 项目中引入图片的几种方式
2021/06/02 Javascript
为什么MySQL 删除表数据 磁盘空间还一直被占用
2021/10/16 MySQL
python获取字符串中的email
2022/03/31 Python