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

關(guān)于譯者:這是一個(gè)流淌著滬江血液的純粹工程:認(rèn)真驱入,是 HTML 最堅(jiān)實(shí)的梁柱卓嫂;分享秀鞭,是 CSS 里最閃耀的一瞥;總結(jié)鸠按,是 JavaScript 中最嚴(yán)謹(jǐn)?shù)倪壿嫛=?jīng)過(guò)捶打磨練,成就了本書的中文版。本書包含了函數(shù)式編程之精髓改淑,希望可以幫助大家在學(xué)習(xí)函數(shù)式編程的道路上走的更順暢。比心炫贤。

譯者團(tuán)隊(duì)(排名不分先后):阿希溅固、bluekenbrucecham兰珍、cfanlifedail询吴、kyoko-df掠河、l3velilins猛计、LittlePineapple唠摹、MatildaJin冬青奉瘤、pobusama勾拉、Cherry蘿卜盗温、vavd317藕赞、vivaxy萌萌卖局、zhouyao

JavaScript 輕量級(jí)函數(shù)式編程

附錄 C:函數(shù)式編程函數(shù)庫(kù)

如果您已經(jīng)從頭到尾通讀了此書斧蜕,請(qǐng)花一分鐘的時(shí)間停下來(lái)回顧一下從第 1 章到現(xiàn)在的收獲。相當(dāng)漫長(zhǎng)的一段旅程砚偶,不是嗎批销?希望您已經(jīng)收獲了大量新知識(shí),并用函數(shù)式的方式思考你的程序染坯。

在本書即將完結(jié)時(shí)均芽,我想給你提供一些關(guān)于使用官方函數(shù)式編程函數(shù)庫(kù)的快速指南。注意這并不是一個(gè)詳細(xì)的文檔单鹿,而是將你在結(jié)束“輕量級(jí)函數(shù)式編程”后進(jìn)軍真正的函數(shù)式編程時(shí)應(yīng)該注意的東西快速梳理一下掀宋。

如果有可能,我建議你不要做重新造輪子這樣的事情。如果你找到了一個(gè)能滿足你需求的函數(shù)式編程函數(shù)庫(kù)布朦,那么用它就對(duì)了囤萤。只有在你實(shí)在找不到合適的庫(kù)來(lái)應(yīng)對(duì)你面臨的問(wèn)題時(shí),才應(yīng)該使用本書提供的輔助實(shí)用函數(shù) —— 或者自己造輪子是趴。

目錄

在本書第 1 章曾列出了一個(gè)函數(shù)式編程庫(kù)的列表涛舍,現(xiàn)在我們來(lái)擴(kuò)展這個(gè)列表。我們不會(huì)涉及所有的庫(kù)(它們之中有許多重復(fù)的內(nèi)容)唆途,但下面這些你應(yīng)該有所關(guān)注:

  • Ramda:通用函數(shù)式編程實(shí)用函數(shù)
  • Sanctuary:函數(shù)式編程類型 Ramda 伴侶
  • lodash/fp:通用函數(shù)式編程實(shí)用函數(shù)
  • functional.js:通用函數(shù)式編程實(shí)用函數(shù)
  • Immutable:不可變數(shù)據(jù)結(jié)構(gòu)
  • Mori:(受到 ClojureScript 啟發(fā))不可變數(shù)據(jù)結(jié)構(gòu)
  • Seamless-Immutable:不可變數(shù)據(jù)助手
  • tranducers-js:數(shù)據(jù)轉(zhuǎn)換器
  • monet.js:Monad 類型

上面的列表只列出了所有函數(shù)式編程庫(kù)的一小部分富雅,并不是說(shuō)沒(méi)有在列表中列出的庫(kù)就不好,也不是說(shuō)列表中列出的就是最佳選擇肛搬,總之這只是 JavaScript 函數(shù)式編程世界中的一瞥没佑。您可以前往這里查看更完整的函數(shù)式編程資源。

Fantasy Land(又名 FL)是函數(shù)式編程世界中十分重要的學(xué)習(xí)資源之一温赔,與其說(shuō)它是一個(gè)庫(kù)蛤奢,不如說(shuō)它是一本百科全書。

Fantasy Land 不是一份為初學(xué)者準(zhǔn)備的輕量級(jí)讀物陶贼,而是一個(gè)完整而詳細(xì)的 JavaScript 函數(shù)式編程路線圖啤贩。為了盡可能提升互通性,F(xiàn)L 已經(jīng)成為 JavaScript 函數(shù)式編程庫(kù)遵循的實(shí)際標(biāo)準(zhǔn)拜秧。

Fantasy Land 與“輕量級(jí)函數(shù)式編程”的概念相反痹屹,它以火力全開的姿態(tài)進(jìn)軍 JavaScript 的函數(shù)式編程世界。也就是說(shuō)枉氮,當(dāng)你的能力超越本書時(shí)志衍,F(xiàn)L 將會(huì)成為你接下來(lái)前進(jìn)的方向。我建議您將其保存在收藏夾中聊替,并在您使用本書的概念進(jìn)行至少 6 個(gè)月的實(shí)戰(zhàn)練習(xí)之后再回來(lái)楼肪。

