前端工程師都在用這些數組操作方法,你知道嗎?!

在 JavaScript 中,對於數組的操作非常頻繁,對應的 API 也很豐富 。ECMAScript 規範在每一版發佈時,都會提供新的 API 來增強數組的操作能力,下面將詳細介紹這些 API 的一些特性。


ES5 新增的 9 個API

forEach( callback, [thisArg] )

在 ES5 之前,我們可以通過 for 和 for in 兩種方式來遍歷數組。

ES5 引入了一個新方法 forEach,使數組遍歷更加簡潔,

forEach需要傳遞兩個參數,第一個參數是回調函數,是必選參數,第二個參數是一個對象,用來改變 callback 中的 this 指向,是可選參數。

前端工程師都在用這些數組操作方法,你知道嗎?!

輸出結果:

a 0 ['a', 'b', 'c']
b 1 ['a', 'b', 'c']
c 2 ['a', 'b', 'c']

callback 中傳入了3個參數 v,i,r 分別表示當前元素、當前位置、數組對象。

再看看使用 thisArg 的例子:

前端工程師都在用這些數組操作方法,你知道嗎?!

輸出結果:

a 0
b 1
c 2

不傳 thisArgs 時,callback 中的 this 默認指向 window 對象,當傳遞 thisArg 時,callback 中的 this 就指向了 thisArg.

因此這個參數的目的就是為了改變回調函數中的this指向。

對於不支持 ES5 的瀏覽器,我們可以對 forEach 進行簡單的擴展來兼容老的瀏覽器:

前端工程師都在用這些數組操作方法,你知道嗎?!


filter( callback , [thisArg] )

filter 是`過濾`的意思,所以這個方法的作用就是返回一個匹配過濾條件的新數組,其接收兩個參數 callback 和 thisArg,callback也是回調函數,主要用於對元素進行條件匹配,thisArg 和 forEach中的 thisArg 作用一樣,在這裡就不重複了,看下面示例:

前端工程師都在用這些數組操作方法,你知道嗎?!

打印newArr結果 ["a", "a"] 

沒有filter的時候,要實現這個功能,我們事先要創建一個空的數組,把匹配到的元素再 push 進去,現在就不需要那麼麻煩了,我們再看看對filter的擴展:

前端工程師都在用這些數組操作方法,你知道嗎?!

可以看出,filter 將過濾的結果作為一個新數組返回,即使符合條件的元素只有一個,返回的也是數組 。為了更方便的對單個元素進行查詢,ES6 在數組原型上提供了 find 方法,用於從數組中查詢單個符合條件的元素,和 filter 不同的是,它返回的是單個元素。

[2, 3, 5, 8, 9, 3].find(item => item == 3); // 3 

需要注意的是,find 只返回第一個匹配到的元素,如果沒有匹配到,則會返回 undefined 。和 filter 一樣,find 也可以傳遞第 2 個參數,用於設置回調函數的 this 指針 。


map( callback, [thisArg] )

map 的作用是對原數組進行加工處理後並將其作為一個新數組返回,該方法同樣接收兩個參數,callback 是回調函數用於對數組進行加工處理,thisArg 和上面的一樣。先看一個簡單的例子:

前端工程師都在用這些數組操作方法,你知道嗎?!

打印newArr[0] 結果:{w: 10, h: 10, area: 100}

可以看出,newArr 返回的是增加了 area 屬性的對象數組。這個方法非常實用,一般情況下,當一個ajax請求返回時,我們都要對其結果集進行過濾和校驗等操作,這時 map 就派上用場了。我們再看看如果對 map 進行兼容性擴展:

前端工程師都在用這些數組操作方法,你知道嗎?!


reduce ( callback, [initialValue] )

reduce 在這裡有`減少`的意思,其作用是對數組進行歸併操作,換句話說就是對數組每一個元素進行累加,最終返回所有元素之和。 回調函數 callback 接收4個參數:

previousValue - 存放的是上一次callback返回的結果,其初始值默認為數組的第一個元素。
currentValue - 是當前元素 。默認從數組的第二個元素開始。
currentIndex - 是當前元素位置 。
array - 是當前數組。
前端工程師都在用這些數組操作方法,你知道嗎?!

輸出結果:

1 2 1
3 3 2
6 4 3

打印newArr ---> 10

