引言

最近在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的重载.再次感叹一下,这个方法真的很巧妙.真是漂亮又充满魅力的代码

如果觉得还可以,请点赞鼓励一下,谢谢!

原文发布时间为:2018年06月17日
原文作者:鲍康霖
本文来源: 掘金 如需转载请联系原作者

美丽的闭包,在js中实现函数重载相关推荐

  1. java js中 function函数报错_浅析JS中对函数function的理解(基础篇)

    正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定 ...

  2. Js中匿名函数的理解

    目录 1.js中匿名函数的N种写法 最常见的用法: 2.JavaScript 匿名函数及闭包 2.1 匿名函数 2.1.1 函数的定义 2.1.2 匿名函数的创建 2.2 闭包 2.3 举例 2.4 ...

  3. JS OOP -02 深入认识JS中的函数

    深入认识JS中的函数: 1.概述,认识函数对象 2.函数对象和其他内部对象的关系 3.将函数作为参数传递 4.传递给函数的隐含参数:arguments 5.函数的apply,call方法和length ...

  4. JS中Promise函数then的奥秘探究

    JS中Promise函数then的奥秘探究 Promise概述 Promise对象是CommonJS工作组提出的一种规范,目的是为异步操作提供统一接口. 那么,什么是Promises? 首先,它是一个 ...

  5. JS中的函数,Array对象,for-in语句,with语句,自定义对象,Prototype

    一)函数 A)JS中的函数的定义格式: function add(a,b) { var sum = a+b; document.write("两个数的和是:" + sum); // ...

  6. JS中的函数声明和函数表达式

    JS中的函数声明和函数表达式 1. 函数声明定义一个具有指定参数的函数 函数声明提升, 函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用 hoist ...

  7. 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 -- ...

  8. 谈谈JS中的函数劫持

    说到劫持,第一反应可能是什么不好的东西.函数劫持并不邪恶,关键是看使用的人.虽然这个概念在前端领域使用较少,但是在安全领域.自定义业务等场景下还是有一定的使用价值的.所以,这一篇文章将会和大家一起去了 ...

  9. Javascript中的函数重载-最佳做法

    用JavaScript伪造函数重载的最佳方法是什么? 我知道不可能像其他语言一样重载Javascript中的函数. 如果我需要两个函数一起使用foo(x)和foo(x,y,z) ,这是最佳/首选方式: ...

最新文章

  1. java 反射加实例化内部类
  2. java高级编程技巧
  3. HiKey960 开发板 android 编译
  4. Android之Timer和TimerTask的介绍
  5. Smart-Mall新零售商城系统
  6. JavaScript 编程精解 中文第三版 十五、处理事件
  7. 20-21-2网络管理quiz4
  8. 多线程环境下,HashMap 为什么会出现死循环?
  9. K Simple question (第十届山东理工大学ACM网络编程擂台赛 正式赛)
  10. 连连看消除算法和最佳路径推荐
  11. 计算机连接网络被限制,电脑连接wifi出现网络受限的解决方法
  12. Web项目中前端页面引用外部Js和Css的路径问题
  13. JCL新手入门学习教程(1) 2021-02-09
  14. 力扣-股票的资本损益
  15. 计算机中的无线网卡使用哪两种类型的扩展槽,第三章计算机每一种扩展槽的相关信息.ppt...
  16. NASA WIND卫星观测数据作图——origin
  17. 叶荣添给你的11条投机建议!
  18. 计算机网络技术(二)——数据通信
  19. 用于大数据的星际文件系统
  20. java 加载gif_android使用giflib加载gif

热门文章

  1. 企业云部署要如何选择IaaS PaaS和SaaS
  2. JS-用js的for循环实现九九乘法表以及其他算数题等
  3. 天冷了,大家如果有往年的不穿的衣服别扔,寄给需要的人好吗?
  4. JavaScript异步史
  5. rocketmq单机搭建
  6. 如何为 Python 添加远程调试能力而不修改系统代码
  7. 关于 0xCCCCCCCC
  8. NFX UNISTACK
  9. JEECG微云快速开发平台
  10. Spring 常用工具类