搜尋
首頁web前端js教程使用地圖並減少功能性JavaScript

Using Map and Reduce in Functional JavaScript

核心要點

  • JavaScript原生Array對象的map()reduce()方法是強大的函數式編程工具,可以使代碼更簡潔、易讀且易於維護。
  • map()是基本的函數式編程技術,它作用於數組中的所有元素,並生成另一個長度相同的數組,其中包含轉換後的內容。通過向數組對象添加映射功能,ECMAScript 5 將基本的數組類型變成了一個完整的函子,使函數式編程更容易上手。
  • reduce()方法(也是ECMAScript 5中的新增方法)類似於map(),但它不是生成另一個函子,而是生成單個結果,該結果可以是任何類型。它按順序將函數應用於數組的每個元素,以便將數組簡化為單個輸出值。
  • 雖然map()reduce()方法可能會影響性能,但如今使用它們帶來的代碼質量和開發人員滿意度的提升,很可能超過對性能的任何暫時影響。作者建議使用函數式技術進行開發,並在實際情況下衡量影響,然後再決定map()reduce()是否適合某個應用程序。

ECMAScript 6 的眾多令人驚嘆的新特性相關的流程討論甚囂塵上,很容易讓人忘記ECMAScript 5 為我們在JavaScript 中支持函數式編程提供了一些很棒的工具,而這些工具我們今天就可以使用。其中包括基於 JavaScript Array 對象的原生 map()reduce() 方法。

如果您現在還沒有使用 map()reduce(),那麼現在就開始吧!大多數現代 JavaScript 平台都原生支持 ECMAScript 5。映射和規約可以使您的代碼更簡潔、更易於閱讀和維護,並引導您走向更優雅的函數式開發。

性能:注意事項

當然,在需要的情況下,必須將代碼的閱讀和維護與性能相平衡。目前,瀏覽器使用更繁瑣的傳統技術(例如for循環)的效率更高。

我的方法通常是首先編寫易於閱讀和維護的代碼,然後如果我在實際情況下注意到問題,則優化性能。過早優化是萬惡之源。

還值得考慮的是,隨著瀏覽器對 map()reduce() 進行優化,使用這些方法可能會更好地利用 JavaScript 引擎的改進。除非我面臨性能問題,否則我更喜歡樂觀地編寫代碼,並將使我的代碼不那麼吸引人的性能調整放在我的後備口袋裡,以防我需要它們。

使用 Map

映射是作用於數組中所有元素並生成另一個長度相同的數組(包含轉換後的內容)的基本函數式編程技術。

為了更具體一些,讓我們想出一個簡單的用例。例如,假設您有一個單詞數組,您需要將其轉換為包含每個單詞長度的數組。 (我知道,這並不是您通常需要為複雜的應用程序執行的那種複雜的火箭科學,但是理解它在這種簡單情況下的工作原理將幫助您在它可以為您的代碼增加實際價值的情況下應用它)。

您可能已經知道如何使用數組上的for循環來完成我剛才描述的操作。它可能看起來像這樣:

var animals = ["cat","dog","fish"];
var lengths = [];
var item;
var count;
var loops = animals.length;
for (count = 0; count < loops; count++) {
  item = animals[count];
  lengths.push(item.length);
}
console.log(lengths); //[3, 3, 4]

我們所做的只是定義了一些變量:一個名為animals 的數組,其中包含我們的單詞;一個名為lengths 的空數組,它將包含我們操作的輸出;以及一個名為item 的變量,用於臨時存儲我們將要在數組的每個循環中操作的每個項目。我們使用一個帶有臨時內部計數器變量的for循環和一個loops變量來優化我們的for循環。然後,我們迭代了直到 animals 數組長度的每個項目。對於每一個項目,我們計算其長度,並將其推送到 lengths 數組中。

注意:可以說,我們可以通過直接將 animals[count] 的長度推送到 lengths 數組而無需中間賦值來更簡潔地完成此操作。這將節省我們一些代碼,但也會使代碼的可讀性降低,即使對於這個非常簡單的示例也是如此。同樣,為了使它更有效率,但不太直接,我們可以使用已知的 animals 數組長度來初始化我們的 lengths 數組為 new Array(animals.length),然後通過索引插入項目而不是使用 push。這完全取決於您將在現實世界中如何使用代碼。

這種方法在技術上沒有任何問題。它應該在任何標準的 JavaScript 引擎中都能工作,並且它將完成工作。但是,一旦您知道如何使用 map(),這樣做就會顯得笨拙。

讓我向您展示我們如何使用 map() 來處理這個問題:

