javascript - 看不懂这个 Javascript 函数(函数重载)

标签 javascript function methods overloading

我在阅读 Secrets of Javascript Ninja 时遇到了一个我无法完全理解的示例。这个例子以前也被其他用户引用过,但是他们的疑惑和我的不一样。这是示例:

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 */ });

我对作用域、闭包和 apply() 的使用有深入的了解。我的疑惑是:

  • fn.length 将返回 fn 中定义的参数个数。 arguments.length 会返回哪些参数的数量?已经存在的功能?
  • 但如果是这样,并且它们匹配,为什么它会应用新功能而不是现有功能?
  • 如果 arguments.length 返回给定函数的编号,那么它们什么时候会不同?
  • 我添加了 10 个方法,从无参数开始,每次增加方法的数量,添加第 10 个方法后,我调用了无参数方法,它在哪里“存储”了第一个函数?
  • 我不明白old 在这里的用法。

我可能没有能回答所有问题的关键概念。请随意给我一个解释,而不是单独回答问题。

最佳答案

fn.length will return the number of parameters defined in fn. Will arguments.length return the number of which arguments? The already existing function's?

没有。 arguments 是一个类似于数组的局部变量,可在函数内部使用。它包含传递给函数的参数数量。

你的其余问题可以通过解决这个问题来回答:

I add 10 methods, starting with no parameters and increasing the number of them each time, after adding the 10th method, I call the method with no parameters, where did it 'store' the first function?

逐个查看 addMethod 方法可能会有所帮助:

function addMethod(object, name, fn) {

  var old = object[name];
  // Get the old function corresponding to this name. Will be "undefined"
  // the first time "addMethod" is called.


  object[name] = function(){
  // Now, assign object[name] to a new function.
  // The critical part of this function is that "old" is captured inside of
  // this function and will be available any time the function is called.

       if (fn.length == arguments.length)
       // if the number of parameters belonging to the function we've added
       // matches what was passed in, call "fn"
          return fn.apply(this, arguments)

       else if (typeof old == 'function')
       // Otherwise if there's another function with this name
       // call it instead.
          return old.apply(this, arguments);

    };
}

因此,让我们在您的示例中每次调用 addMethod 并检查 fnold 的值。您可以将其组织为相互堆叠的函数的方式,利用 old 的范围。

addMethod(ninja,'whatever',function(){ /* do something */ });
// old === undefined

addMethod(ninja,'whatever',function(a){ /* do something else */ });
// old === function #1

addMethod(ninja,'whatever',function(a,b){ /* yet something else */ });
// old === function #2

在调用 addMethod 三次之后 ninja.whatever 指的是一个函数,如果可能的话调用函数 #3,然后调用 old 函数(函数 #2),如果参数与函数 #3 的参数列表长度不匹配。

所以在视觉上,你可以这样想:

function #3 (a,b)
function #2 (a)
function #1 ()

每个函数的引用指向它下面的函数。

现在让我们看看当您调用 ninja.whatever() 时会发生什么。此函数位于我们堆栈的“底部”。

  1. 当前与whatever 关联的函数是函数#3。调用函数 #3 时,fn.length != arguments.length,因此执行 old(函数 #2)。
  2. 现在我们正在执行功能#2。同样,当调用函数 #2 时,fn.length != arguments.lengthold(函数 #1)被执行。
  3. 最后,函数 #1 被执行。这次 fn.length == arguments.length 函数被调用。

关于javascript - 看不懂这个 Javascript 函数(函数重载),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30989600/

相关文章:

javascript - 用纯 Javascript 交换默认选择的选择选项

javascript - 在背景上播放音乐/声音的方法

java - 泛化二叉树遍历的 Action ?

c++ - 在 Win32 C++ 中调用未导出的函数

c - 如何防止从 C 保存的文件末尾出现额外的空格?

javascript - 如何使用动态数据循环遍历链式方法?

c++ - C语言中delay()是什么?是系统功能吗?

javascript - Jquery php实时搜索文本在搜索栏中消失

javascript - 当鼠标向下移动时滚动/拖动 div 中的值

c# - 在变量中引用函数?