2012-11-11 38 views
3

我正在閱讀雄辯的Javascript和我有困難的時候瞭解下面的例子。任何人都可以做一個逐行的解釋?具體來說,我很困惑,爲什麼第一個循環從一開始,以及爲什麼push方法在knownArgs和arguments上都被使用。我知道這與「部分應用」有關,但希望更詳細地解釋逐行發生的事情。部分應用程序 - 雄辯的Javascript

var op = { 
"+": function(a,b){return a + b;} 
}; 

function partial(func) { 
var knownArgs = arguments; 

return function() { 
    var realArgs = []; 

    for (var i=1; i<knownArgs.length; i++) 
    realArgs.push(knownArgs[i]); 

    for (var i=0; i<arguments.length; i++) 
    realArgs.push(arguments[i]); 

    return func.apply(null, realArgs); 
}; 
} 

map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]); 
+2

我花了_literally_ 2秒找到這個http://www.drdobbs.com/open-source/currying-and-partial-functions-in-javasc/ 231001821。閱讀所有關於它的內容。 – elclanrs

+0

謝謝,我會閱讀。有希望的我仍然可以得到上述的解釋。 – KMcA

+0

我用更多的解釋更新了我的答案。碰巧,我只是在幾個星期前教了幾個JavaScript類,其中有些例子與此非常相似:-) – Pointy

回答

2

knownArgs變量保留arguments的值的副本,與調用partial()時的值一樣。該呼叫返回另一函數,並在該代碼arguments是一個完全不同的列表—它們是傳遞給該返回的函數的參數。換句話說:

var p = partial(someFunction,「hello」,「world」);

當調用p()時,knownArgs將會是「你好」和「世界」(也是someFunction,但請注意第一個循環從1開始)。如果撥打p()看起來像這樣:

p(「how」,「are」,「you」);

那麼它會先推「你好」和「世界」到realArgs列表(從knownArgs),然後傳遞到p()三個參數,從arguments

編輯 —一步一步擊穿的map(partial(op["+"], 1), [0, 2, 4, 6, 8, 10]);是如何評估:

  1. 首先,op["+"]必須被評估。我猜它返回一個函數,大概是這樣的:

    function add(a, b) { 
        return a + b; 
    } 
    
  2. 那「添加」功能和價值1傳遞給partial()。因此內部partial()arguments僞陣列看起來像

    [ add, 1 ] 
    

    也就是說,第一個參數是從op["+"]「添加」功能,第二個是該值1partial()在返回匿名函數之前唯一真正做的是將arguments保存爲knownArgs。必須這樣做,因爲奇怪的arguments僞變量是總是在每次函數調用時都會分配一個新值。它被保存在這裏,以便匿名函數中的代碼可以在以後訪問它。

  3. 現在,使用從partial()返回的匿名函數以及偶數數組,我們將其稱爲map()。這大概功能看起來是這樣的(我沒有書):

    function map(fn, list) { 
        var i, result = []; 
        for (i = 0; i < list.length; ++i) { 
        result.push(fn(list[i])); 
        } 
        return result; 
    } 
    

    裏面map(),那麼,第一個參數是從先前調用返回partial()匿名函數。這個功能是做什麼的?那麼,它將來自原始partial()呼叫— 的參數與第一個參數 —與傳遞給它的參數結合起來。 map()函數只傳遞一個參數,因此每次調用匿名函數時生成的參數列表將爲值1傳遞給partial(),然後在每次迭代中從列表中獲取一個不同的偶數。

一個簡單的例子是考慮當你調用會發生什麼:

partial(op["+"], 1)(2); 

也就是說,如果你打電話partial(),然後立即使用它的返回值(匿名函數)。效果會與調用:

add(1, 2); 
+0

謝謝。我理解你的答案,它與上面的代碼有關係。我對部分應用的概念似乎還很模糊。除了elclanrs發佈的鏈接之外,你是否對任何完全陌生的編程人員的解釋有任何建議? – KMcA

+0

@KMcA對於新編程的人來說,這是一些相當奇特的東西:-)儘管這並不難;這只是一套你必須與之合作的想法,才能熟悉它。從JavaScript開始是一個好主意,因爲這是一個用這種概念玩相對友好的環境。關鍵是,在JavaScript和其他一些語言中,函數不僅僅是代碼塊,還包括對象,並且可以像對待任何其他對象一樣處理。它們只是具有可作爲函數調用的附加功能! – Pointy

+0

我一直在考慮將此作爲本書的一個停止點,因爲它似乎在學習一些高級概念,但我知道在哪裏接近實際使用這些概念的地方。當你說「花哨的東西」時,你會說我可能會更好地支持並做一些編程書籍/在線課程的介紹嗎?例如,我坐在桌子上的「學習計劃」,但是討厭停止雄辯的Javascript而沒有完成。 – KMcA

1

第一個循環開始於一個,而不是零,因爲knownArgs[0]包含的功能,而不是它的參數。

push將單個元素附加到數組。這是構建數組的一個相當常見的方法。

var realArgs = []; 

    for (var i=1; i<knownArgs.length; i++) 
    realArgs.push(knownArgs[i]); 

    for (var i=0; i<arguments.length; i++) 
    realArgs.push(arguments[i]); 

將創建從knownArgsarguments串接一個新的數組。 knownArgs保存了curried參數和函數(不附加到realArgs),arguments是函數在調用時提供的參數。