JS 利用参数个数进行函数重载

分享下《JavaScript忍者秘籍》中的一种函数重载方式

首先说一下函数的length属性:

全部的函数都有一个常常被忽略的属性,但却可让咱们了解函数的声明,那就是length属性。和arguments参数的length属性不一样的是,它表示函数声明时所需传入的形参数量。javascript

function makeNinja(name){};
//makeNinja.length === 1;复制代码

对一个函数,在参数方面,咱们能够肯定两件事情:java

  • 经过其length属性,能够知道声明了多少命名参数
  • 经过arguments.length,能够知道在调用时传入了多少参数

重载函数的方法:

/* * object为要绑定方法的对象 * name为绑定方法所用的属性名称 * fn为要绑定的方法 * */
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 ninja = {};
addMethod(ninja, 'whatever', function () {
  /* do something */
});
addMethod(ninja, 'whatever', function (a) {
  /* do something else */
});
addMethod(ninja, 'whatever', function (a, b) {
  /* yet something else */
});复制代码

分析

addMethod()第一次调用将建立一个新匿名函数,传入零个参数进行调用的时候将会调用该fn函数。因为此时ninja是一个新对象,因此这时候不用担忧以前建立的方法。数据结构

addMethod()第二次调用的时候,首先将以前的同名函数保存到一个变量old中,而后将新建立的匿名函数做为方法。新方法首先检查传入的函数个数是否为一,若是是,就调用刚才传入的fn函数;若是不是,则从新调用存储在old上的函数,从新调用该函数时,将会再次检查参数个数是否为零,继而调用参数个数为零的fn版本的函数。闭包

addMethod()第三次调用的时候,传入了一个接收两个参数的fn函数,而后判断逻辑相同:建立一个匿名函数做为方法,判断是否传入参数的个数为两个,若是是则调用两个参数的fn函数,不然继续判断参数个数是否为一。app

这种方法就像剥洋葱同样,每一层都检查参数个数是否匹配,若是不匹配的话,就进入上一层建立的函数。内部函数是经过闭包访问到old和fn的。函数

这是一个绝佳的技巧,由于这些函数实际上并无存储于任何典型的数据结构中,而是在闭包里做为引用进行存储。应该注意的是,在使用这个特定的技巧时,须要注意如下两点:ui

  • 这个重载只适用于不一样数量的参数,但并不区分类型、参数名或其余东西。这些才是咱们常常想作的事情
  • 这个重载方法会有一些函数调用的开销
相关文章
相关标签/搜索