Ramda (0.23.0)

摘自 Ramda 文檔:

Ramda 函數(shù)自動(dòng)地被柯里化。

Ramda 函數(shù)的參數(shù)經(jīng)過(guò)優(yōu)化佃牛,更便于柯里化淹辞。需要被操作的數(shù)據(jù)往往放在最后提供。

我認(rèn)為合理的設(shè)計(jì)是 Ramda 的優(yōu)勢(shì)之一俘侠。值得注意的是象缀,Ramda 的柯里化形式(似乎大多數(shù)的庫(kù)都是這種形式)是我們?cè)诘?3 章中討論過(guò)的“松散柯里化”。

第 3 章的最后一個(gè)例子 —— 我們定義無(wú)值(point-free)工具函數(shù) printIf() —— 可以在 Ramda 中這樣實(shí)現(xiàn):

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

與我們?cè)诘?3 章中的實(shí)現(xiàn)相比有幾處不同:

  • 我們使用 R.complement(..) 而不是 not(..)isShortEnough(..) 周圍新建一個(gè)否定函數(shù) isLongEnough(..)爷速。

  • 使用 R.flip(..) 而不是 reverseArgs(..) 函數(shù)央星,值得一提的是,R.flip(..) 僅交換頭兩個(gè)參數(shù)惫东,而 reverseArgs(..) 會(huì)將所有參數(shù)反向莉给。在這種情景下毙石,flip(..) 更加方便,所以我們不再需要使用 partialRight(..) 或其他投機(jī)取巧的方式進(jìn)行處理颓遏。

  • R.partial(..) 所有的后續(xù)參數(shù)以單個(gè)數(shù)組的形式存在徐矩。

  • 因?yàn)?Ramda 使用松散柯里化,因此我們不需要使用 R.uncurryN(..) 來(lái)獲得一個(gè)包含所有參數(shù)的 printIf(..)叁幢。如果我們這樣做了滤灯,就相當(dāng)于使用 R.uncurryN(2, ..) 包裹 R.partial(..) 進(jìn)行調(diào)用,這是完全沒(méi)有必要的曼玩。

Ramda 是一個(gè)受歡迎的鳞骤、功能強(qiáng)大的庫(kù)。如果你想要在你的代碼中實(shí)踐 FP黍判,從 Ramda 開始是個(gè)不錯(cuò)的選擇豫尽。

Lodash/fp (4.17.4)

Lodash 是整個(gè) JS 生態(tài)系統(tǒng)中最受歡迎的庫(kù)。Lodash 團(tuán)隊(duì)發(fā)布了一個(gè)“FP 友好”的 API 版本 —— "lodash/fp"顷帖。

在第 8 章中美旧,我們討論了合并獨(dú)立列表操作(map(..)filter(..) 以及 reduce(..))窟她。使用“l(fā)odash/fp”時(shí)陈症,你可以這樣做:

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

與我們所熟知的 _. 命名空間前綴不同,“l(fā)odash/fp”將 fp. 定義為其命名空間前綴震糖。我發(fā)現(xiàn)一個(gè)很有用的區(qū)別,就是 fp._. 更容易識(shí)別趴腋。

注意 fp.compose(..)(在常規(guī) lodash 版本中又名 _.flowRight(..))接受一個(gè)函數(shù)數(shù)組吊说,而不是獨(dú)立的函數(shù)作為參數(shù)。

lodash 擁有良好的穩(wěn)定性优炬、廣泛的社區(qū)支持以及優(yōu)秀的性能颁井,是你探索 FP 世界時(shí)的堅(jiān)實(shí)后盾。

Mori (0.3.2)

在第 6 章中蠢护,我們已經(jīng)快速瀏覽了一下 Immutable.js 庫(kù)雅宾,該庫(kù)可能是最廣為人知的不可變數(shù)據(jù)結(jié)構(gòu)庫(kù)了。

讓我們來(lái)看一下另一個(gè)流行的庫(kù):Mori葵硕。Mori 設(shè)計(jì)了一套與眾不同(從表面上看更像函數(shù)式編程)的 API:它使用獨(dú)立的函數(shù)而不直接在值上操作眉抬。

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]

這是一個(gè)指出關(guān)于 Mori 的一些有趣的事情的例子:

  • 使用 vector 而不是 list(你可能會(huì)想用的),主要是因?yàn)槲臋n說(shuō)它的行為更像 JavaScript 中的數(shù)組懈凹。

  • 不能像在操作原生 JavaScript 數(shù)組那樣在任意位置設(shè)置值蜀变,在 vector 結(jié)構(gòu)中,這將會(huì)拋出異常介评。因此我們必須使用 mori.into(..)库北,傳入一個(gè)合適長(zhǎng)度的數(shù)組來(lái)擴(kuò)展 vector 的長(zhǎng)度爬舰。在上例中,vector 有 43 個(gè)可用位置(4 + 39)寒瓦,所以我們可以在最后一個(gè)位置(索引為 42)上寫入 "meaning of life" 這個(gè)值情屹。

  • 使用 mori.into(..) 創(chuàng)建一個(gè)較大的 vector,再用 mor.assoc(..) 根據(jù)這個(gè) vector 創(chuàng)建另一個(gè) vector 的做法聽起來(lái)效率低下垃你。但是蜡镶,不可變數(shù)據(jù)結(jié)構(gòu)的好處在于數(shù)據(jù)不會(huì)進(jìn)行克隆,每次“改變”發(fā)生恤筛,新的數(shù)據(jù)結(jié)構(gòu)只會(huì)追蹤其與舊數(shù)據(jù)結(jié)構(gòu)的不同之處官还。

