2014-02-07 14 views
1

所以我在讀一本書,它使用此方法重載職能 -的Javascript重載函數

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

我有這幾個問題。

  1. 爲什麼當傳入的函數被調用時fn.length仍然在範圍內?不應執行addMethod導致fn超出範圍?
  2. 爲什麼參數不是引用匿名函數的參數屬性而不是fn函數的參數屬性? (這應該是我想?)
+0

請注意,只有當原始函數(如果有)具有不同數量的參數時,它纔會重載。很明顯,因爲JavaScript是無類型的,但值得一提,因爲一些其他(鍵入)語言允許重載相同的參數。結果是你不能'重載'一個不需要使用其所有參數的函數。 (x = x || 0; ...) – GameAlchemist

回答

2
  1. 參數「FN」在範圍上,因爲這是JavaScript的是如何工作的。這是匿名函數關閉的一部分。
  2. 創建的匿名函數是替換,原始函數綁定到屬性名稱爲「name」的對象。當被調用時,它通過查看arguments對象來檢查實際在特定調用上傳遞的參數。如果它看到傳遞的參數數量與「fn」函數中形式參數的數量相同,則它調用該函數。否則,它會調用前一個(「舊」)函數,如果它存在並且是一個函數。
    要理解的一個關鍵是函數實例的.length屬性爲您提供了聲明中的形式參數的數量。例如,該「addMethod」函數的.length將爲3

在JavaScript中關閉工作的方式花了我一段時間才真正「獲得」,因爲我很長一段時間都是C程序員。在這樣的語言中,函數調用局部變量(等)的空間被分配到堆棧中,當函數退出時,它們都從堆棧中彈出。 JavaScript不會那樣工作。

+0

所以fn在調用該函數時仍然存在,因爲在匿名函數的閉包中存在對fn的引用? – praks5432

+0

是的。從實際的函數調用到「addMethod」的參數(本質上是一個局部變量)將「基本上永遠停留在」周圍;只要該對象屬性(被替換的函數)仍然存在。因此每次調用新的替換函數都可以訪問它。 – Pointy