翻譯連載 | 附錄 C:函數式編程函數庫-《JavaScript輕量級函數式編程》 |《你不知道的JS》姊妹篇

關於譯者:這是一個流淌着滬江血液的純粹工程:認真,是 HTML 最堅實的樑柱;分享,是 CSS 裏最閃耀的一瞥;總結,是 JavaScript 中最嚴謹的邏輯。通過捶打磨練,成就了本書的中文版。本書包含了函數式編程之精髓,但願能夠幫助你們在學習函數式編程的道路上走的更順暢。比心。前端

譯者團隊(排名不分前後):阿希bluekenbrucechamcfanlifedailkyoko-dfl3velilinsLittlePineappleMatildaJin冬青pobusamaCherry蘿蔔vavd317vivaxy萌萌zhouyaonode

JavaScript 輕量級函數式編程

附錄 C:函數式編程函數庫

若是您已經從頭至尾通讀了此書,請花一分鐘的時間停下來回顧一下從第 1 章到如今的收穫。至關漫長的一段旅程,不是嗎?但願您已經收穫了大量新知識,並用函數式的方式思考你的程序。git

在本書即將完結時,我想給你提供一些關於使用官方函數式編程函數庫的快速指南。注意這並非一個詳細的文檔,而是將你在結束「輕量級函數式編程」後進軍真正的函數式編程時應該注意的東西快速梳理一下。程序員

若是有可能,我建議你不要作從新造輪子這樣的事情。若是你找到了一個能知足你需求的函數式編程函數庫,那麼用它就對了。只有在你實在找不到合適的庫來應對你面臨的問題時,才應該使用本書提供的輔助實用函數 —— 或者本身造輪子。github

目錄

在本書第 1 章曾列出了一個函數式編程庫的列表,如今咱們來擴展這個列表。咱們不會涉及全部的庫(它們之中有許多重複的內容),但下面這些你應該有所關注:編程

上面的列表只列出了全部函數式編程庫的一小部分,並非說沒有在列表中列出的庫就很差,也不是說列表中列出的就是最佳選擇,總之這只是 JavaScript 函數式編程世界中的一瞥。您能夠前往這裏查看更完整的函數式編程資源。小程序

Fantasy Land(又名 FL)是函數式編程世界中十分重要的學習資源之一,與其說它是一個庫,不如說它是一本百科全書。微信小程序

Fantasy Land 不是一份爲初學者準備的輕量級讀物,而是一個完整而詳細的 JavaScript 函數式編程路線圖。爲了儘量提高互通性,FL 已經成爲 JavaScript 函數式編程庫遵循的實際標準。數組

Fantasy Land 與「輕量級函數式編程」的概念相反,它以火力全開的姿態進軍 JavaScript 的函數式編程世界。也就是說,當你的能力超越本書時,FL 將會成爲你接下來前進的方向。我建議您將其保存在收藏夾中,並在您使用本書的概念進行至少 6 個月的實戰練習以後再回來。微信

Ramda (0.23.0)

摘自 Ramda 文檔:

Ramda 函數自動地被柯里化。

Ramda 函數的參數通過優化,更便於柯里化。須要被操做的數據每每放在最後提供。

我認爲合理的設計是 Ramda 的優點之一。值得注意的是,Ramda 的柯里化形式(彷佛大多數的庫都是這種形式)是咱們在第 3 章中討論過的「鬆散柯里化」。

第 3 章的最後一個例子 —— 咱們定義無值(point-free)工具函數 printIf() —— 能夠在 Ramda 中這樣實現:

function output(msg) {
	console.log( msg );
}

function isShortEnough(str) {
	return str.length <= 5;
}

var isLongEnough = R.complement( isShortEnough );

var printIf = R.partial( R.flip( R.when ), [output] );

var msg1 = "Hello";
var msg2 = msg1 + " World";

printIf( isShortEnough, msg1 );			// Hello
printIf( isShortEnough, msg2 );

printIf( isLongEnough, msg1 );
printIf( isLongEnough, msg2 );			// Hello World
複製代碼

與咱們在第 3 章中的實現相比有幾處不一樣:

  • 咱們使用 R.complement(..) 而不是 not(..)isShortEnough(..) 周圍新建一個否認函數 isLongEnough(..)

  • 使用 R.flip(..) 而不是 reverseArgs(..) 函數,值得一提的是,R.flip(..) 僅交換頭兩個參數,而 reverseArgs(..) 會將全部參數反向。在這種情景下,flip(..) 更加方便,因此咱們再也不須要使用 partialRight(..) 或其餘投機取巧的方式進行處理。

  • R.partial(..) 全部的後續參數以單個數組的形式存在。

  • 由於 Ramda 使用鬆散柯里化,所以咱們不須要使用 R.uncurryN(..) 來得到一個包含全部參數的 printIf(..)。若是咱們這樣作了,就至關於使用 R.uncurryN(2, ..) 包裹 R.partial(..) 進行調用,這是徹底沒有必要的。

