2014-01-14 90 views
5

我在"Hey Underscore, You're Doing it Wrong" JavaScript talk(4:15)中遇到過這種語法。我想知道這意味着什麼。當你在JavaScript中的函數聲明中聲明.autoCurry()會發生什麼?

var add = function(x,y){ 
    return x + y; 
}.autoCurry();//What is happening in this line. 
+3

,這些傳言是真的*先進的材料。 – Pointy

+1

是的,在4:12那次演講中,他明確表示他已將「autoCurry」添加到函數原型中。 – Pointy

+0

請注意,前段時間'autoCurry()'已被重命名爲'curry()'。 – falconepl

回答

0

在JavaScript中,函數實例表達式:

function name(arg1, arg2, ...) { /* code */ } 

創建到功能對象的引用的功能和結果。因此,.autoCurry()是對該對象屬性的引用,該屬性顯然被認爲是一個函數。

我懷疑你正在看的例子有一些其他代碼,將「autoCurry」添加到函數原型對象。這樣,每個函數對象都可以作爲「autoCurry」屬性訪問該函數。

+0

感謝您的回答 – Taimoor

1

好了,我不能告訴你,究竟是什麼autoCurry是做......但是我可以告訴大家的是:

  1. 他們已經修改了功能構造函數的原型Function.prototype.autoCurry = function() { };
    您在該頁面上創建的每個新功能現在都可以作爲其屬性之一訪問此方法。
    var myFunc = function() { return true; }; myFunc.autoCurry();

  2. 你可以鏈接語句在一起,愉快地在JS中。
    var myObj = { run : function() { } }, result = myObj.run();是一樣的
    var result = { run : function() { } }.run();,只要你不在乎myObj之後。

所以:

  1. 您正在創建一個功能,只要它的創建,你在其上運行的方法,並且該方法的return語句(在過去的事情鏈)正被保存到變量中。

現在,currying是一種接受函數並將其包裝在其他函數中的形式,它允許您僅使用所需參數的一部分來調用函數。

function add_two_numbers = function(x,y){return x + y; }

柯里將允許你這樣做:

var save_x_for_later = curry(add_two_numbers), 
    save_y_and_add = save_x_for_later(3), 
    result = save_y_and_add(5); 

result; // 8 

至於你的新頭銜,得到的答覆是: 你會在你的臉上拋出一個錯誤: .autoCurry()沒有的一部分語言。 它被寫,手,裝上Function.prototypeFunction.prototype.autoCurry = function() { }

我能進入討好的實現,但還有很多東西要繞到你的頭,如果你還沒有做太多的函數式編程,或者「lambda」是頭部劃痕術語。

+0

感謝Norguard的回答。非常豐富... – Taimoor

8

首先讓我們看看咖喱和自動排水器實際上做了什麼。我註釋了這兩個函數的來源(最初發現於吳。JS庫):

//// 
    // Type: 
    // 
    // ((a,b, ... c) -> d) -> a -> b -> ... -> c -> d 
    // 
    // Example: 
    // 
    // function add(a, b) { return a + b; } 
    // add2 = curry(add, 2) 
    // add2(3) 
    // // 5 
    function curry(fn /* variadic number of args */) { 
    var args = Array.prototype.slice.call(arguments, 1); 
    function f() { return fn.apply(this, args.concat(toArray(arguments))); } 
    return f; 
    } 

    //// 
    // Example: 
    // 
    // function add(a, b) { return a + b; } 
    // autoCurry(add); 
    // 
    // add(2)(3)      
    // // 5 
    // 
    // add(2, 3) 
    // // 5 
    function autoCurry(fn, numArgs) { 
    numArgs = numArgs || fn.length; 
    function f() { 
     if (arguments.length < numArgs) 
     { 
     return numArgs - arguments.length > 0 ? 
     autoCurry(curry.apply(this, [fn].concat(toArray(arguments))), 
     numArgs - arguments.length) : 
     curry.apply(this, [fn].concat(toArray(arguments))); 
     } 
     else 
     { 
     return fn.apply(this, arguments); 
     } 
    } 
    f.toString = function() { return fn.toString(); }; 
    f.curried = true; 
    return f; 
    } 

換句話說,

autoCurry(add) 

注意到一個函數,它有兩個參數,並返回一個數,並返回一個函數A採用單個參數,並返回的功能B.其中B是帶一個參數,並返回一個數的函數:

add(1) -> returns a function add1(), which itself takes a single argument. 

接着,在通話揚聲器執行以下操作:

Function.prototype.autoCurry = function(n) { return autoCurry(this, n); } 

這只是應用autoCurry法任何給定函數(個體經營),以便

var add = function(x,y){ 
    return x + y; 
}.autoCurry(); 

具有同樣的效果:如果你在JavaScript的初學者

var add = function(x,y) { return x + y; }; 
add = autoCurry(add) 
+0

你需要在這裏定義一個'toArray'函數。正如你所說的那樣,在定義的'curry'函數中,即'function toArray(args){return [] .slice.call(args); }' –

相關問題