目錄
效能:一個警告
使用Map方法
什么是函子?
使用Reduce方法
結論
首頁 web前端 js教程 如何在JavaScript函數式程式設計裡使用Map和Reduce方法的詳解

如何在JavaScript函數式程式設計裡使用Map和Reduce方法的詳解

Mar 08, 2017 pm 02:53 PM

所有人都談論道workflows支援ECMAScript6裡出現的令人吃驚的新特性,因此我們很容易忘記ECMAScript5帶給我們一些很棒的工具方法來支援在JavaScript裡進行函數編程,這些工具方法我們現在可以使用了。在這些函數方法裡主要的是基於JavaScript 陣列物件的map()方法和reduce()方法。

如果你如今還沒有使用map()和reduce()方法,那麼現在是時候開始使用了。如今絕大部分的JavaScript開發平台都與生俱來的支援ECMAScript5。使用Map方法和reduce方法可以讓你的程式碼更加簡潔和更容易閱讀和更容易維護,而且把你帶到朝向更簡潔的功能開發的路上。

效能:一個警告

當然,當現實狀況需要保持提高效能時,你的程式碼的易讀性和易維護性不得不在兩者之間保持平衡。現今的瀏覽器使用較笨重的傳統技術例如for迴圈來執行的更有效率。

我寫程式碼的方式通常是把可讀性和可維護性放在編寫程式碼的第一位,然後如果我發現在現實情況裡程式碼運行出現了問題,再去為了提高效能而去優化程式碼。過早的最佳化程式碼是很困難的,而且這種最佳化會導致後面編寫程式碼很困難。

值得考慮的是在JavaScript引擎裡使用諸如map()和reduce()這樣的方法可以更好地改善程式碼的效能,而不是指望將來瀏覽器能為了改善效能而做出最佳化。除非我在一個效能問題上碰壁,否則我更喜歡開心地寫程式碼,然而以防我需要它們我卻隨時準備著為保持程式碼的效能而做出調整,儘管這樣做使我的程式碼減少了吸引力。

使用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迴圈,這個for迴圈有個內部變數和一個迴圈變數來初始化我們的for迴圈。然後我們循環迭代每一個項,直到迭代的數組長度等於animals數組的長度。每一次循環我們都計算迭代項的字元長度,然後把它存到lengths數組裡。

注意:需要討論的是我們可以把上面的程式碼寫得更簡潔些,不需要那個item變數,而直接把animals[count]的長度放到lengths數組裡,這樣就不需要中間的轉換過程了。這樣做可以幫我們省一點點程式碼空間,但它也讓我們的程式碼有點不易閱讀,即使是這個很簡單的例子也是如此。同樣地,為了使程式碼更有效率而少些直白,我們可能會使用已知的animals數組長度來透過new Array(animals.length)的方式來初始化我們的lengths數組,然後透過索引而不是使用push方法來插入選項資料長度。這取決於你在現實中準備如何去使用這些程式碼。

這種實作方式沒有任何的技術錯誤。它在任何標準的JavaScript引擎裡都可以用,而且它能很好的完成工作。一旦你知道怎麼使用map()方法了,透過這個方法來實現就顯得有些笨拙了。

讓我展示給你看使用map()方法是如何實現上面的程式碼的:

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

在這個小例子裡,我們首先再次為我們的animal類型的數組創建一個animals變數。然而,其他我們需要宣告的變數就是lengths變數了,然後我們直接分配它的值到映射一個匿名內聯函數到animals數組的每一個元素上的結果。

那個匿名函數執行在每個animal 上的操作,然後傳回該animal的字元長度。這樣做的結果是,lengths變成了具有與原始animals數組具有相同長度的數組,並且該數組包含了每個字元的長度。

这种方式需要注意的一些事情。首先,它比最初编写的代码更简洁。其次,我们仅需要申明更少的变量。更少的变量意味着在全局命名空间里杂音更少,并且如果相同代码的其他部分使用了相同的变量名就会减少碰撞的机会。最后,我们的变量不可能从头到脚都会改变它们的值。随着你深入函数式编程,你将会欣赏使用常量和不变的变量的优雅的能力,现在开始使用并不算早。

这种实现方式的另一个优点是,我们可以通过在整个代码编写过程中通过将代码放进一个个命名的函数里而简化代码而有机会提升自己编写代码的多功能性。匿名的内联函数看着有些乱,并且使得重复使用代码更困难。我们可以定义一个命名为getLength()的函数,并且像下面的方式来使用:

var animals = ["cat","dog","fish"];
function getLength(word) {
  return word.length;
}
console.log(animals.map(getLength)); //[3, 3, 4]
登入後複製

看看上面的代码看上去多简洁啊?只是把你处理数据的部分映射一下就使你的代码达到一个全新的功能水平。

什么是函子?

有趣的一点是,通过在数组对象里添加映射,ECMAScript5把基本的数组类型变成了一个完整的函子,这使得函数式编程对我们来说更加的容易。

