2016-02-10 145 views
1

我有以下蹦牀實現:瞭解蹦牀優化

function trampoline(f) { 
    while (f && f instanceof Function) { 

     f = f.apply(f.context, f.args); 

    } 
    return f; 
} 

和它的作品也同樣,例如是階乘:

function factorial(n) { 
    function recur(n, acc) { 
     if (n == 0) { 
      return acc; 
     } else { 
      return recur.bind(null, n-1, n*acc); 
     } 
    } 
    return trampoline(recur.bind(null, n, 1)); 
} 

的問題是,我不知道如何f.contextf.args是作爲參數傳遞的,那些屬性在蹦牀內部的重複函數中顯然無法找到,例如,當我嘗試訪問它們並嘗試訪問它們時。然後它會記錄undefined值。

這個特定實現的機制是傳遞函數的參數嗎?

+1

你能澄清什麼是使用蹦牀的優勢,而不是隻稱爲「香草」功能? –

+2

默認情況下,Javascript並未優化尾部遞歸,所以它很容易超出堆棧限制和排氣性能。 –

+0

你的代碼似乎工作正常,你能澄清這個問題嗎? –

回答

2

正如你所見,here,函數對象沒有名爲argscontext的屬性,這就是它們在控制檯日誌中顯示爲undefined的原因。在函數本身內部,您可以在argumentsthis對象中訪問這些值,但在中,它們在綁定函數(或未綁定函數)中從外部不可見。

您的代碼工作的原因是因爲如果函數與參數綁定,則會追加apply參數。當您使用bind函數時,您只能綁定上下文(this)或上下文和參數。如果綁定上下文和參數,那麼當您使用該函數時,您傳入的參數將被添加到參數列表的末尾。你的具體情況,你正在做的...

f = f.apply(undefined, undefined); 

...和f的結果參數是:

[...parametersWhenTheFunctionWasBound, undefined, undefined] 
+0

謝謝。我知道沒有這樣的屬性,因此這個問題。 因此,它可能是空的或未定義的,也可能是純函數調用,因爲該綁定只是將執行延遲爲準部分應用程序嘗試。 –

+0

參數數組不會被忽略,而是附加到綁定列表。 – Bergi

+0

謝謝@Bergi,我要更新答案 –