Mori 受到 ClojureScript 極大的啟發(fā)。如果您有 ClojureScript 編程經(jīng)驗(yàn)毒坛,那您應(yīng)該對(duì) Mori 的 API 感到非常熟悉望伦。由于我沒(méi)有這種編程經(jīng)驗(yàn),因此我感覺(jué) Mori 中的方法名有點(diǎn)奇怪煎殷。

但相比于在數(shù)據(jù)上直接調(diào)用方法屯伞,我真的很喜歡調(diào)用獨(dú)立方法這樣的設(shè)計(jì)。Mori 還有一些自動(dòng)返回原生 JavaScript 數(shù)組的方法豪直,用起來(lái)非常方便劣摇。

總結(jié)

JavaScript 不是作為函數(shù)式編程語(yǔ)言來(lái)特別設(shè)計(jì)的。不過(guò)其自身的確擁有很多對(duì)函數(shù)式編程非常友好基礎(chǔ)語(yǔ)法(例如可作為變量的函數(shù)弓乙、閉包等)末融。本章提及的庫(kù)將使你更方便的進(jìn)行函數(shù)式編程。

有了本書中函數(shù)式編程概念的武裝暇韧,相信你已經(jīng)準(zhǔn)備好開始處理現(xiàn)實(shí)世界的代碼了勾习。找一個(gè)優(yōu)秀的函數(shù)式編程庫(kù)來(lái)用,然后練習(xí)懈玻,練習(xí)巧婶,再練習(xí)。

就是這樣了涂乌。我已經(jīng)將我目前所知道的知識(shí)分享給你了艺栈。我在此正式認(rèn)證您為“JavaScript 輕量級(jí)函數(shù)式編程”程序員!好了骂倘,是時(shí)候結(jié)束我們一起學(xué)習(xí) FP 這部分的“章節(jié)”了眼滤,但我的學(xué)習(xí)之旅還將繼續(xù)。我希望历涝,你也是赵刑!

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

[圖片上傳失敗...(image-cd6976-1512962064310)]

iKcamp原創(chuàng)新書《移動(dòng)Web前端高效開發(fā)實(shí)戰(zhàn)》已在亞馬遜般此、京東、當(dāng)當(dāng)開售牵现。

iKcamp官網(wǎng):https://www.ikcamp.com
訪問(wèn)官網(wǎng)更快閱讀全部免費(fèi)分享課程:
《iKcamp出品|全網(wǎng)最新|微信小程序|基于最新版1.0開發(fā)者工具之初中級(jí)培訓(xùn)教程分享》
《iKcamp出品|基于Koa2搭建Node.js實(shí)戰(zhàn)項(xiàng)目教程》
包含:文章科乎、視頻、源代碼
[圖片上傳失敗...(image-292ac3-1512962064310)]

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末贼急,一起剝皮案震驚了整個(gè)濱河市茅茂,隨后出現(xiàn)的幾起案子太抓,更是在濱河造成了極大的恐慌空闲,老刑警劉巖走敌,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件掉丽,死亡現(xiàn)場(chǎng)離奇詭異影斑,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)机打,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)片迅,“玉大人残邀,你說(shuō)我怎么就攤上這事「躺撸” “怎么了芥挣?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)耻台。 經(jīng)常有香客問(wèn)我空免,道長(zhǎng),這世上最難降的妖魔是什么盆耽? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任蹋砚,我火速辦了婚禮扼菠,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘坝咐。我一直安慰自己循榆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布墨坚。 她就那樣靜靜地躺著秧饮,像睡著了一般。 火紅的嫁衣襯著肌膚如雪泽篮。 梳的紋絲不亂的頭發(fā)上盗尸,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音帽撑,去河邊找鬼泼各。 笑死,一個(gè)胖子當(dāng)著我的面吹牛油狂,可吹牛的內(nèi)容都是我干的历恐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼专筷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼弱贼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起磷蛹,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤吮旅,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后味咳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庇勃,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年槽驶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了责嚷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掂铐,死狀恐怖罕拂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情全陨,我是刑警寧澤爆班,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站辱姨,受9級(jí)特大地震影響柿菩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜雨涛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一枢舶、第九天 我趴在偏房一處隱蔽的房頂上張望懦胞。 院中可真熱鬧,春花似錦祟辟、人聲如沸医瘫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)醇份。三九已至,卻和暖如春吼具,著一層夾襖步出監(jiān)牢的瞬間僚纷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工拗盒, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留怖竭,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓陡蝇,卻偏偏與公主長(zhǎng)得像痊臭,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子登夫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容