根据传统的函数编程定义,一个函子需要满足三个条件:

  • 1.它保存着一组值。

  • 2.它实现了一个map函数来操作每一个元素。

  • 3.它的map函数返回一个具有同样大小的函子。

这个将会在你下一次的JavaScript聚会上被翻来覆去的讨论。

如果你想了解更多关于函子的信息,你可以看看Mattias Petter Johansson录制的关于这方面的视频。

使用Reduce方法

Reduce()方法在ECMAScript5里也是新增的,而且它和map()方法很类似,除了不产生其他的函子,reduce()方法产生的一个结果是它可能是任何类型。例如,设想一下,如果你想得到我们animals数组里的所有字符长度都分别作为一个数字然后相加的结果。你也许会像下面这样做:

var animals = ["cat","dog","fish"];
var total = 0;
var item;
for (var count = 0, loops = animals.length; count < loops; count++){
  item = animals[count];
  total += item.length;
}
console.log(total); //10
登入後複製

在我们定义我们的初始数组之后,我们为运行总计定义了一个total变量,并把它的初始值设为0。我们也定义一个变量item来保存每一次for循环迭代animals数组的迭代值,并且再定义一个count变量作为一个循环计数器,并且用这两个变量来初始化我们的迭代。然后我们运行for循环来迭代animals数组里的所有字符数据,每次迭代都会把迭代的结果保存到item变量。最终我们把每一次迭代到的item的长度加到我们的total变量里就可以了。

这种实现方式也没有任何的技术错误。我们从定义一个数组开始,然后得到一个结果值就结束了。但是如果我们使用了reduce()方法,我们可以使上面的代码更加简单明了:

var animals = ["cat","dog","fish"];
var total = animals.reduce(function(sum, word) {
  return sum + word.length;
}, 0);
console.log(total);
登入後複製

这里发生变化的是,我们定义了一个名为total的新变量,并且把执行animals数组对象的reduce方法的返回值分配给它,在reduce方法里有两个参数:一个匿名内联function方法,和初始化total的值为0。对于数组中的每一个项reduce()方法都会执行,它在数组的那一项上执行这个function函数,并且把它添加到运行总计,然后再进行下一次迭代。这里我们的内联function方法有两个参数:运行总计,和当前程序正在处理的从数组中获取的字符。这个function函数把当前total的值添加到当前word的长度上。

注意的是:我们设置reduce()方法的第二个参数值为0,这样做确定了total变量包含的是一个数值。如果没有第二个参数reduce方法仍然可以执行,但是执行的结果将不是你期望的那样。(你可以试试并且可以看看当运行总计结束后你是否能推测出JavaScript所使用的编程逻辑。)

那看上去似乎比它需要做的更有一点复杂,因为当调用reduce()方法时需要在一个内联function里综合的定义。我们再那么做一次,但是首先让我们定义一个命名的function函数,而不再使用匿名内联函数:

var animals = ["cat","dog","fish"];
var addLength = function(sum, word) {
  return sum + word.length;
};
var total = animals.reduce(addLength, 0);
console.log(total);
登入後複製

这个代码稍微有点长,但是代码有点长并不总是坏事。这样写你应该看到它使代码更加清晰些,只是在reduce()方法里发生了一点变化。

该程序里reduce()方法有两个参数:一个function函数,用来调用数组里的每一个元素,和一个为total变量设置的运行总计初始值。在这个代码示例中,我们放入了一个名为addLength的新function和为运行总计变量赋初始值为0。在上一行代码中,我们定义了一个名为addLength的function函数,这个函数也需要两个参数:一个当前和一个要处理的字符串。

結論

經常使用map()方法和reduce()方法將會為你的程式碼更加簡潔,更加多功能,更加可維護性提供了選擇。同時它們為你使用更多的JavaScript功能函數技術鋪平了道路。

map()方法和reduce()方法只是被加入到ECMAScript5中新方法中的兩個。從使用它們的今天你將會明白程式碼品質的提升和開發人員滿意度的提升勝過任何在效能上的臨時影響。在判斷map()方法和reduce()方法是否適合你的應用之前,試著用功能函數技術來開發和度量一下它在你現實世界裡的影響,然後再判斷是否去用。


###### ###

以上是如何在JavaScript函數式程式設計裡使用Map和Reduce方法的詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

最佳化Go語言map的效能 最佳化Go語言map的效能 Mar 23, 2024 pm 12:06 PM

最佳化Go語言map的效能在Go語言中,map是一種非常常用的資料結構,用來儲存鍵值對的集合。然而,在處理大量資料時,map的效能可能受到影響。為了提高map的效能,我們可以採取一些最佳化措施來減少map操作的時間複雜度,從而提升程式的執行效率。 1.預先分配map的容量在建立map時,我們可以透過預先分配容量來減少map擴容的次數,提高程式的效能。一般情況下,我們

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles