您好,登錄后才能下訂單哦!
這篇文章主要為大家展示了“JS中的柯里化Currying怎么用”,內容簡而易懂,條理清晰,希望能夠幫助大家解決疑惑,下面讓小編帶領大家一起研究并學習一下“JS中的柯里化Currying怎么用”這篇文章吧。
柯里化將多參數函數轉換為一元(單參數)函數。
柯里化函數一次接受多個參數。所以如果你有
greet = (greeting, first, last) => `${greeting}, ${first} ${last}`; greet('Hello', 'Bruce', 'Wayne'); // Hello, Bruce Wayne
可以寫成這種形式
curriedGreet = curry(greet); curriedGreet('Hello')('Bruce')('Wayne'); // Hello, Bruce Wayne
正確的使用“柯里化”是因為某些curry
函數在使用上更加靈活。Currying 在理論上很棒,但是在 JavaScript 中為每個參數調用一個函數會很累。
Ramda 的 curry
函數可以讓你curriedGreet
像這樣調用:
// greet requires 3 params: (greeting, first, last) // these all return a function looking for (first, last) curriedGreet('Hello'); curriedGreet('Hello')(); curriedGreet()('Hello')()(); // these all return a function looking for (last) curriedGreet('Hello')('Bruce'); curriedGreet('Hello', 'Bruce'); curriedGreet('Hello')()('Bruce')(); // these return a greeting, since all 3 params were honored curriedGreet('Hello')('Bruce')('Wayne'); curriedGreet('Hello', 'Bruce', 'Wayne'); curriedGreet('Hello', 'Bruce')()()('Wayne');
請注意,你可以選擇一次性給出多個參數。此實現在編寫代碼時更有用。
如上所示,你可以在沒有參數的情況下永遠調用此函數,并且它將始終返回一個需要剩余參數的函數。
const curry = (f, arr = []) => (...args) => ((a) => (a.length === f.length ? f(...a) : curry(f, a)))([...arr, ...args]);
讓我們一起重構和欣賞它。
我還在debugger
Chrome 開發人員工具中添加了一些語句來檢查它。
curry = (originalFunction, initialParams = []) => { debugger; return (...nextParams) => { debugger; const curriedFunction = (params) => { debugger; if (params.length === originalFunction.length) { return originalFunction(...params); } return curry(originalFunction, params); }; return curriedFunction([...initialParams, ...nextParams]); }; };
粘貼greet
并curry
進入您的控制臺。然后進入curriedGreet = curry(greet)
并開始瘋狂。
檢查我們看到的兩個參數,originalFunction
并且greet
默認initialParams
為空數組,因為我們沒有提供它。移動到下一個斷點,哦等等……就是這樣。
是的!curry(greet)
只返回一個需要 3 個以上參數的新函數。在控制臺中輸入curriedGreet
以查看我在說什么。
當你玩完這個之后,讓我們變得更瘋狂一點,然后做sayHello = curriedGreet('Hello')
.
在繼續之前,在控制臺中輸入originalFunction
和。initialParams
請注意,即使我們在一個全新的函數中,我們仍然可以訪問這兩個參數?這是因為從父函數返回的函數享有其父函數的作用域。
在父函數傳遞之后,他們將參數留給孩子使用。有點像現實生活中的繼承。
curry
最初給出originalFunction
,initialParams
然后返回一個“子”函數。這兩個變量還沒有被處理掉,因為也許那個孩子需要它們。如果他不這樣做,那么這個范圍就會被清理干凈,因為當沒有人提到你時,那就是你真正死去的時候。
檢查nextParams
并看到它是['Hello']
……一個數組?但我以為我們說curriedGreet(‘Hello’)
,不是curriedGreet(['Hello'])
!
正確:我們調用curriedGreet
了 with 'Hello'
,但是多虧了rest 語法,我們變成 'Hello'
了['Hello']
.
curry
是一個通用函數,可以提供 1、10 或 10,000,000 個參數,因此它需要一種方法來引用所有參數。使用類似的 rest 語法捕獲一個數組中的每個參數,使curry
' 的工作更容易。
讓我們跳到下debugger
一條語句。
您可能已經注意到第 12 行實際上在debugger
第 6 行的語句之前運行。如果不是,請仔細查看。我們的程序在第 5 行定義了一個調用函數curriedFunction
,在第 12 行使用它,然后我們debugger
在第 6 行點擊了該語句。curriedFunction
調用的是什么?
[...initialParams, ...nextParams];
呸呸呸。查看params
第 5 行,您會看到['Hello']
. 兩者initialParams
和都是數組,所以我們使用方便的擴展運算符nextParams
將它們展平并組合成一個數組。
這就是好事發生的地方。
第 7 行說“如果params
和originalFunction
長度相同,請greet
使用我們的參數調用,我們就完成了。” 這使我想起…
這就是curry
它的魔力!這就是它決定是否要求更多參數的方式。
在 JavaScript 中,函數的 .length
屬性告訴你它需要多少個參數。
greet.length; // 3 iTakeOneParam = (a) => {}; iTakeTwoParams = (a, b) => {}; iTakeOneParam.length; // 1 iTakeTwoParams.length; // 2復制代碼
如果我們提供的和預期的參數匹配,我們很好,只需將它們交給原始函數并完成工作!
但是在我們的例子中,參數和函數長度是不一樣的。我們只提供了‘Hello’
,所以params.length
是 1,并且originalFunction.length
是 3 因為greet
需要 3 個參數:greeting, first, last
。
好吧,由于該if
語句的計算結果為false
,代碼將跳到第 10 行并重新調用我們的主curry
函數。它重新接收greet
,這一次,'Hello'
并重新開始瘋狂。
這就是遞歸,我的朋友們。
curry
本質上是一個無限循環的自調用,參數饑渴的函數,直到他們的客人滿了才會休息。熱情好客。
與以前相同initialParams
的參數,除了['Hello']
這次。再次跳過以退出循環。在控制臺中輸入我們的新變量,sayHello
. 這是另一個函數,仍然期待更多參數,但我們正在變得更加溫暖......
讓我們把火調大sayHelloToJohn = sayHello('John')
。
我們又在第 4 行了,而且nextParams
是['John']
。跳到第 6 行的下一個調試器并檢查params
:它是['Hello', 'John']
!?
因為請記住,第 12 行說“嘿curriedFunction
,他'Hello'
上次和‘John’
這次都給了我。把他們兩個都帶進這個陣法[...initialParams, ...nextParams]
。”
現在curriedFunction
再次將length
這些params
與進行比較originalFunction
,因為2 < 3
我們移動到第 10 行并curry
再次調用!當然,我們傳遞greet
了我們的 2 個參數,['Hello', 'John']
我們已經很接近了,讓我們完成這一切,并得到完整的問候!
sayHelloToJohnDoe = sayHelloToJohn('Doe')
我想我們知道接下來會發生什么。
greet
得到他的參數,curry
停止循環,我們收到了我們的問候:Hello, John Doe
.
多玩一些這個功能。嘗試一次提供多個參數或不提供參數,隨心所欲地瘋狂。curry
查看在返回預期輸出之前必須遞歸多少次。
curriedGreet('Hello', 'John', 'Doe'); curriedGreet('Hello', 'John')('Doe'); curriedGreet()()('Hello')()('John')()()()()('Doe');
以上是“JS中的柯里化Currying怎么用”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業資訊頻道!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。