[譯]在 JavaScript 中 為什麼你應當使用 map 和 filter 來替代 forEach
當你需要將一個數組或一部分陣列複製到一個新陣列時,首選map
和filter
,而不是forEach
。
諮詢工作對我來說最大的好處之一是我可以看到無數的專案。這些專案有大有小,使用的程式語言和開發人員能力差異很大。儘管我認為有很多模式都應該放棄使用,但 JavaScript 語言中的這種模式尤其要棄用:使用 forEach 建立新陣列。該模式實際上非常簡單,看起來像這樣:
const kids = []; people.forEach(person => { if (person.age < 15) { kids.push({ id: person.id, name: person.name }); } }); 複製程式碼
這段程式碼的意思是,處理一個包含所有人的陣列,以找出每個年齡小於 15 歲的人。然後選擇 person 物件中的其中幾個欄位作為 'kids' 物件,並將其複製到 kids 陣列中。
雖然這是有效的,但這是非常必要的(參見程式設計範例)編碼方式。你可能有所懷疑,這有什麼不對?要理解這一點,讓我們首先熟悉兩個朋友map
和filter
。
map
和filter
在 2015 年,map
和filter
作為 ES6 特性集的一部分被引入 JavaScript。它們是陣列的方法,允許在 JavaScript 中進行更多函數語言程式設計。像在函數語言程式設計世界中一樣,這兩種方法都沒有改變原始陣列。相反,它們都返回一個新陣列。它們都接受函式型別的單個引數。然後在原始陣列中的每一項上呼叫此函式以生成結果陣列。讓我們看看這些方法的作用:
map filter
在同一個團體中他們也有第三個朋友,但較少使用。這位朋友的名字是
reduce
。
以下是可以檢視實際操作結果的簡單示例:
const numbers = [1, 2, 3, 4, 5]; const doubled = numbers.map(number => number * 2); // [2, 4, 6, 8, 10] const even = numbers.filter(number => number % 2 === 0); // [2, 4] 複製程式碼
既然我們知道map
和filter
會做什麼,讓我們接下來看一個我希望前面的示例應當如何編寫的例子:
const kids = people .filter(person => person.age < 15) .map(person => ({ id: person.id, name: person.name })); 複製程式碼
如果您想知道map
中使用的 lambda 的語法,請參閱此Stack Overflow answer
以獲取解釋。
那麼這個實現究竟有什麼好處:
- 關注點分離:過濾和更改資料格式是兩個獨立的問題,使用單獨的方法可以分離關注點。
-
可測試性:為實現這兩個目的,一個簡單的、純函式的方法可以輕鬆地針對各種行為進行單元測試。值得注意的是,初始實現並不像它依賴於其範圍 (
kids
陣列)之外的某些狀態那樣純粹。 -
可讀性:由於這些方法具有過濾資料或更改資料格式的明確目的,因此很容易看出正在進行何種操作。特別是因為有那些同類功能的函式,如
reduce
。 -
非同步程式設計:
forEach
和async
/await
不能很好地協同工作。另一方面,map
提供了一個能夠結合 promises 和async
/await
的有效模式。在下一篇博文中有關於此問題的更多資訊。
另一個值得注意的地方是,當你想引起副作用時(例如更改全域性狀態),不應當使用map
。特別是在不使用或儲存map
方法的返回值的情況下。
結論
map
和filter
的使用提供了許多好處,例如關注點分離、可測試性、可讀性和對非同步程式設計的支援。因此,對我來說這是一個明智的選擇。然而,我經常遇到使用forEach
的開發人員。雖然函數語言程式設計可能令人害怕,這些方法有也具有來自該世界的某些特徵,對它們並不用害怕。在響應式程式設計中,map
和filter
也被大量使用,感謝RxJS 的貢獻,響應式程式設計現在越來越多地在 JavaScript 世界中使用。因此,下次你要寫一個forEach
時,首先要考慮其他方法。但要注意,它們可能會永久改變您的編碼方式。
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為掘金 上的英文分享文章。內容覆蓋Android 、iOS 、前端 、後端 、區塊鏈 、產品 、設計 、人工智慧 等領域,想要檢視更多優質譯文請持續關注掘金翻譯計劃 、官方微博、知乎專欄 。