Ramda 是一個受歡迎的、功能強大的庫。若是你想要在你的代碼中實踐 FP,從 Ramda 開始是個不錯的選擇。

Lodash/fp (4.17.4)

Lodash 是整個 JS 生態系統中最受歡迎的庫。Lodash 團隊發佈了一個「FP 友好」的 API 版本 —— "lodash/fp"

在第 8 章中,咱們討論了合併獨立列表操做(map(..)filter(..) 以及 reduce(..))。使用「lodash/fp」時,你能夠這樣作:

var sum = (x,y) => x + y;
var double = x => x * 2;
var isOdd = x => x % 2 == 1;

fp.compose( [
	fp.reduce( sum )( 0 ),
	fp.map( double ),
	fp.filter( isOdd )
] )
( [1,2,3,4,5] );					// 18
複製代碼

與咱們所熟知的 _. 命名空間前綴不一樣,「lodash/fp」將 fp. 定義爲其命名空間前綴。我發現一個頗有用的區別,就是 fp._. 更容易識別。

注意 fp.compose(..)(在常規 lodash 版本中又名 _.flowRight(..))接受一個函數數組,而不是獨立的函數做爲參數。

lodash 擁有良好的穩定性、普遍的社區支持以及優秀的性能,是你探索 FP 世界時的堅實後盾。

Mori (0.3.2)

在第 6 章中,咱們已經快速瀏覽了一下 Immutable.js 庫,該庫多是最廣爲人知的不可變數據結構庫了。

讓咱們來看一下另外一個流行的庫:Mori。Mori 設計了一套不同凡響(從表面上看更像函數式編程)的 API:它使用獨立的函數而不直接在值上操做。

var state = mori.vector( 1, 2, 3, 4 );

var newState = mori.assoc(
	mori.into( state, Array.from( {length: 39} ) ),
	42,
	"meaning of life"
);

state === newState;						// false

mori.get( state, 2 );					// 3
mori.get( state, 42 );					// undefined

mori.get( newState, 2 );				// 3
mori.get( newState, 42 );				// "meaning of life"

mori.toJs( newState ).slice( 1, 3 );	// [2,3]
複製代碼

這是一個指出關於 Mori 的一些有趣的事情的例子:

  • 使用 vector 而不是 list(你可能會想用的),主要是由於文檔說它的行爲更像 JavaScript 中的數組。

  • 不能像在操做原生 JavaScript 數組那樣在任意位置設置值,在 vector 結構中,這將會拋出異常。所以咱們必須使用 mori.into(..),傳入一個合適長度的數組來擴展 vector 的長度。在上例中,vector 有 43 個可用位置(4 + 39),因此咱們能夠在最後一個位置(索引爲 42)上寫入 "meaning of life" 這個值。

  • 使用 mori.into(..) 建立一個較大的 vector,再用 mor.assoc(..) 根據這個 vector 建立另外一個 vector 的作法聽起來效率低下。可是,不可變數據結構的好處在於數據不會進行克隆,每次「改變」發生,新的數據結構只會追蹤其與舊數據結構的不一樣之處。

Mori 受到 ClojureScript 極大的啓發。若是您有 ClojureScript 編程經驗,那您應該對 Mori 的 API 感到很是熟悉。因爲我沒有這種編程經驗,所以我感受 Mori 中的方法名有點奇怪。

但相比於在數據上直接調用方法,我真的很喜歡調用獨立方法這樣的設計。Mori 還有一些自動返回原生 JavaScript 數組的方法,用起來很是方便。

總結

JavaScript 不是做爲函數式編程語言來特別設計的。不過其自身的確擁有不少對函數式編程很是友好基礎語法(例如可做爲變量的函數、閉包等)。本章說起的庫將使你更方便的進行函數式編程。

有了本書中函數式編程概念的武裝,相信你已經準備好開始處理現實世界的代碼了。找一個優秀的函數式編程庫來用,而後練習,練習,再練習。

就是這樣了。我已經將我目前所知道的知識分享給你了。我在此正式認證您爲「JavaScript 輕量級函數式編程」程序員!好了,是時候結束咱們一塊兒學習 FP 這部分的「章節」了,但個人學習之旅還將繼續。我但願,你也是!

**【上一章】翻譯連載 | 附錄 B: 謙虛的 Monad-《JavaScript輕量級函數式編程》 |《你不知道的JS》姊妹篇 **

iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、噹噹開售。

iKcamp官網:www.ikcamp.com 訪問官網更快閱讀所有免費分享課程: 《iKcamp出品|全網最新|微信小程序|基於最新版1.0開發者工具之初中級培訓教程分享》 《iKcamp出品|基於Koa2搭建Node.js實戰項目教程》 包含:文章、視頻、源代碼

iKcamp新課程推出啦~~~~~開始免費連載啦~每週2更共11堂iKcamp課|基於Koa2搭建Node.js實戰項目教學(含視頻)| 課程大綱介紹


2019年,iKcamp原創新書《Koa與Node.js開發實戰》已在京東、天貓、亞馬遜、噹噹開售啦!

相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息