javascript添加功能脚本 - 有人可以解释一下吗?

时间:2016-02-01 13:36:02

标签: javascript javascript-objects

我在一个应该按对象创建函数的示例中查找这段代码。 据我所知,它也可以在对象上创建相同功能的重载。

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

该对象应该包含3个任何函数的重载。

问题我不明白addMethod函数:

据我所知,我们将最后一个函数存储在old中。 我们用这种方式创建一个闭包吗?用匿名函数?

所以执行这行代码:

 else if (typeof old == 'function')
            return old.apply(this, arguments);

它将递归调用之前定义的所有函数,直到匹配?

有人可以解释一下吗?

感谢

3 个答案:

答案 0 :(得分:1)

  

但不明白我们用新匿名函数存储的内容

代码的要点是根据传递的参数数量调用函数的不同版本。

如果您没有在某处存储旧版本的功能,那么就无法调用它。

  

为什么我们将fn.lenth测试为参数长度(不是args.arguments是3总是?(addMethod))

函数的length属性是预期参数的数量。即创建它的函数声明或函数表达式的()之间的标识符数。

length对象的arguments属性是实际传递给它的参数数量。

见这个例子:

function myFunction(foo, bar) {
  document.body.appendChild(
    document.createElement("br")
  );
  document.body.appendChild(
    document.createTextNode(
      "The function was called with " + arguments.length + " arguments"
    )
  );
}


document.body.appendChild(
  document.createTextNode(
    "The length of the function is " + myFunction.length
  )
);

myFunction();
myFunction("a", "b", "c", "d", "e");

答案 1 :(得分:0)

好的,我会尝试用例子来解释,想象一下:

var obj = {
  foo: function() {}
};

var foo2 = function(arg) {};

调用addMethod(obj, 'foo', foo2)将使用创建的匿名函数替换obj.foo。是的,这是一个封闭,在fn内部始终是foo2

下次调用obj.foo时,将调用匿名函数。在闭包内fn(等于foo2)将使length等于foo2期望接收的参数数量,arguments.length等于实际收到的参数数量

obj.foo(1);

在这种情况下,fn.lengtharguments.length都是1,然后使用我发送的参数调用foo2

obj.foo();

在这种情况下,fn.length为1但arguments.length为0 闭包将检查是否有old函数并调用它传递参数(在这种情况下没有)。

如果再次使用新函数调用addMethod,它将以递归方式查找,直到找到一个接收相同数量的参数的函数或者直到它到达最后一个函数为止。

var foo3 = function(arg1, arg2) {};
addMethod(obj, 'foo', foo3);

obj.foo(1, 2); // will trigger foo3
obj.foo(1); // will trigger foo2
obj.foo(); // will trigger the original foo

添加具有相同数量参数的函数将使旧的函数永远不会被再次调用。

var foo4 = function(arg) {};
addMethod(obj, 'foo', foo4);

obj.foo(1); // will trigger foo4

答案 2 :(得分:0)

  

是不是args.arguments总是3?

不,arguments.length表达式最直接位于内部函数表达式object[name] = function(){ ... }内,而不是addMethod。因此,arguments引用传递给object[name]上定义的函数的参数(即新定义的函数)。