var animals = ["cat","dog","fish"];
var lengths = animals.map(function(animal) {
  return animal.length;
});
console.log(lengths); //[3, 3, 4]

在這種情況下,我們再次從 animals 數組變量開始。但是,我們聲明的唯一其他變量是 lengths,我們將它的值直接賦值給將匿名內聯函數映射到 animals 數組的每個元素的結果。該匿名函數對每個動物執行操作,返回長度。結果,lengths 成為與原始 animals 數組長度相同的數組,包含每個單詞的長度。

關於這種方法需要注意幾點。首先,它比原來的方法短得多。其次,我們必須聲明的變量要少得多。變量越少,全局命名空間中的噪聲就越少,如果同一代碼的其他部分使用相同名稱的變量,則衝突的機會就越少。此外,我們的變量從頭到尾都不需要更改其值。當您深入研究函數式編程時,您將欣賞使用常量和不可變變量的優雅能力,而且現在就開始學習也為時不晚。

這種方法的另一個優點是,我們有機會通過分離命名函數來提高其多功能性,從而在過程中生成更簡潔的代碼。匿名內聯函數可能看起來很凌亂,並且使代碼重用變得更加困難。我們可以定義一個名為 getLength() 的函數,並通過這種方式在上下文中使用它:

var animals = ["cat","dog","fish"];
var lengths = [];
var item;
var count;
var loops = animals.length;
for (count = 0; count < loops; count++) {
  item = animals[count];
  lengths.push(item.length);
}
console.log(lengths); //[3, 3, 4]

看看這看起來多麼乾淨?僅僅將映射作為您的工具包的一部分就可以將您的代碼提升到一個全新的函數式級別。

什麼是函子?

有趣的是,通過向數組對象添加映射功能,ECMAScript 5 將基本的數組類型變成了一個完整的函子,使函數式編程更容易為我們所有人所用。

根據經典的函數式編程定義,函子滿足三個條件:

  1. 它包含一組值
  2. 它實現一個作用於每個元素的映射函數
  3. 它的映射函數返回大小相同的函子

這是在您下次 JavaScript 聚會上可以討論的一個話題。

如果您想了解更多關於函子的信息,請查看 Mattias Petter Johansson 的這個精彩視頻。

使用 Reduce

reduce() 方法也是 ECMAScript 5 中的新增方法,它類似於 map(),不同之處在於它不是生成另一個函子,而是生成單個結果,該結果可以是任何類型。例如,假設您想將 animals 數組中所有單詞的長度之和作為一個數字。您可能會從以下操作開始:

var animals = ["cat","dog","fish"];
var lengths = animals.map(function(animal) {
  return animal.length;
});
console.log(lengths); //[3, 3, 4]

在定義初始數組後,我們為運行總計創建一個變量 total,最初設置為零。我們還創建了一個變量 item 來保存 animals 數組在遍歷for循環時的每次迭代,以及一個變量 count 用於循環計數器,以及一個 loops 變量來優化我們的迭代。然後,我們運行一個for循環來迭代 animals 數組中的所有單詞,並將每個單詞賦值給 item 變量。最後,我們將每個項目的長度添加到我們的總計中。

同樣,這種方法在技術上沒有任何問題。我們從一個數組開始,最終得到一個結果。但是,使用 reduce() 方法,我們可以使這個過程更直接:

var animals = ["cat","dog","fish"];
var lengths = [];
var item;
var count;
var loops = animals.length;
for (count = 0; count < loops; count++) {
  item = animals[count];
  lengths.push(item.length);
}
console.log(lengths); //[3, 3, 4]

這裡發生的情況是,我們正在定義一個新變量 total,並將其賦值給使用兩個參數減少 animals 數組的結果:一個匿名內聯函數和一個初始運行總計值零。減少會遍歷數組中的每個項目,對該項目執行函數,並將其添加到傳遞給下一次迭代的運行總計中。這裡我們的內聯函數有兩個參數:運行總和和當前正在從數組中處理的單詞。該函數將 total 的當前值添加到當前單詞的長度。

請注意,我們將 reduce() 的第二個參數設置為零,這表明 total 將包含一個數字。如果沒有第二個參數,reduce 方法仍然可以工作,但結果不一定是您期望的結果。 (試一試,看看當省略運行總計時,JavaScript 使用的邏輯是什麼。)

由於在調用 reduce() 方法時集成了匿名內聯函數的定義,這可能看起來比需要復雜一點。讓我們再次這樣做,但讓我們首先定義一個命名函數,而不是使用匿名內聯函數:

var animals = ["cat","dog","fish"];
var lengths = animals.map(function(animal) {
  return animal.length;
});
console.log(lengths); //[3, 3, 4]

