摘要:本文將會手把手去實現(xiàn)這兩個函數(shù),來深入理解它們的工作原理。通過對輸入的數(shù)組中每一個元素進行變換,返回由變換后的元素按序組成的新數(shù)組。函數(shù)我們將重構為我們將重命名為,并增加了一個參數(shù)。通過定義一個函數(shù)來達到實現(xiàn)對每一個數(shù)組元素乘以的目的。
譯者按: 魯迅曾經(jīng)說過,學習JavaScript最好方式莫過于敲代碼了!
原文: Master Map & Filter, Javascript’s Most Powerful Array Functions
譯者: Fundebug
為了保證可讀性,本文采用意譯而非直譯。另外,本文版權歸原作者所有,翻譯僅用于學習。
這篇文章面向那些已經(jīng)熟練使用for循環(huán),但對Array.map和Array.filter并沒有特別理解的開發(fā)者。本文將會手把手去實現(xiàn)這兩個函數(shù),來深入理解它們的工作原理。
Array.mapArray.map通過對輸入的數(shù)組中每一個元素進行變換,返回由變換后的元素按序組成的新數(shù)組。原始數(shù)組的值不會被修改。假設我們相對一個數(shù)組中的每一個元素乘以3,使用for循環(huán)可以這樣寫。
for循環(huán)var originalArr = [1, 2, 3, 4, 5]; var newArr = []; for(var i = 0; i < originalArr.length; i++) { newArr[i] = originalArr[i] * 3; } console.log(newArr); // -> [3, 6, 9, 12, 15]
接下來我們將這個for循環(huán)抽象成一個函數(shù)。
multiplyByThree函數(shù)var originalArr = [1, 2, 3, 4, 5]; function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = arr[i] * 3; } return newArr; } var arrTransformed = multiplyByThree(originalArr); console.log(arrTransformed); // -> [3, 6, 9, 12, 15]
現(xiàn)在我們繼續(xù)深化這個抽象思路,將multiplyByThree中對每一個元素乘以3部分抽象為一個新的函數(shù)。
var originalArr = [1, 2, 3, 4, 5]; function timesThree(item) { return item * 3; } function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = timesThree(arr[i]); } return newArr; } var arrTransformed = multiplyByThree(originalArr); console.log(arrTransformed); // -> [3, 6, 9, 12, 15]
這樣有什么好處呢?設想如果我們想對每一個元素乘以5,或則10,我們還要把整個for循環(huán)寫一遍嗎!
如果我們對timesThree函數(shù)稍作修改,就可以輕松的復用很多代碼。
我們將:
function multiplyByThree(arr) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = timesThree(arr[i]); } return newArr; }
重構為:
function multiply(arr, multiplyFunction) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = multiplyFunction(arr[i]); } return newArr; }
我們將multiplyByThree重命名為multiply,并增加了一個參數(shù)。該參數(shù)是一個函數(shù),定義了數(shù)組元素的變換規(guī)則。通過定義一個timesThree函數(shù)來達到實現(xiàn)對每一個數(shù)組元素乘以3的目的。
var originalArr = [1, 2, 3, 4, 5]; function timesThree(item) { return item * 3; } var arrTimesThree = multiply(originalArr, timesThree); console.log(arrTimesThree); // -> [3, 6, 9, 12, 15]
有何優(yōu)點呢?我們可以很簡單定義任何變換:
var originalArr = [1, 2, 3, 4, 5]; function timesFive(item) { return item * 5; } var arrTimesFive = multiply(originalArr, timesFive); console.log(arrTimesFive); // -> [5, 10, 15, 20, 25]Map
我們進一步抽象:
function multiply(arr, multiplyFunction) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = multiplyFunction(arr[i]); } return newArr; }
將multiply改為map, multiplyFunction改為transform:
function map(arr, transform) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = transform(arr[i]); } return newArr; }
我們可以將任何對單個元素操作的函數(shù)傳入map函數(shù)。比如,我們將所有字符都變換成大寫:
function makeUpperCase(str) { return str.toUpperCase(); } var arr = ["abc", "def", "ghi"]; var ARR = map(arr, makeUpperCase); console.log(ARR); // -> ["ABC", "DEF, "GHI"]Array.map
我們定義的map函數(shù)和原生的Array.map還是有區(qū)別的:數(shù)組不再需要作為第一個參數(shù)傳入,而是在點(.)的左側。如果使用我們定義的map函數(shù),如下:
function func(item) { return item * 3; } var arr = [1, 2, 3]; var newArr = map(arr, func); console.log(newArr); // -> [3, 6, 9]
將其改寫為使用Array.map函數(shù)的形式:
function func(item) { return item * 3; } var arr = [1, 2, 3]; var newArr = arr.map(func); console.log(newArr); // -> [3, 6, 9]Arrary.map參數(shù)解析
除了變換函數(shù)外,Array.map還可以接收其它兩個參數(shù): 數(shù)組索引(index), 原始的數(shù)組。
function logItem(item) { console.log(item); } function logAll(item, index, arr) { console.log(item, index, arr); } var arr = ["abc", "def", "ghi"]; arr.map(logItem); // -> "abc", "def", "ghi" arr.map(logAll); // -> "abc", 0, ["abc", "def", "ghi"] // -> "def", 1, ["abc", "def", "ghi"] // -> "ghi", 2, ["abc", "def", "ghi"]
因此,你可以再變換函數(shù)中使用索引和原始的數(shù)組。比如:你想要將一個列表變?yōu)閹蛱柕牧斜恚瑒t需要使用索引(index)參數(shù):
function multiplyByIndex(item, index) { return (index + 1) + ". " + item; } var arr = ["bananas", "tomatoes", "pasta", "protein shakes"]; var mappedArr = arr.map(multiplyByIndex); console.log(mappedArr); // -> // ["1. bananas", "2. tomatoes", "3. pasta", "4. protein shakes"]
因此,我們自己實現(xiàn)的map函數(shù)也應該支持這兩個參數(shù):
function map(arr, transform) { var newArr = []; for(var i = 0; i < arr.length; i++) { newArr[i] = transform(arr[i], i, arr); } return newArr; }
當然,Array.map函數(shù)還有一些錯誤檢查和執(zhí)行優(yōu)化的代碼,我們定義的map只編碼了核心功能。
Array.filterArray.filter將數(shù)組中不滿足條件的元素過濾,我們可以用for循環(huán)加上Array.push來實現(xiàn)。
for-loop下面這段JS代碼將所有大于5的元素篩選出來:
var arr = [2, 4, 6, 8, 10]; var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(arr[i] > 5) { filteredArr.push(arr[i]); } } console.log(filteredArr); // -> [6, 8, 10]
我們可以抽象這段代碼,定義為一個函數(shù):
function filterLessThanFive(arr) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(arr[i] > 5){ filteredArr.push(arr[i]); } } return filteredArr; } var arr1 = [2, 4, 6, 8, 10]; var arr1Filtered = filterLessThanFive(arr1); console.log(arr1Filtered); // -> [6, 8, 10]
進一步抽象,將過濾條件抽出來:
function isGreaterThan5(item) { return item > 5; } function filterLessThanFive(arr) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(isGreaterThan5(arr[i])) { filteredArr.push(arr[i]); } } return filteredArr; } var originalArr = [2, 4, 6, 8, 10]; var newArr = filterLessThanFive(originalArr); console.log(newArr); // -> [6, 8, 10]
將過濾條件函數(shù)作為參數(shù)傳入:
function filterBelow(arr, greaterThan) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(greaterThan(arr[i])) { filteredArr.push(arr[i]); } } return filteredArr; } var originalArr = [2, 4, 6, 8, 10];
大功告成!我們可以使用如下代碼來取出所有大于5的元素:
function isGreaterThan5(item) { return item > 5; } var newArr = filterBelow(originalArr, isGreaterThan5); console.log(newArr); // -> [6, 8, 10];Array.filter
我們將filterBelow重命名為filter, greaterThan重命名為testFunction:
function filter(arr, testFunction) { var filteredArr = []; for(var i = 0; i < arr.length; i++) { if(testFunction(arr[i])) { filteredArr.push(arr[i]); } } return filteredArr; }
這就是一個基本的Array.filter函數(shù)了!
var arr = ["abc", "def", "ghijkl", "mnopuv"]; function longerThanThree(str) { return str.length > 3; } var newArr1 = filter(arr, longerThanThree); var newArr2 = arr.filter(longerThanThree); console.log(newArr1); // -> ["ghijkl", "mnopuv"] console.log(newArr2); // -> ["ghijkl", "mnopuv"]
同樣,Array.filter也有索引(index)和原始數(shù)組這兩個額外參數(shù)。
function func(item, index, arr) { console.log(item, index, arr); } var arr = ["abc", "def", "ghi"]; arr.filter(func); // -> "abc", 0, ["abc", "def", "ghi"] // -> "def", 1, ["abc", "def", "ghi"] // -> "ghi", 2, ["abc", "def", "ghi"]
>
版權聲明:
轉載時請注明作者Fundebug以及本文地址:
https://blog.fundebug.com/201...
文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://systransis.cn/yun/84571.html
摘要:原文作者譯者高階函數(shù)可以幫助你增強你的,讓你的代碼更具有聲明性。知道什么時候和怎樣使用高階函數(shù)是至關重要的。太棒了我們通過使用高階函數(shù)減少了許多額外的代碼。 原文:Higher Order Functions: Using Filter, Map and Reduce for More Maintainable Code作者:Guido Schmitz譯者:JeLewine 高階函數(shù)可...
摘要:通過對一系列任務建模來理解一些非常重要的函數(shù)式編程在列表操作中的價值一些些看起來不像列表的語句作為列表操作,而不是單獨執(zhí)行。映射我們將采用最基礎和最簡單的操作來開啟函數(shù)式編程列表操作的探索。函子是采用運算函數(shù)有效用操作的值。 原文地址:Functional-Light-JS 原文作者:Kyle Simpson-《You-Dont-Know-JS》作者 關于譯者:這是一個流淌著...
摘要:簡單模式記錄多個累加值在之前的版本中,我們創(chuàng)建了很多中間變量,。接下來,我們給自己設一個挑戰(zhàn),使用鏈式操作,將所有的函數(shù)調用組合起來,不再使用中間變量。你甚至可以繼續(xù)簡化上述代碼,移除不必要的中間變量,讓最終的計算代碼只有一行。 譯者按: 有時候一個算法的直觀、簡潔、高效是需要作出取舍的。 原文: FUNCTIONAL JAVASCRIPT: FIVE WAYS TO CALCULA...
摘要:第二種則一定會執(zhí)行所有的異步函數(shù),即便你需要使用的是這些高階函數(shù)。并發(fā)實現(xiàn)的異步數(shù)組然后修改,使用即可上面的其他內容終結整個鏈式操作并返回結果這里使用是為了兼容的調用方式調用方式不變。 JavaScript 異步數(shù)組 吾輩的博客原文: https://blog.rxliuli.com/p/5e... 場景 吾輩是一只在飛向太陽的螢火蟲 JavaScript 中的數(shù)組是一個相當泛用性的...
摘要:前言函數(shù)式編程在前端已經(jīng)成為了一個非常熱門的話題。整個過程就是體現(xiàn)了函數(shù)式編程的核心思想通過函數(shù)對數(shù)據(jù)進行轉換。高階函數(shù)函數(shù)式編程傾向于復用一組通用的函數(shù)功能來處理數(shù)據(jù),它通過使用高階函數(shù)來實現(xiàn)。 前言 函數(shù)式編程在前端已經(jīng)成為了一個非常熱門的話題。在最近幾年里,我們看到非常多的應用程序代碼庫里大量使用著函數(shù)式編程思想。 本文將略去那些晦澀難懂的概念介紹,重點展示在 JavaScrip...
閱讀 2351·2021-11-24 10:27
閱讀 3593·2019-08-30 15:55
閱讀 3355·2019-08-30 15:53
閱讀 2355·2019-08-29 17:27
閱讀 1445·2019-08-26 13:47
閱讀 3558·2019-08-26 10:28
閱讀 927·2019-08-23 15:59
閱讀 2871·2019-08-23 15:19