這篇文章帶大家快速了解一下Javascript中的柯里化(Currying),有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。
柯里化將多參數函數轉換為一元(單一參數)函數。 【相關推薦:javascript學習教學】
#柯里化函數一次接受多個參數。所以如果你有
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)
並開始瘋狂。
在第2 行暫停
#檢查我們看到的兩個參數,originalFunction
並且greet
預設initialParams
為空數組,因為我們沒有提供它。移動到下一個斷點,哦等等……就是這樣。
是的! curry(greet)
只傳回一個需要 3 個以上參數的新函數。在控制台中輸入curriedGreet
以查看我在說什麼。
當你玩完這個之後,讓我們變得更瘋狂一點,然後做sayHello = curriedGreet('Hello')
.
#在第4 行暫停
在繼續之前,在控制台中輸入originalFunction
和。 initialParams
請注意,即使我們在一個全新的函數中,我們仍然可以存取這兩個參數?這是因為從父函數傳回的函數享有其父函數的作用域。
繼承
在父函數傳遞之後,他們將參數留給孩子使用。有點像現實生活中的繼承。
curry
最初給出originalFunction
,initialParams
然後回傳一個「子」函數。這兩個變數還沒有被處理掉,因為也許那個孩子需要它們。如果他不這樣做,那麼這個範圍就會被清理乾淨,因為當沒有人提到你時,那就是你真正死去的時候。
好的,回到第4 行…
#檢查nextParams
並看到它是['Hello']
…一個陣列?但我以為我們說curriedGreet(‘Hello’)
,不是curriedGreet(['Hello'])
!
正確:我們呼叫curriedGreet
了with 'Hello'
,但是多虧了rest 語法,我們變成#'Hello'
了['Hello']
.
#是嗎? !
curry
是一個通用函數,可以提供 1、10 或 10,000,000 個參數,因此它需要一種方法來引用所有參數。使用類似的 rest 語法捕獲一個陣列中的每個參數,使curry
' 的工作更容易。
讓我們跳到下debugger
一條語句。
现在是第 6 行,但请稍等。
您可能已经注意到第 12 行实际上在debugger
第 6 行的语句之前运行。如果不是,请仔细查看。我们的程序在第 5 行定义了一个调用函数curriedFunction
,在第 12 行使用它,然后我们debugger
在第 6 行点击了该语句。curriedFunction
调用的是什么?
[...initialParams, ...nextParams];
呸呸呸。查看params
第 5 行,您会看到['Hello']
. 两者initialParams
和都是数组,所以我们使用方便的扩展运算符nextParams
将它们展平并组合成一个数组。
这就是好事发生的地方。
第 7 行说“如果params
和originalFunction
长度相同,请greet
使用我们的参数调用,我们就完成了。” 这使我想起…
JavaScript 函数也有长度
这就是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
本质上是一个无限循环的自调用,参数饥渴的函数,直到他们的客人满了才会休息。热情好客。
回到第 2 行
与以前相同initialParams
的参数,除了['Hello']
这次。再次跳过以退出循环。在控制台中输入我们的新变量,sayHello
. 这是另一个函数,仍然期待更多参数,但我们正在变得更加温暖......
让我们把火调大sayHelloToJohn = sayHello('John')
。
我们又在第 4 行了,而且nextParams
是['John']
。跳到第 6 行的下一个调试器并检查params
:它是['Hello', 'John']
!?
为什么?
因为请记住,第 12 行说“嘿curriedFunction
,他'Hello'
上次和‘John’
这次都给了我。把他们两个都带进这个阵法[...initialParams, ...nextParams]
。”
现在curriedFunction
再次将length
这些params
与进行比较originalFunction
,因为2 我们移动到第 10 行并<code>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');
【相关视频教程推荐:web前端 】
以上是一文快速了解JS中的柯里化(Currying)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

VSCode Windows 64位元 下載
微軟推出的免費、功能強大的一款IDE編輯器

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

ZendStudio 13.5.1 Mac
強大的PHP整合開發環境

Dreamweaver Mac版
視覺化網頁開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。