這個稍微長一些,但長並不總是壞事。以這種方式查看它應該使 reduce 方法發生的事情更清晰一些。

reduce() 方法有兩個參數:一個應用於數組中每個元素的函數,以及一個用於運行總計的初始值。在這種情況下,我們傳遞一個名為 addLength 的新函數的名稱和運行總計的初始值零。我們創建了 addLength() 函數,以便它也接受兩個參數:運行總和和要處理的字符串。

結論

養成定期使用map()reduce() 的習慣將為您提供替代方法,使您的代碼更簡潔、更通用、更易於維護,並為您鋪平使用更多函數式JavaScript 技術的道路。

map()reduce() 方法只是添加到 ECMAScript 5 的新方法中的兩個。很可能,您今天使用它們所看到的代碼質量和開發人員滿意度的提高將遠遠超過對性能的任何暫時影響。使用函數式技術進行開發,並在現實世界中衡量影響,然後再決定 map()reduce() 是否適合您的應用程序。

本文由 Panayiotis Velisarakos、Tim Severien 和 Dan Prince 共同評審。感謝所有 SitePoint 的同行評審者,使 SitePoint 內容達到最佳狀態!

關於函數式 JavaScript 中 Map-Reduce 的常見問題 (FAQ)

JavaScript 中 Map 和 Reduce 之間的區別是什麼?

在 JavaScript 中,Map 和 Reduce 都是作用於數組的高階函數。 Map 函數用於通過將函數應用於原始數組的每個元素來創建一個新數組。它不會修改原始數組,而是返回一個新數組。另一方面,Reduce 函數用於將數組簡化為單個值。它按順序將函數應用於數組的每個元素,以便將其簡化為單個輸出值。

Map 函數在 JavaScript 中是如何工作的?

JavaScript 中的 Map 函數通過從現有數組創建一個新數組來工作。它通過將指定的函數應用於原始數組中的每個元素來實現此目的。該函數按順序為數組中的每個元素調用一次。結果是一個包含函數調用結果的新數組。

Reduce 函數在 JavaScript 中是如何工作的?

JavaScript 中的 Reduce 函數通過按順序將函數應用於數組中的每個元素,以便將數組簡化為單個輸出值來工作。輸出值是函數調用的累積結果。該函數接受兩個參數:累加器和當前值。累加器累積函數調用的返回值。

我可以在 JavaScript 中同時使用 Map 和 Reduce 嗎?

是的,您可以在 JavaScript 中同時使用 Map 和 Reduce。事實上,它們經常在函數式編程中一起使用。您可以使用 Map 函數轉換數組中的每個元素,然後使用 Reduce 函數將轉換後的元素組合成單個輸出值。

JavaScript 中 Map 和 ForEach 之間的區別是什麼?

Map 和 ForEach 都是 JavaScript 中作用於數組的高階函數。它們之間的主要區別在於,Map 通過將函數應用於原始數組的每個元素來創建一個新數組,而 ForEach 應用於數組的每個元素以獲得其副作用。 ForEach 不會返回新數組。

我如何使用 Map 函數在 JavaScript 中轉換數組?

您可以使用 JavaScript 中的 Map 函數通過將函數應用於數組的每個元素來轉換數組。該函數按順序為數組中的每個元素調用一次。結果是一個包含函數調用結果的新數組。

我如何使用 Reduce 函數在 JavaScript 中組合數組的元素?

您可以使用 JavaScript 中的 Reduce 函數將數組的元素組合成單個輸出值。該函數按順序應用於數組中的每個元素,輸出值是函數調用的累積結果。

Map 函數在 JavaScript 中的一些常見用例是什麼?

JavaScript 中的 Map 函數通常用於通過將函數應用於數組的每個元素來轉換數組。一些常見用例包括將字符串轉換為數字、更改字符串的大小寫以及從對像中提取屬性。

Reduce 函數在 JavaScript 中的一些常見用例是什麼?

JavaScript 中的 Reduce 函數通常用於將數組的元素組合成單個輸出值。一些常見用例包括求和數字、查找最大值或最小值以及連接字符串。

如何調試 JavaScript 中的 Map 或 Reduce 函數?

您可以通過在函數中使用 console.log 語句來顯示變量和表達式的值來調試 JavaScript 中的 Map 或 Reduce 函數。您還可以使用 debugger 語句暫停執行並在 Web 瀏覽器的開發者工具中檢查變量和表達式的值。

以上是使用地圖並減少功能性JavaScript的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JavaScript在行動中:現實世界中的示例和項目JavaScript在行動中:現實世界中的示例和項目Apr 19, 2025 am 12:13 AM

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境