摘要:原文鏈接原文作者函數(shù)式編程這篇文章是介紹函數(shù)式編程的四篇文章中的第二篇。這些部分被使用的越來越頻繁,人們把他們放到一個(gè)函數(shù)式編程的庫(kù)里面,有一些流行的庫(kù)包括未亡待續(xù)閱讀下一節(jié)原文地址歡迎關(guān)注
tips
原文鏈接: http://jrsinclair.com/articles/2016/gentle-introduction-to-functional-javascript-arrays/;
原文作者: James Sinclair;
這篇文章是介紹函數(shù)式編程的四篇文章中的第二篇。在上一篇文章中,我們看到如何使用函數(shù)使代碼抽象地更簡(jiǎn)潔,在這篇文章中我們將使用這個(gè)技術(shù)在列表上。
Part1 組成部分和動(dòng)機(jī),
Part2 使用數(shù)組和列表,
Part3 生成函數(shù)的函數(shù),
Part4 使用函數(shù)式編程的風(fēng)格,
處理函數(shù)和集合會(huì)想之前的文章,我們談?wù)摿?DRY 準(zhǔn)則。我們看到用函數(shù)綁定一系列重復(fù)的操作是很有用的。但是如果我們重復(fù)同一個(gè)函數(shù)很多次呢?就像這樣:
function addColour(colour) { var rainbowEl = document.getElementById("rainbow"); var div = document.createElement("div"); div.style.paddingTop = "10px"; div.style.backgroundColour = colour; rainbowEl.appendChild(div); } addColour("red"); addColour("orange"); addColour("yellow"); addColour("green"); addColour("blue"); addColour("purple");
在這里 addColour 這個(gè)函數(shù)被調(diào)用很多次,我們?nèi)匀恢貜?fù)了我們自己,這是我們一直想回避的。一種重構(gòu)的方法是構(gòu)建一個(gè)數(shù)組包含這些顏色的列表,然后循環(huán)調(diào)用 addColour 這個(gè)函數(shù)。
var colours = [ "red", "orange", "yellow", "green", "blue", "purple" ]; for (var i = 0; i < colours.length; i = i + 1) { addColour(colours[i]); }For-Each
JavaScript 允許我們把一個(gè)函數(shù)座位參數(shù)傳遞給另一個(gè)函數(shù),編寫一個(gè) forEach 函數(shù)是相當(dāng)明確了:
function forEach(callback, array) { for (var i = 0; i < array.length; i = i + 1) { callback(array[i], i); } }
這個(gè)函數(shù)接受執(zhí)行 callback 函數(shù),并且把數(shù)組的每一項(xiàng)作為參數(shù)調(diào)用 callback 函數(shù)。
現(xiàn)在,在我們的例子中,我們想要對(duì)數(shù)組的每一個(gè)元素去運(yùn)行 addColour 方法,使用我們的 forEach 我們僅需一行就能完美執(zhí)行~
forEach(addColour, colours);
對(duì)數(shù)組中的每一個(gè)元素調(diào)用一個(gè)方法是非常有用的一個(gè)工具,JavaScript 也實(shí)現(xiàn)了這么一個(gè)特性組成,作為數(shù)組對(duì)象的一個(gè)方法。因此我們也可以使用它來替代我們的 forEach 方法,如下:
var colours = [ "red", "orange", "yellow", "green", "blue", "purple" ]; colours.forEach(addColour);
我們可以查找更多的方法在 MDN 的 JavaScript 參考文檔里。
Map我們的 forEach 已經(jīng)非常好用了,但是扔有一些局限性。如果回調(diào)函數(shù)返回一個(gè)值,那 forEach 只會(huì)忽略掉這個(gè)返回值。我們可以適當(dāng)改造一下 forEach 函數(shù),無論他返回什么類型的值我們都可以取得。我們可以得到一個(gè)數(shù)組,它包含了我們?cè)紨?shù)字相對(duì)應(yīng)的一些值。
讓我們看看下面的例子,我們有一個(gè) ID 的數(shù)組,然后我們想得到他們每個(gè)相對(duì)應(yīng)的 DOM 元素集合。在程序上找到解決的方法,我們可以使用循環(huán):
var ids = ["unicorn", "fairy", "kitten"]; var elements = []; for (var i = 0; i < ids.length; i = i + 1) { elements[i] = document.getElementById(ids[i]); } // elements now contains the elements we are after
我們想要闡明計(jì)算機(jī)是如何創(chuàng)建一個(gè)索引變量并且增加它--細(xì)節(jié)我們不需多考慮。讓我們使用循環(huán)就像 forEach 里面一樣,并且把它復(fù)制給一個(gè)叫做 map 的變量。
var map = function(callback, array) { var newArray = []; for (var i = 0; i < array.length; i = i + 1) { newArray[i] = callback(array[i], i); } return newArray; }
現(xiàn)在我們有了一個(gè) map 函數(shù),可以這么實(shí)用它:
var getElement = function(id) { return document.getElementById(id); }; var elements = map(getElement, ids);
這個(gè) map 函數(shù)小而簡(jiǎn)單,但是它里面執(zhí)行了另一個(gè)我們的超級(jí)函數(shù),只需在數(shù)組的一個(gè)入口調(diào)用它一次就可以了,成倍的增長(zhǎng)了函數(shù)的效率。
像 forEach 函數(shù)一樣,JavaScript 本身也實(shí)現(xiàn)了 map 函數(shù),作為數(shù)組對(duì)象的一個(gè)方法。我們可以調(diào)用這部分方法如下:
var ids = ["unicorn", "fairy", "kitten"]; var getElement = function(id) { return document.getElementById(id); }; var elements = ids.map(getElement, ids);
我們可以在 MDN 上查閱更多關(guān)于 map 函數(shù)的組成。
Reduce嗯,map 函數(shù)事很有用的。但是我們想實(shí)現(xiàn)一個(gè)更有用的函數(shù),如果我們對(duì)所有的數(shù)組元素執(zhí)行函數(shù)但是返回僅僅一個(gè)值。這聽起來可能有一點(diǎn)反常,函數(shù)返回一個(gè)值為什么會(huì)比返回多個(gè)值更有用?為了尋找答案,我們可以先看看下面這個(gè)函數(shù)是如何工作的。
為了解釋,我們考慮兩個(gè)相似的問題:
給一個(gè)數(shù)組一些數(shù)值元素,并且計(jì)算他們的和;
給一個(gè)數(shù)組一些字符串元素,并且用空格符在他們直接連接起來。
現(xiàn)在我們來看看一個(gè)愚蠢、微不足道的例子--事實(shí)是他們也確實(shí)如此。這對(duì)于我來說相當(dāng)難忍受,但是如果我們一旦學(xué)習(xí)到 reduce 函數(shù)是如何工作的,我們就可以把它應(yīng)用在很多有趣的情況下。
我們?cè)賮砜纯闯绦蛏蠒r(shí)如可解決這個(gè)問題的,還是循環(huán):
// Given an array of numbers, calculate the sum var numbers = [1, 3, 5, 7, 9]; var total = 0; for (i = 0; i < numbers.length; i = i + 1) { total = total + numbers[i]; } // total is 25 // Given an array of words, join them together with a space between each word. var words = ["sparkle", "fairies", "are", "amazing"]; var sentence = ""; for (i = 0; i < words.length; i++) { sentence = sentence + " " + words[i]; } // " sparkle fairies are amazing"
兩個(gè)方案都是一樣的其實(shí),他們都使用for循環(huán)去迭代,他們都有個(gè)執(zhí)行變量(total 和 sentence),他們都對(duì)執(zhí)行變量賦值一個(gè)初始值。
讓我們把他們循環(huán)中的操作抽出來寫一個(gè)函數(shù):
var add = function(a, b) { return a + b; } // Given an array of numbers, calculate the sum var numbers = [1, 3, 5, 7, 9]; var total = 0; for (i = 0; i < numbers.length; i = i + 1) { total = add(total, numbers[i]); } // total is 25 function joinWord(sentence, word) { return sentence + " " + word; } // Given an array of words, join them together with a space between each word. var words = ["sparkle", "fairies", "are", "amazing"]; var sentence = ""; for (i = 0; i < words.length; i++) { sentence = joinWord(sentence, words[i]); } // "sparkle fairies are amazing"
現(xiàn)在,它變得簡(jiǎn)潔有用了,內(nèi)部函數(shù)把執(zhí)行變量作為他的第一個(gè)參數(shù),然后當(dāng)前遍歷到的數(shù)組元素值作為第二個(gè)參數(shù)?,F(xiàn)在我們讓它更加簡(jiǎn)潔,我們把凌亂的 for 循環(huán)放到函數(shù)里面。
var reduce = function(callback, initialValue, array) { var working = initialValue; for (var i = 0; i < array.length; i = i + 1) { working = callback(working, array[i]); } return working; };
現(xiàn)在我們又個(gè)閃閃發(fā)亮的 reduce 新函數(shù)了,讓我們來使用使用它:
var total = reduce(add, 0, numbers); var sentence = reduce(joinWord, "", words);
就像 forEach 和 map 函數(shù),reduce 函數(shù)也是 JavaScript 數(shù)組對(duì)象的標(biāo)準(zhǔn)方法之一。
我們可以這么使用它:
var total = numbers.reduce(add, 0); var sentence = words.reduce(joinWord, "");
我們可以在 MDN 上查閱更多關(guān)于 reduce 函數(shù)的組成。
總結(jié)正如我們前面所提及,他們都是很簡(jiǎn)單的例子--add 和 joinWord 函數(shù)都非常地簡(jiǎn)單。更小,更簡(jiǎn)單的函數(shù)易于思考和測(cè)試。當(dāng)我們把兩個(gè)小而簡(jiǎn)單的函數(shù)結(jié)合起來的時(shí)候(就像 add 和 reduce),他的結(jié)果比起編寫一個(gè)大而復(fù)雜的函數(shù)來說仍然很好解釋。
但是,正如我前面所說,我們可以把很多方法結(jié)合起來做一些更有意思的事情。
讓我們嘗試更復(fù)雜一些,我們把一個(gè)數(shù)據(jù)對(duì)象用 map 和 reduce 函數(shù)轉(zhuǎn)化成一個(gè) HTML 列表,數(shù)據(jù)如下:
var ponies = [ [ ["name", "Fluttershy"], ["image", "http://tinyurl.com/gpbnlf6"], ["description", "Fluttershy is a female Pegasus pony and one of the main characters of My Little Pony Friendship is Magic."] ], [ ["name", "Applejack"], ["image", "http://tinyurl.com/gkur8a6"], ["description", "Applejack is a female Earth pony and one of the main characters of My Little Pony Friendship is Magic."] ], [ ["name", "Twilight Sparkle"], ["image", "http://tinyurl.com/hj877vs"], ["description", "Twilight Sparkle is the primary main character of My Little Pony Friendship is Magic."] ] ];
這些數(shù)據(jù)不是十分整潔,如果把里面的數(shù)組變成對(duì)象會(huì)更清晰。不過,在之前我們可以 reduce 函數(shù)去估算一些簡(jiǎn)單的值就像數(shù)字或者字符串,但是沒人敢說 reduce 返回的值一定簡(jiǎn)單。我們可以把它使用在 對(duì)象,數(shù)組 或者甚至是 DOM 元素 上面。讓我們創(chuàng)造一個(gè)函數(shù)把內(nèi)部的數(shù)組(像 ["name", "Fluttershy"])以鍵值對(duì)的形式添加到一個(gè)對(duì)象之中。
var addToObject = function(obj, arr) { obj[arr[0]] = arr[1]; return obj; };
使用 addToObject 函數(shù),我們可以把每個(gè)數(shù)組轉(zhuǎn)化成對(duì)象:
var ponyArrayToObject = function(ponyArray) { return reduce(addToObject, {}, ponyArray); };
然后使用 map 函數(shù)把整個(gè)數(shù)組轉(zhuǎn)化的更簡(jiǎn)潔清晰:
var tidyPonies = map(ponyArrayToObject, ponies);
現(xiàn)在我們有了一個(gè)對(duì)象組成的數(shù)組,可以從Thomas Fuchs’ tweet-sized templating engine獲得一些幫助,我們可以再使用 reduce 函數(shù)把它轉(zhuǎn)換成 HTML 片段。模版函數(shù)接受一個(gè)模版字符串和一個(gè)對(duì)象,他會(huì)把字符串當(dāng)中 mustache-wrapped 格式的部分(像, {name} 或者 {image}))用對(duì)象中包含的屬性值類替換。比如:
var data = { name: "Fluttershy" }; t("Hello {name}!", data); // "Hello Fluttershy!" data = { who: "Fluttershy", time: Date.now() }; t("Hello {name}! It"s {time} ms since epoch.", data); // "Hello Fluttershy! It"s 1454135887369 ms since epoch."
所以,如果我們想要吧對(duì)象轉(zhuǎn)換成列表項(xiàng),我們可以這么做:
var ponyToListItem = function(pony) { var template = "
{description}
" + "在上面我們把對(duì)象轉(zhuǎn)換成了 html 片段,但是如果想轉(zhuǎn)換整個(gè)數(shù)組,我們就需要 reduce 和 joinWord 方法:
var ponyList = map(ponyToListItem, tidyPonies); var html = "
我們可以在http://jsbin.com/wuzini/edit?html,js,output看到整個(gè)運(yùn)行結(jié)果。
當(dāng)你理解 reduce 和 map 方法之后,你就不再需要老舊的 for 循環(huán)了。事實(shí)上,如果你決定在你的下一個(gè)項(xiàng)目上完全不使用 for 循環(huán)將會(huì)是一個(gè)很有意思的挑戰(zhàn)。當(dāng)你使用 reduce 和 map 越來越多的時(shí)候,你就會(huì)注意還有沒有更多的部分可以被抽象出來。一些常見的包括過濾filtering,或者plucking。這些部分被使用的越來越頻繁,人們把他們放到一個(gè)函數(shù)式編程的庫(kù)里面,有一些流行的庫(kù)包括:
Ramda,
Lodash, and
Underscore.
-----------------
未亡待續(xù)...
[閱讀下一節(jié)~]
原文地址
歡迎關(guān)注blog~
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/78810.html
摘要:開始翻譯函數(shù)式編程專有名詞庫(kù)在翻譯的過程中,難免會(huì)遇到很多描述不太清楚的專有名詞,一個(gè)辦法是小組內(nèi)進(jìn)行討論,最后商量出來結(jié)果,小組內(nèi)統(tǒng)一翻譯。因?yàn)楸緯闹黝}是函數(shù)式編程,所以這個(gè)名詞庫(kù)里大部分都是函數(shù)式編程相關(guān)的專有名詞。 在平時(shí)的工作中,我們都會(huì)經(jīng)常查閱一些英文文檔來解決平時(shí)遇到的問題和拓寬視野??吹胶玫奈恼禄蛘邥袥]有想要和小伙伴分享的沖動(dòng),那么我們一起來翻譯吧~ 翻譯主張 信 ...
摘要:開始翻譯函數(shù)式編程專有名詞庫(kù)在翻譯的過程中,難免會(huì)遇到很多描述不太清楚的專有名詞,一個(gè)辦法是小組內(nèi)進(jìn)行討論,最后商量出來結(jié)果,小組內(nèi)統(tǒng)一翻譯。因?yàn)楸緯闹黝}是函數(shù)式編程,所以這個(gè)名詞庫(kù)里大部分都是函數(shù)式編程相關(guān)的專有名詞。 在平時(shí)的工作中,我們都會(huì)經(jīng)常查閱一些英文文檔來解決平時(shí)遇到的問題和拓寬視野??吹胶玫奈恼禄蛘邥袥]有想要和小伙伴分享的沖動(dòng),那么我們一起來翻譯吧~ 翻譯主張 信 ...
摘要:開始翻譯函數(shù)式編程專有名詞庫(kù)在翻譯的過程中,難免會(huì)遇到很多描述不太清楚的專有名詞,一個(gè)辦法是小組內(nèi)進(jìn)行討論,最后商量出來結(jié)果,小組內(nèi)統(tǒng)一翻譯。因?yàn)楸緯闹黝}是函數(shù)式編程,所以這個(gè)名詞庫(kù)里大部分都是函數(shù)式編程相關(guān)的專有名詞。 在平時(shí)的工作中,我們都會(huì)經(jīng)常查閱一些英文文檔來解決平時(shí)遇到的問題和拓寬視野??吹胶玫奈恼禄蛘邥袥]有想要和小伙伴分享的沖動(dòng),那么我們一起來翻譯吧~ 翻譯主張 信 ...
摘要:一旦我們滿足了基本條件值為,我們將不再調(diào)用遞歸函數(shù),只是有效地執(zhí)行了。遞歸深諳函數(shù)式編程之精髓,最被廣泛引證的原因是,在調(diào)用棧中,遞歸把大部分顯式狀態(tài)跟蹤換為了隱式狀態(tài)。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關(guān)于譯者:這是一個(gè)流淌著滬江血液的純粹工程:認(rèn)真,是 HTML 最堅(jiān)實(shí)的梁柱;...
摘要:為此決定自研一個(gè)富文本編輯器。例如當(dāng)要轉(zhuǎn)化的對(duì)象有環(huán)存在時(shí)子節(jié)點(diǎn)屬性賦值了父節(jié)點(diǎn)的引用,為了關(guān)于函數(shù)式編程的思考作者李英杰,美團(tuán)金融前端團(tuán)隊(duì)成員。只有正確使用作用域,才能使用優(yōu)秀的設(shè)計(jì)模式,幫助你規(guī)避副作用。 JavaScript 專題之惰性函數(shù) JavaScript 專題系列第十五篇,講解惰性函數(shù) 需求 我們現(xiàn)在需要寫一個(gè) foo 函數(shù),這個(gè)函數(shù)返回首次調(diào)用時(shí)的 Date 對(duì)象,注意...
閱讀 3015·2021-10-12 10:12
閱讀 3068·2021-09-22 16:04
閱讀 3300·2019-08-30 15:54
閱讀 2612·2019-08-29 16:59
閱讀 2926·2019-08-29 16:08
閱讀 878·2019-08-29 11:20
閱讀 3502·2019-08-28 18:08
閱讀 660·2019-08-26 13:43