reduce 除過可以傳遞 callback 之外,還可以傳遞一個參數 initialValue ,作為數組累加的基數。當傳了這個參數以後,callback 中的 previousValue 初始值就被置為 initialValue,reduce 也改為從數組的第一個元素開始遍歷。

前端工程師都在用這些數組操作方法,你知道嗎?!

輸出結果:

100 1 0
101 2 1
103 3 2
106 4 3

打印newArr ---> 110

從結果可以看出,reduce 最終返回的是: previousValue + 數組本身歸併計算的結果。對 reduce 的 polyfill 實現如下:

前端工程師都在用這些數組操作方法,你知道嗎?!


reduceRight ( callback, [initialValue] )

和 reduce 的作用完全相同,唯一的不同是,reduceRight 是從右至左遍歷數組的元素。


some ( callback, [thisArg] )

some 是`某些、一些`的意思,其作用是對數組中的每一項執行回調函數,如果該函數對任一項返回 true,則停止遍歷,並返回 true 。

前端工程師都在用這些數組操作方法,你知道嗎?!

輸出結果:

1 0 [1, 2, 3, 4]
2 1 [1, 2, 3, 4]
3 2 [1, 2, 3, 4]

打印 result ---> true

some 檢測整個數組,只要當arr中有一個元素符合條件 item>2 就停止檢測和遍歷,並返回 true,以表示檢測到目標。這和我們在 for 循環中使用 break 語言的作用有點類似。

對於 some 的兼容性擴展如下:

前端工程師都在用這些數組操作方法,你知道嗎?!


every (callback, [thisArg])

every 是`每一個`的意思,其作用是對數組中的每一項執行回調函數,如果該函數對每一項都返回 true,則返回 true 。

前端工程師都在用這些數組操作方法,你知道嗎?!

輸出結果:

1 0 [1, 2, 3, 4]
2 1 [1, 2, 3, 4]
3 2 [1, 2, 3, 4]


打印result ---> false

當檢測第3個元素時,item<3 為 false,停止檢測,並返回 false,這說明every在檢測元素時,要求每一個元素都要符合條件 item<3,如果有一個不符合就停止檢測,並返回false。(你可以測試 item<5 時的運行結果,返回值一定是 true ) 。

那 every 到底有什麼作用呢? 當一個 for 循環使用了 break 語句後,我們想知道 for 循環是否正常的執行完時, 我們一般會通過檢測for中的索引 i==arr.length 來判斷,因此every 的作用就體現在這裡。

下面是對於 every 的兼容性擴展:

前端工程師都在用這些數組操作方法,你知道嗎?!


indexOf[searchElement, [fromIndex]]

indexOf() 用於查詢數組元素對應的索引位置,可以傳遞兩個參數,第一個參數是要匹配的元素,必須是簡單數據類型。第二個參數是指定查詢的起始位置。

// 默認從索引0的位置開始
[1, 2, 3, 5, 2].indexOf(2);// 1
// 指定從索引3的位置開始
[1, 2, 3, 5, 2].indexOf(2, 3);// 4

ndexOf() 返回的是元素在數組中的位置 。如果只想知道數組中是否存在某個元素,而不關心元素的位置,也可以使用 ES6 提供的 includes() 方法來判斷。

let a = [1, 2, 3];
a.includes(1);// true
a.includes(1, 1);// false

includes() 也是數組原型上的方法, 和 indexOf() 的傳參是一樣的。

需要注意的是,indexOf() 適用於數組元素是簡單類型的情況,而無法檢索對象數組的元素位置。

let arr = [{c: 1}, {c: 2}];// 對象數組
arr.indexOf({c: 1});// -1

對於這個問題,可以使用 forEach() 來遍歷數組,當找到符合條件的元素時,就可以獲取到對應的數組下標,而在 ES6 中,可以使用 findIndex() 達到同樣的目的。

findIndex() 也是用於查詢數組元素的位置,和 indexOf() 不同的是,它可以檢索對象數組的元素位置,但需要通過回調函數來指定匹配的元素。

//簡單數組
[1, 2, 3, 5].findIndex(item => item == 3);// 2
//對象數組
[{id: 1}, {id: 3}, {id: 5}].findIndex(item => item.id == 3);// 1

lastIndexOf[searchElement, [fromIndex]]

和 indexOf() 的作用完全相同,唯一的不同是,lastIndexOf() 是從右至左檢索數組元素。


分享到:


相關文章: