美丽的闭包,在js中实现函数重载
引言
最近在js的学习中,看到了函数重载的问题,一开始,只看到了实现代码,看着代码冥思苦想了半个小时,总算是理清了其实现的原理,也为其实现的巧妙感到赞叹,也是在自己搞懂原理之后,去网络上搜索了下,才知道,这个实现方法是jQuery作者John Resig在《JavaScript忍者秘籍》中对函数重载的实现,设计十分的巧妙,写下此文,给大家做一个分享
什么是函数的重载
重载,简单说,就是函数或者方法有相同的名称,但是参数列表不相同的情形,这样的同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
先来看看效果
function addMethod (obj, name, fn) {var old = obj[name];obj[name] = function () {if (fn.length === arguments.length) {return fn.apply(this, arguments)} else if (typeof old === 'function') {return old.apply(this, arguments)}}}var person = {userName: 'bear鲍的小小熊'}addMethod(person, 'show', function () {console.log(this.userName + '---->' + 'show1')})addMethod(person, 'show', function (str) {console.log(this.userName + '---->' + str)})addMethod(person, 'show', function (a, b) {console.log(this.userName + '---->' + (a + b))})person.show() person.show('bkl')person.show(10, 20)
输出的结果
//bear鲍的小小熊---->show1//bear鲍的小小熊---->bkl//bear鲍的小小熊---->30
我们给一个对象添加了一个show方法,这个show方法,每次传入的参数不一样,它进行的处理也是不一样的
为了后文更好理解,这里先对fn.length这个大家可能陌生的属性做个解释,先看下面的代码
function fn(a,b,c) {}
fn.length // 3
function fn(a,b,c,d) {}
fn.length // 4
fn.legnth,是函数fn在定义时,形参的个数.好了,让我们继续往下讲吧
这个addMethod函数,简单的来说,就是给一个对象添加一个指定name的方法fn(后文中为了方便大家理解,我们就以这个例子中的show来指代这个name吧),他利用了闭包,通过变量old,将每次传进来的fn给保存起来,我们每次调用这个show方法,根据传入的参数的不同,我们的代码可能多次通过old来找到之前传入的fn函数
下面我们来对这个方法进行解析为了看的更加直观,我们对之前的addMethod的函数做一点小小的改造,其实就是加入了一个console.log(),可以方便我们理解,函数的执行过程
function addMethod (obj, name, fn) {var old = obj[name];obj[name] = function () {console.log(1) //打印1if(fn.length === arguments.length){console.log(2) // 打印2return fn.apply(this,arguments);}else if(typeof old === 'function'){console.log(3) // 打印3return old.apply(this,arguments);}}}addMethod(person, 'show', function () {console.log(this.userName + '---->' + 'show1')})addMethod(person, 'show', function (str) {console.log(this.userName + '---->' + str)})addMethod(person, 'show', function (a, b) {console.log(this.userName + '---->' + (a + b))})
下面,我们看一下person.show方法,在不传参,传了一个参数,与传了两个参数时,函数执行的具体过程,
- person.show(10, 20)
1
2
bear鲍的小小熊---->30
可见,传入两个参数的时候,只打印了一个1,一个2,就将对应的执行函数执行了.其实这个时候person.show函数的作用域内 fn为下面这个函数
function (a, b) {console.log(this.userName + '---->' + (a + b))}
- person.show('bkl')
1
3
1
2
bear鲍的小小熊---->bkl
传入一个参数的时候执行结果为 1 --> 3 --> 1 --> 2 --> 处理后的结果 在这个过程中由于执行person.show方法时,fn.length === 2,而我们传入的参数为1个,那么函数会执行到
return old.apply(this,arguments);
这个时候的old是什么呢?这个时候的old其实是在下面这个函数执行之前的person.show方法
addMethod(person, 'show', function (a, b) {console.log(this.userName + '---->' + (a + b))})
执行之后person.show函数作用域内的fn函数也就是下面这个方法
function (str) {console.log(this.userName + '---->' + str)}
- person.show()
1
3
1
3
1
2
bear鲍的小小熊---->show1
上面的也是同理,根据这个输出结果,不难看出,当没有传递参数时,通过闭包的old变量,我们可以一路向上找到这个方法.
function () {console.log(this.userName + '---->' + 'show1')}
结语
就这样,我们通过闭包中的old变量,将对不传参数,传了一个参数和传了两个参数进行区别处理的方法给串联了起来.实现了js的重载.再次感叹一下,这个方法真的很巧妙.真是漂亮又充满魅力的代码
如果觉得还可以,请点赞鼓励一下,谢谢!
本文来源: 掘金 如需转载请联系原作者
美丽的闭包,在js中实现函数重载相关推荐
- java js中 function函数报错_浅析JS中对函数function的理解(基础篇)
正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...
- Js中匿名函数的理解
目录 1.js中匿名函数的N种写法 最常见的用法: 2.JavaScript 匿名函数及闭包 2.1 匿名函数 2.1.1 函数的定义 2.1.2 匿名函数的创建 2.2 闭包 2.3 举例 2.4 ...
- JS OOP -02 深入认识JS中的函数
深入认识JS中的函数: 1.概述,认识函数对象 2.函数对象和其他内部对象的关系 3.将函数作为参数传递 4.传递给函数的隐含参数:arguments 5.函数的apply,call方法和length ...
- JS中Promise函数then的奥秘探究
JS中Promise函数then的奥秘探究 Promise概述 Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口. 那么,什么是Promises? 首先,它是一个 ...
- JS中的函数,Array对象,for-in语句,with语句,自定义对象,Prototype
一)函数 A)JS中的函数的定义格式: function add(a,b) { var sum = a+b; document.write("两个数的和是:" + sum); // ...
- JS中的函数声明和函数表达式
JS中的函数声明和函数表达式 1. 函数声明定义一个具有指定参数的函数 函数声明提升, 函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用 hoist ...
- js中trim函数_30天中的30个Excel函数:03 – TRIM
js中trim函数 Yesterday, in the 30XL30D challenge, we took a poke at the lazy brother-in-law function -- ...
- 谈谈JS中的函数劫持
说到劫持,第一反应可能是什么不好的东西.函数劫持并不邪恶,关键是看使用的人.虽然这个概念在前端领域使用较少,但是在安全领域.自定义业务等场景下还是有一定的使用价值的.所以,这一篇文章将会和大家一起去了 ...
- Javascript中的函数重载-最佳做法
用JavaScript伪造函数重载的最佳方法是什么? 我知道不可能像其他语言一样重载Javascript中的函数. 如果我需要两个函数一起使用foo(x)和foo(x,y,z) ,这是最佳/首选方式: ...
最新文章
- java 反射加实例化内部类
- java高级编程技巧
- HiKey960 开发板 android 编译
- Android之Timer和TimerTask的介绍
- Smart-Mall新零售商城系统
- JavaScript 编程精解 中文第三版 十五、处理事件
- 20-21-2网络管理quiz4
- 多线程环境下,HashMap 为什么会出现死循环?
- K Simple question (第十届山东理工大学ACM网络编程擂台赛 正式赛)
- 连连看消除算法和最佳路径推荐
- 计算机连接网络被限制,电脑连接wifi出现网络受限的解决方法
- Web项目中前端页面引用外部Js和Css的路径问题
- JCL新手入门学习教程(1) 2021-02-09
- 力扣-股票的资本损益
- 计算机中的无线网卡使用哪两种类型的扩展槽,第三章计算机每一种扩展槽的相关信息.ppt...
- NASA WIND卫星观测数据作图——origin
- 叶荣添给你的11条投机建议!
- 计算机网络技术(二)——数据通信
- 用于大数据的星际文件系统
- java 加载gif_android使用giflib加载gif