无法理解函数重载

时间:2014-05-17 15:40:43

标签: javascript

我很难从“Javascript Ninja的秘密”一书中把握这个例子。

这个概念是你有一个addMethod函数,它允许你将同一个方法的多个版本传递给一个对象,区别在于这些方法接受的参数数量,它们处理这些参数的内容。

我没有得到这背后的“机制”。在检查器中,我只看到第一种方法,但是当我使用不同的参数运行find方法时,它仍然设法使用它的正确变体。但是怎么样?在使用三个版本运行addMethod后,这些方法如何仍然可用? 你能帮我理解一下吗?

将方法绑定到对象的函数:

addMethod = function(object, name, fn) {
  var old;
  old = object[name];
  return object[name] = function() {
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments);
    } else if (typeof old === 'function') {
      return old.apply(this, arguments);
    }
  };
};

然后你可以分配相同的函数名作为对象的属性,如下所示:

addMethod(ninjas, 'find', function() {
  return this.values;
});

addMethod(ninjas, 'find', function(name) {
  var ninja, _i, _len, _ref, _results;
  _ref = this.values;
  _results = [];
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    ninja = _ref[_i];
    if (ninja.indexOf(name) !== -1) {
      _results.push(ninja);
    }
  }
  return _results;
});

addMethod(ninjas, 'find', function(first, last) {
  var ninja, _i, _len, _ref, _results;
  _ref = this.values;
  _results = [];
  for (_i = 0, _len = _ref.length; _i < _len; _i++) {
    ninja = _ref[_i];
    if (ninja === ("" + first + " " + last)) {
      _results.push(ninja);
    }
  }
  return _results;
});

2 个答案:

答案 0 :(得分:3)

每次重载函数时,都会使用旧函数并将其替换为检查要使用哪个重载的函数。

添加第一个函数后,您的代码(粗略地)与:

相同
ninjas.find = function(){
  if (arguments.length === 1) {
    // code for first overload
  }
}

添加第二个函数后,您的代码与:

相同
ninjas.find = function(){
  if (arguments.length === 2) {
    // code for second overload
  } else {

    if (arguments.lenght === 1) {
      // code for first overload
    }

  }
}

每次添加另一个重载时,都会在前一个代码周围添加另一级别的检查。

答案 1 :(得分:1)

addMethod = function(object, name, fn) {
  var old;
  old = object[name];
  return object[name] = function() {
    if (fn.length === arguments.length) {
      return fn.apply(this, arguments);
    } else if (typeof old === 'function') {
      return old.apply(this, arguments);
    }
  };
};

让我们开始吧:

object[name] = function ()为对象分配一个函数。

例如:

ninjas["find"] = function()

然后它使用第一个匹配将命名的参数数量(fn.length)与传入的参数数量(arguments.length)进行比较。这样它就可以确定需要调用哪个函数。

如果第一个条件不满足,则检查旧函数的类型。如果它是一个函数,那么它只是将参数应用于旧函数。

fn.length指的是传递的最外层函数。

&安培;

arguments.length指的是最内部函数长度的参数。

那么压倒一切有效吗?

正如您所看到的,我们每次调用addMethod时都会将函数引用到名为old的变量。然后根据if条件结果,它将覆盖上一个函数与较新的函数。

如果我们没有匹配变量的旧函数,它将返回undefined。

例如:

-----------------------------------------------------------------------
function                            -       fn.length == arguments.length
------------------------------------------------------------------------
ninjas.find()                       -        (0 == 0), uses `function ()`
ninjas.find("Rias")                 -        (1 == 1), uses `function (name)`
ninjas.find("Mohamed", "Rias")      -        (2 == 2), uses `function (first, last)`
ninjas.find("Mohamed", "Rias", "A") -        (? == 3), no match, returns `undefined`