1. 程式人生 > >JavaScript方法過載(一)

JavaScript方法過載(一)

最近在讀中文版一書,其中79頁(程式碼清單4.15)有一個函式過載的例子,感覺有點難懂.

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 ninjas = {
  values: ["Dean Edwards", "Sam Stephenson", "Alex Russell"]
};

addMethod(ninjas, "find", function(){
  return this.values;
}); //#0

addMethod(ninjas, "find", function(name){
  var ret = [];
  for (var i = 0; i < this.values.length; i++)
  if (this.values[i].indexOf(name) == 0)
  ret.push(this.values[i]);
  return ret;
}); //#1

addMethod(ninjas, "find", function(first, last){
  var ret = [];
  for (var i = 0; i < this.values.length; i++)
  if (this.values[i] == (first + " " + last))
  ret.push(this.values[i]);
  return ret;
}); //#2

assert(ninjas.find().length == 3,
"Found all ninjas");//#3
assert(ninjas.find("Sam").length == 1,
"Found ninja by first name");//#4
assert(ninjas.find("Dean", "Edwards").length == 1,
"Found ninja by first and last name");//#5
assert(ninjas.find("Alex", "Russell", "Jr") == null,
"Found nothing");//#6


按我的理解,應該是這個例子建立了三個閉包,每個閉包裡能訪問的是old和fn.

如下圖所示,每當呼叫ninjas.find時都會順著箭頭網上找相應引數個數的函式.
#3 中的呼叫將會從2個引數的函式開始->1個引數的函式->0個引數的函式
#4 中的呼叫將會從2個引數的函式開始->1個引數的函式
#5 中的呼叫將會從2個引數的函式開始
#6 中的呼叫將會從2個引數的函式開始->1個引數的函式->0個引數的函式->old不是函式
所以這種寫法雖然實現了不同引數個數的過載,但是沒有判斷引數的型別,而且也會使呼叫變慢.