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