多且易亂的數組方法 js 中對數組操作比比皆是,不管是單純前端操作數組變數,還是後臺返回的數組形式介面數據,都需要用到數組一些方法操作數組。不知道大家是不是和我一樣經常忘記或混亂數組一些方法,什麼 ,`some() reduce()`等等,還有哪些會改變原始數組哪些返回新數組,真是一頭霧水。 來張圖 ...
多且易亂的數組方法
js 中對數組操作比比皆是,不管是單純前端操作數組變數,還是後臺返回的數組形式介面數據,都需要用到數組一些方法操作數組。不知道大家是不是和我一樣經常忘記或混亂數組一些方法,什麼 find()
,some()
,reduce()
等等,還有哪些會改變原始數組哪些返回新數組,真是一頭霧水。
來張圖片壓壓驚
這張圖是我收藏的數組方法圖,上面列出了常見的數組方法及解釋,界面很舒服,應該一看就懂。
看我整理
構造函數 Array
專屬
Array
構造函數的方法常見有三種:
Array.isArray(obj)--- 判斷對象是否為數組,返回布爾
Array.isArray([]) // true
Array.isArray({}) // false
創建新數組
下麵兩種方法意在創建新數組,所以我總結在一個大類裡面。
比較常見的有兩種創建形式,大家可以理解分類記憶。
- 可以指定規則:從一個迭代器對象或一個偽數組按照一定規則生成新的數組。
Array.from(arrayLike[, mapFn[, thisArg]])
參數:
arrayLike
想要轉換成數組的偽數組對象或可迭代對象。
mapFn
(可選參數)
既然有規則,必定需要指定規則函數。
thisArg
(可選參數)
可選參數,執行回調函數 mapFn 時 this 對象。
Array.from('foo')
// ["f", "o", "o"]
let m = new Map([[1, 2], [2, 4], [4, 8]])
Array.from(m)
// [[1, 2], [2, 4], [4, 8]]
Array.from([1, 2, 3], x => x + x)
// [2, 4, 6]
- 沒有規則,直接生成
Array.of(element0[, element1[, ...[, elementN]]])
參數:
任意參數
Array.of(1) // [1]
Array.of(1, 2, 3) // [1, 2, 3]
Array.of(undefined) // [undefined]
實例對象專屬
實例對象的方法是最多的,也是大家容易混淆的,推薦大家從三個大類去記憶。
可以改變原數組(9個)
splice()
刪除元素並且向數組添加新元素
array.splice(index,howmany,item1,.....,itemX)
參數:
index
:必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。
howmany
:必需。要刪除的項目數量。如果設置為 0,則不會刪除項目。
item1, ..., itemX
: 可選。向數組添加的新項目。
var fruits = ["Banana", "Orange", "Apple", "Mango"]
fruits.splice(2,1,"Lemon","Kiwi")
// 結果
// [Banana,Orange,Lemon,Kiwi,Mango]
splice() 方法在 ES5 中常用來數組去重,相當經典。
var arr = [1,2,2,3,4,2]
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //如果第一個和第二個一樣,splice方法減去第二個;
arr.splice(j,1)
// 設置j-- 防止刪除元素後,下麵第一位元素遺漏
j--
}
}
}
// arr [1, 2, 3, 4]
sort()
排序數組
參數:排序規則函數或無參數
沒有參數:則按照元素的字母升序,如果不是元素不是字元串的話,會調用toString()方法將元素轉化為字元串的Unicode(萬國碼)位點,然後再比較字元。
排序規則函數:排序規則函數接受兩個參數:a , b,返回一個正數或負數。這裡教大家一個簡單記憶方法:升序不變返回負,降序改變返回正
。
var a = [1,3,3,5,2,0]
a.sort()
// [0, 1, 2, 3, 3, 5]
a.sort((a, b) => {
return a-b // 升序不變返回負,不變指參數位置不變
})
// [0, 1, 2, 3, 3, 5]
a.sort((a, b) => {
return b-a // 降序改變返回正
})
// [5, 3, 3, 2, 1, 0]
下麵就是兩組頭尾刪除和添加方法,可以對應記憶
尾部操作
pop()
刪除數組最後的一個元素並且返回
參數: 無
push(item1, item2...)
數組的末尾添加元素並返回新長度
參數:要添加的新元素
// 刪除
var a = [1, 3, 5, 7, 9]
a.pop() // [1, 3, 5, 7]
// 添加
a.push(9, 11)
// [1, 3, 5, 7, 9, 11]
頭部操作
shift()
刪除數組第一個元素並返回
參數: 無
unshift(item1, item2...)
數組頭部添加元素並返回新長度
參數:要添加的新元素
// 刪除
var a = [1, 3, 5, 7, 9]
a.shift() // [1, 3, 5, 7]
// 添加
a.unshift(0) // [0, 1, 3, 5, 7]
reverse()
顛倒數組中元素的順序
參數: 無
let a = [1,2,3]
a.reverse()
console.log(a) // [3,2,1]
下麵是 ES6 新增的兩個方法
fill(item, start, end)
用指定元素填充數組
參數:
item
(必需): 要填充數組的值
start
(可選): 填充的開始位置,預設值為0
end
(可選):填充的結束位置,預設是為this.length
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
copyWithin(target, start, end)
指定位置的成員複製到其他位置並返回替換後的新數組。
參數:
target
(必需):從該位置開始替換數據。如果為負值,表示倒數。
start
(可選):從該位置開始讀取數據,用哪些數據來替換,預設為 0。如果為負值,表示倒數。
end
(可選):到該位置前停止讀取數據,預設等於數組長度。使用負數可從數組結尾處規定位置。
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]
var a=['a','b','c','d','e','f','g','h','i','j']
// 2位置開始被替換,3位置開始讀取要替換的 5位置前面停止替換
a.copyWithin(2,3,5)
// ["a","b","d","e","e","f","g","h","i","j"]
這裡可以總結下:
替換前後數組的長度保持不變;
讀取數據在終止位置的前一個位置停止,並且保存這個位置的數據不動
讀取出來了多少數據,就需要在前面按順序替換掉多少數據。
上面大類屬於可以改變原數組的實例方法,下麵一大類當然就是不改變原數組了。
不改變原數組(8個)
slice(start, end)
截取數組片段,返回新數組
參數:
start:(可選)規定從何處開始選取,負數表示從數組尾部算起
end: (可選)沒指定則一直截取到數組最後一個元素,包括最後一個。指定了則截取到指定位置前一個元素。
[1, 2, 3, 4].slice()
// [1, 2, 3, 4]
[1, 2, 3, 4].slice(1)
// [2, 3, 4]
[1, 2, 3, 4].slice(1, 3)
// [2, 3]
join(str)
按照連接符將數組連接成字元串並返回字元串
參數:
沒有參數: 則使用 ,
連接
有參數: 按照參數指定連接符連接
let a= ['hello','world']
let str=a.join() // 'hello,world'
let str2=a.join('+') // 'hello+world'
特別註意:當原始數組中含有對象時,使用 join()
方法連接時會把對象轉成 [object Object]
字元串,看下麵:
var b = [{name: 'pubdreamcc', age: 24}, 'test']
b.join()
// [object Object],test
cancat(item1,item2...)
合併多個數組並返回
參數:
可以是數組對象:等待合併的數組
也可以是具體的值(元素): 等待合併的元素
var a = [1, 2, 3]
var b = [4, 5, 6]
a.concat(b)
// [1, 2, 3, 4, 5, 6]
a.concat(4, 5, 6)
// [1, 2, 3, 4, 5, 6]
toLocaleString()
數組轉字元串
參數: 無
該方法同樣也是數組轉字元串,是將數組中每一個元素調用自身的toLocaleString()
方法後用 ,
連接得到的字元串。
可以理解為先把數組中每個元素都調用下 toLocaleString()
方法,再把得到的結果數組調用 join()
方法。
let a=[{name:'pubdreamcc'},24,'cc',new Date()]
a.toLocaleString()
// [object Object],24,cc,2019/7/18 下午1:52:20
toString()
數組轉字元串
這個方法應該比較熟悉,它是定義在 Object
原型上面的一個方法,用來把一個對象轉成字元串,在這裡其實同 join(無參數)
方法效果一樣。
實際開發中不推薦使用。
indexOf(item, start)
查找數組某個元素並返回其第一次出現位置下標
參數:
item
(必需): 需要查找的元素值
start(可選)
: 規定在數組中開始檢索的位置(0-array.length)
如果沒找到,返回 -1
var a = [1, 2, 1]
a.indexOf() // -1
a.indexOf(1) // 0
a.indexof('1') // -1
註意: indexOf()不能識別NaN, 因為 NaN 與任何數不相等,包括自身。
lastIndexOf(item, fromIndex)
查找數組某個元素並返回其最後一次出現位置下標
該方法與 indexOf()
恰好相反,查找不到同樣返回 -1
參數:
item
(必需): 被查找的元素
fromIndex
(可選): 逆向查找開始位置,預設值數組的長度-1,即查找整個數組。
let a=['cc',4,'pubdreamcc',1,2,'pubdreamcc',3,4,5,'pubdreamcc'] // 數組長度為10
// let b=a.lastIndexOf('pubdreamcc',4) // 從下標4開始往前找 返回下標2
// let b=a.lastIndexOf('pubdreamcc',100) // 大於或數組的長度 查找整個數組 返回9
// let b=a.lastIndexOf('pubdreamcc',-11) // -1 數組不會被查找
let b=a.lastIndexOf('pubdreamcc',-9) // 從第二個元素4往前查找,沒有找到 返回-1
下麵這個方法是 ES7 中新增
includes(item, fromIndex)
查找數組是否包含某個元素返回布爾
參數:
item
(必需):要查找的元素
fromIndex
(可選): 預設值為0,參數表示搜索的起始位置,接受負值。正值超過數組長度,數組不會被搜索,返回false。負值絕對值超過長數組度,重置從0開始搜索。
註意: includes()方法可以檢測 NaN
let a=['cc','pubdreamcc',1,NaN]
// let b=a.includes(NaN) // true 識別NaN
// let b=a.includes('pubdreamcc',100) // false 超過數組長度 不搜索
// let b=a.includes('pubdreamcc',-3) // true 從倒數第三個元素開始搜索
// let b=a.includes('pubdreamcc',-100) // true 負值絕對值超過數組長度,搜索整個數組
總結完了數組的基本兩大類方法後,接下來我們開始上數組的遍歷方法。
遍歷方法 (12個)
數組的遍歷也是非常重要,在實際項目開發中用的很多,不同的場景使用不同的遍歷方法可以加快我們開發速度。
數組的遍歷並不會改變原始數組。
forEach(func, thisValue)
遍曆數組,為每一項執行一次回調函數
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
array.forEach((value, index, arr) => {}, thisValue)
關於 forEach()
這裡需要註意的幾點:
無法中途退出迴圈,只能用return退出本次回調,進行下一次回調。
它總是返回 undefined值,即使你return了一個值。
如果在回調中需要更改數組中的基本類型數據,請使用
array[index] = XXX
,不能直接給value
賦值。
every(func, thisValue)
檢測數組所有元素是否都符合判斷條件返回布爾
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
如果有一項元素執行回調返回false
,剩餘元素不再執行回調,整個方法返回 false
如果所有元素都滿足條件,則整個方法返回 true
。
[12, 5, 8, 130, 44].every(x => x >= 10) // 判斷數組中每個元素是否大於或等於 10
// false
some(func, thisValue)
檢測數組中的是否有滿足條件的元素返回布爾
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
some()
恰好和 every()
相反,只要數組中有一項滿足條件判斷,則整個方法返回 true
,如果全部元素都不滿足條件,則返回 false
。
[12, 5, 8, 130, 44].every(x => x >= 10) // 判斷數組中是否有元素大於或等於 10
// true
filter(func, thisValue)
按照條件過濾原始數組返回新數組
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
var arr1 = [1, 3, 8, 4, 6, 7, 2]
var arr2 = arr1.filter((item, index)=>{return item > 5})
// 從原數組中過濾出大於 5 的元素
// [6, 7, 8]
map(func, thisValue)
對數組中每個元素進行一次回調,返回回調返回的元素組成的數組
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
可以發現這個幾個方法的參數都一樣,只是返回值不同而已。
let a1 = ['1','2','3','4']
let a2 = a1.map((value, index) => {
return +value
})
// [1, 2, 3, 4]
reduce(func, initialValue)
為數組提供一個累加器,把數組合併為一個值
reduce()
方法很多人搞的不是很清楚,也包括自己,講真的這個方法還真有點繞,但是弄明白之後確實可以給我們帶來很多的便利。
參數:
func
(必需):指定的回調函數
initialValue
(可選):傳遞給回調的初始值,說白了即是回調第一個參數 prev
的初始值。
func(prev, curr, currIndex, arr)
參數解析:
prev
(必需): 函數上一次 return
回來的值。如果提供了 initialValue
,則初始值為initialValue
,如果沒有提供,則 prev
初始值為數組第一個元素。
curr
(必需): 當前執行回調時,數組中的元素
currIndex
(可選): 當前執行回調時,數組中元素的下標
arr
(可選):當前元素所屬的數組對象
利用 reduce() 方法 我們操作數組更加方便,例如一些常見的例子:
- 數組元素求和
var arr = [1, 3, 5, 7, 9]
var sum = arr.reduce((prev, curr) => {
return prev+curr
})
// 25
- 統計數組中元素出現的次數
var arr = ['cc', 'cc1', 'cc', 'cc2', 'cc1', 'cc', 'cc5']
var obj = arr.reduce((prev, curr) => {
if (!prev[curr]) {
prev[curr] = 1
} else {
prev[curr] += 1
}
return prev
}, {})
// {'cc': 3, 'cc1': 2, 'cc2': 1, 'cc5': 1}
reduceRight(func, initialValue)
從右至左的方向把數組累加為一個值
該方法同上面講的 reduce() 方法使用基本一致,只不過累加的方式為數組的末尾向前將數組中的數組項做累加。
下麵幾個關於遍歷的方法是 ES6 新增的,一種關於查找,一種是關於遍歷。
find(func, thisValue)
找出第一個符合條件的數組成員並返回
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
如果沒有找到,則返回 undefined
var arr = [1, 3, 5, 7]
var num = arr.find((item, index) => {return item > 1})
// 3
findIndex(func, thisValue)
找出第一個符合條件的數組成員下標並返回
參數:
func
(必需):指定的回調函數
thisValue
(可選):當執行回調函數時this
綁定對象的值,預設值為undefined
如果沒有找到則返回 -1
var arr = [1, 3, 5, 7]
var index = arr.findIndex((item, index) => {return item > 1})
// 1
註意:
這兩個方法都可以識別 NaN
,彌補了indexOf
的不足。
keys()&values()&entries()
遍歷鍵名、遍歷鍵值、遍歷鍵名+鍵值
這三種方法都會返回一個新的 Array Iterator
對象
array.keys()
返回一個包含數組所有下標組成的 Iterator。
array.values()
返回一個包含數組所有元素組成的 Iterator。
array.entries()
返回一個包含數組元素加下標組成的 Iterator。
返回的 遍歷器 可以用 ES6 提供的 for...of
迴圈來遍歷。
for (let index of ['pubdreamcc', 'pubdreamcc1'].keys()) {
console.log(index)
}
// 0
// 1
for (let item of ['pubdreamcc', 'pubdreamcc1'].values()) {
console.log(item)
}
// 'pubdreamcc'
// 'pubdreamcc1'
for (let [index, item] of ['pubdreamcc', 'pubdreamcc1'].entries()) {
console.log(index, item)
}
// 0 "pubdreamcc"
// 1 "pubdreamcc1"
結語
花了將近一下午的時間來整理出數組的一些方法,希望自己能夠更加清晰包括理解 它們 的用法,當然最最重要還是在平時擼碼的過程中能夠運用到對的地方加快開發效率,畢竟咱們學技術還是要服務於產品,把技術變現呢。
最後,希望你能夠細心看完,保證你會有不一樣的收穫。
參考資料
路易斯 [深度長文]JavaScript數組所有API全解密