全面介紹JavaScript陣列方法

俠客有情劍無情發表於2020-01-15

隨著JavaScript的發展,JavaScriptArray也增加了許多方法。有必要全面瞭解一下。本文基本涵蓋了Array所有的方法介紹。

一、 檢測方法

Array.isArray()

判斷傳入的值是否是一個陣列。

// true
Array.isArray([1, 2, 3])
// false
Array.isArray({foo: 123})
// false
Array.isArray('foobar')   
// false
Array.isArray(undefined)  
複製程式碼

二、 建立陣列方法

Array.from()

Array.from()方法用於將類陣列物件可迭代物件轉為真正的陣列,並且返回一個新的,淺拷貝的陣列例項。

// 報錯
Array.from(undefined)
// 報錯
Array.from(null)
// ["f", "o", "o"]
console.log(Array.from('foo'))
// []
console.log(Array.from(''))
// []
console.log(Array.from(123))
// []
console.log(Array.from(NaN))

// arguments物件轉為陣列
function foo() {
  const args = Array.from(arguments)
  //true
  console.log(Array.isArray(args))
}
foo(1, 2, 3)

// NodeList物件轉為陣列
Array.from(document.querySelectorAll('p'))

// Set物件轉為陣列:['a','b']
Array.from(new Set(['a', 'b'])) 

// Map物件轉為陣列:[[1, 2], [2, 4]]
Array.from(new Map([[1, 2], [2, 4]])) 
複製程式碼

Array.from()可以傳入3個引數:

  1. 第一個引數(必填):想要轉換成陣列的類陣列物件或可迭代物件。
  2. 第二個引數(可選):陣列中的每個元素會執行該回撥函式。
  3. 第三個引數(可選):執行第二個引數回撥函式時需要繫結的this物件。
// 傳入第二個引數回撥函式:[2, 4, 6]
Array.from([1, 2, 3], x => x + x)
複製程式碼
let obj = {
  num: 1,
  handle: function(value){
    return n + this.num
  }
}
// 傳入第三個引數修改this指向:[2, 3, 4, 5, 6]
const arrs = Array.from([1, 2, 3, 4, 5], obj.handle, obj)
複製程式碼
// 得到陣列物件裡的id屬性:[1, 2]
const obj = [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'}]
Array.from(obj,(el) => {
  return el.id
})
複製程式碼

注意: Array.from(null)或者Array.from(undefined)會丟擲異常

Array.of()

Array.of()建立一個包含所有傳入引數的陣列,不考慮引數的數量或型別,返回一個新陣列。

使用Array.of()建立新陣列:

Array.of()                  // []
Array.of(undefined)         // [undefined]
Array.of(null)              // [null]
Array.of(NaN)               // [NaN]
Array.of(1)                 // [1]
Array.of(1, 2)              // [1, 2]
Array.of([1,2,3])           // [[1,2,3]]
Array.of({id: 1},{id: 2})   // [{id:1}, {id:2}]
複製程式碼

三、 遍歷(迭代)方法

forEach()

對陣列中的每一項執行指定的函式。這個方法返回undefined,即使你return了一個值。

Array.forEach()引數語法:

  1. 第一個引數(必填): callback在陣列每一項上執行的函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引 (可選) 陣列本身(可選)
  1. 第二個引數(可選):當執行回撥函式時用作 this 的值。
const arr = [{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'}]
// 1 - zhangsan
// 2 - lisi
arr.forEach(el => {
    console.log(`${el.id} - ${el.name}`);
});

const obj = {
  handle: function(n){
    return n + 2
  }
};
// true 
[{id: 1,name: 'zhangsan'},{id: 2,name: 'lisi'}].forEach(function(el,index,arr){
  if(el.id === 1) {
    return
  }
  console.log(this === obj)
},obj);
複製程式碼

Array.forEach()不能中斷迴圈(使用break,或continue語句)。只能用return退出本次回撥,進行下一次回撥。

map()

返回一個新陣列,結果是該陣列中的每個元素都呼叫提供的函式後返回的結果。

Array.map()引數語法:

  1. 第一個引數(必填): callback生成新陣列元素的函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引 (可選) 陣列本身(可選)
  1. 第二個引數(可選):當執行回撥函式時用作 this 的值。
const arr = [{id: 1},{id: 2},{id: 3}]
const newArr = arr.map((el,index,arr) => {
  el.age = 20
  return el
});
//[{id: 1,age: 20},{id: 2,age: 20},{id: 3,age: 20}]
console.log(newArr);
複製程式碼

filter()

對陣列中的每一項執行指定的函式,返回該函式會返回true的項組成的新的陣列。如果沒有任何陣列元素通過測試,則返回空陣列。

Array.filter()引數語法:

  1. 第一個引數(必填): callback用來測試陣列的每個元素的函式。返回true 表示該元素通過測試,保留該元素,false 則不保留。該函式接收三個引數:
element index array
當前元素 當前元素的索引 (可選) 陣列本身(可選)
  1. 第二個引數(可選):當執行回撥函式時用作 this 的值。
const arr = [{id: 1},{id: 2},{id: 3}]
const newArr = arr.filter((el,index,arr) => {
  el.age = 20
  return el
});
// [{id: 1,age: 20},{id: 2,age: 20},{id: 3,age: 20}]
console.log(newArr);
複製程式碼

some()

檢測陣列中的是否有滿足判斷條件的元素。

對陣列中的每一項執行指定的函式,如果該函式對任一項返回true,則返回true,並且剩餘的元素不會再執行檢測。如果沒有滿足條件的元素,則返回false

Array.some()引數語法:

  1. 第一個引數(必填): callback用來測試每個元素的函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引 (可選) 陣列本身(可選)
  1. 第二個引數(可選):當執行回撥函式時用作 this 的值。
const arr = [{id: 1},{id: 2},{id: 3}]
const someResult = arr.some((el,index,arr) => {
  return el.id === 1
});
// true
console.log(someResult)
複製程式碼

every()

檢測陣列所有元素是否都符合判斷條件。

對陣列中的每一項執行指定的函式,如果該函式對每一項都返回true,則返回true。若收到一個空陣列,此方法在一切情況下都會返回true。如果陣列中檢測到有一個元素不滿足,則返回 false,且剩餘的元素不會再進行檢測。

Array.every()引數語法:

  1. 第一個引數(必填): callback用來測試每個元素的函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引 (可選) 陣列本身(可選)
  1. 第二個引數(可選):當執行回撥函式時用作 this 的值。
// true
[].every(() => {})
複製程式碼
const arr = [{id: 1},{id: 2},{id: 3}]
const everyResult = arr.every((el,index,arr) => {
  return el.id > 0
});
// true
console.log(everyResult)
複製程式碼

find()

返回陣列中匹配的第一個元素的值,否則返回undefined

Array.find()引數語法:

  1. 第一個引數(必填): callback在陣列每一項上執行的函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引 (可選) 陣列本身 (可選)
  1. 第二個引數(可選):當執行回撥函式時 this 的值。
const arr = [{id: 1},{id: 2},{id: 3}]
const findResult = arr.find((el,index,arr) => {
  return el.id  === 1
},obj);
// {id: 1}
console.log(findResult)
複製程式碼

findIndex()

返回陣列中匹配的第一個元素的索引。否則返回-1

Array.findIndex()引數語法:

  1. 第一個引數(必填): callback在陣列每一項上執行的函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引值 陣列本身
  1. 第二個引數(可選):當執行回撥函式時 this 的值。
const arr = [{id: 1},{id: 2},{id: 3}]
// 2
const findResult = arr.findIndex((el,index,arr) => {
  return el.id  === 3
},obj)
複製程式碼

entries()keys()values()

用於遍歷陣列,它們都返回一個遍歷器Array Iterator物件。可以用for...of迴圈進行遍歷,他們的區別是keys()是對鍵名的遍歷、values()v是對鍵值的遍歷,entries()`是鍵值對的遍歷。

// 0
// 1
for (let i of ['a', 'b'].keys()) {
  console.log(i)
}

// a
// b
for (let el of ['a', 'b'].values()) {
  console.log(el)
}

// 0-a
// 1-b
for (let [i, el] of ['a', 'b'].entries()) {
  console.log(`${i}-${el}`)
}
複製程式碼

可以手動呼叫遍歷器物件的next方法,進行遍歷。

const arr = ['a', 'b', 'c']
const tempIterator = arr.entries()
// [0, "a"]
console.log(tempIterator.next().value)

// [1, "b"]
console.log(tempIterator.next().value)
複製程式碼

四、操作方法

push()

將一個或多個元素新增到陣列的末尾,並返回該陣列的新長度。

var numbers = [1, 2, 3]
// 5
console.log(numbers.push(4,5))
// [1,2,3,4,5]
console.log(numbers)
複製程式碼

pop()

從陣列中刪除最後一個元素,並返回刪除的元素。

const arr = ['a', 'b', 'c']
// c
console.log(arr.pop())
// ["a", "b"]
console.log(arr);
複製程式碼

shift()

shift() 方法從陣列中刪除第一個元素,並返回刪除的元素。

const arr = ['a', 'b', 'c']
// a
console.log(arr.shift())
// ["b", "c"]
console.log(arr)
複製程式碼

unshift()

將一個或多個元素新增到陣列的開頭,並返回該陣列的新長度(該方法修改原有陣列)。

const arr = ['a', 'b', 'c']
// 5
console.log(arr.unshift('d', 'e'))
// ["d", "e", "a", "b", "c"]
console.log(arr)
複製程式碼

concat()

用於合併兩個或多個陣列。此方法不會更改現有陣列,而是返回一個新陣列。如果省略引數,則concat會返回當前陣列的淺拷貝。

const arr = [1, 2, 3]
const newArr = arr.concat()
// [1,2,3]
console.log(newArr)
// false
console.log(newArr === arr)
複製程式碼
const arr = [1, 2, 3]
const newArr = arr.concat([4, 5])
// [1, 2, 3, 4, 5]
console.log(newArr)
複製程式碼

indexOf()lastIndexOf()

這兩個方法都返回要查詢的元素在陣列中的位置,或者在沒找到的情況下返回-1indexOf()方法從陣列的開頭開始向後查詢,lastIndexOf()方法則從陣列的末尾開始向前查詢。

Array.indexOf()、Array.lastIndexOf()引數語法:

  1. 第一個引數 searchElement(可選):被查詢的元素。
  2. 第二個引數 fromIndex(可選):indexOf()方法表示開始向後查詢的位置。預設值為0lastIndexOf()方法表示從此位置開始逆向查詢。預設為陣列的長度減 1 (arr.length - 1)。

indexOf()

const numbers = [1, 2, 3, 4, 5, 4]
// 3
console.log(numbers.indexOf(4))
// 5
console.log(numbers.indexOf(4, 4)) 
複製程式碼

lastIndexOf()

const numbers = [1, 2, 3, 4, 5, 4]
// 5
console.log(numbers.lastIndexOf(4))
// 3
console.log(numbers.lastIndexOf(4, 4))
複製程式碼

slice()

建立一個新的陣列並返回。該方法接受兩個引數:是一個由起始索引和結束索引的提取出來的原陣列的淺拷貝。原始陣列不會被改變。

Array.slice()引數語法:

  1. 第一個引數(可選):起始索引 begin(預設從 0 開始),從該索引開始提取原陣列元素。
  2. 第二個引數(可選):結束索引 end 在該索引結束提取原陣列元素。如果該引數省略,則一直提取到原陣列末尾結束。slice 會提取原陣列中beginend的所有元素(包含 begin,但不包含end)。
const arr = [1, 2, 3, 4]
const newArr = arr.slice(1)
// [2,3,4]
console.log(newArr);
const newArr1 = arr.slice(1, 3)
// [2,3]
console.log(newArr1)
複製程式碼

如果結束位置小於起始位置,則返回空陣列。

const arr = [1, 2, 3, 4]
const newArr = arr.slice(2, 1)
// []
console.log(newArr)
複製程式碼

splice()

向陣列的中刪除插入替換元素。返回值是被刪除的元素組成的一個陣列。如果沒有刪除元素,則返回空陣列。此方法會改變原陣列。

刪除任意數量的元素,傳入 2 個引數,要刪除的元素開始索引和要刪除的個數。

const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
//刪除前兩個元素
arr.splice(0, 2)
// [{id: 3}]
console.log(arr)
複製程式碼

向指定位置插入任意數量的元素,傳入3個引數:起始位置、0(要刪除的元素個數) 和要插入的元素。如果要插入多個元素,可以再傳入第四、第五,以至任意多個元素。

const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
// 從索引 1 開始插入兩個元素
arr.splice(1, 0, { id: 4 }, { id: 5 })
// [{ id: 1 }, { id: 4 }, { id: 5 },{ id: 2 }, { id: 3 }]
console.log(arr)
複製程式碼

向指定位置插入任意數量的元素,且同時刪除任意數量的元素。傳入3個引數:起始位置、要刪除的元素個數和要插入的元素。

const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
// 從索引 1 開始,刪除一個元素,並切插入兩個元素
arr.splice(1, 1, { id: 4 }, { id: 5 })
// [{ id: 1 }, { id: 4 }, { id: 5 },{ id: 3 }]
console.log(arr)
複製程式碼

copyWithin()

在陣列內部替換自身元素,返回修改後的當前陣列。

Array.copyWithin()引數語法:

  1. 第一個引數(必填):從該位置開始替換元素。
  2. 第二個引數(可選):從該位置開始複製資料,預設為 0
  3. 第三個引數(可選):停止複製的索引(不包含自身),預設值為陣列的長度。
// 將陣列的前兩個元素替換陣列的最後兩個位置:[1,2,1,2]
// 從索引2的位置開始替換
// 從索引0的位置開始複製資料
[1, 2, 3, 4].copyWithin(2,0)

const arr = [{id: 1},{id: 2},{id: 3}]
// [{id: 3},{id: 2},{id: 3}]
arr.copyWithin(0, 2)

// 從索引2的位置開始替換
// 從索引0的位置開始複製
// 在遇到索引1的時候停止複製(不包含自身)
// [1,2,1,4]
[1, 2, 3, 4].copyWithin(2,0)
複製程式碼

fill()

使用固定值填充一個陣列中一個或多個元素。

  1. 第一個引數:用來填充陣列元素的值。
  2. 第二個引數(可選):起始索引,預設值為0
  3. 第二個引數(可選):終止索引,預設值為陣列的長度。

當傳入一個引數的時候,會用這個引數的值填充整個陣列:

const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]

arr.fill({ id: 4 })
// [{ id: 4 }, { id: 4 }, { id: 4 }]
console.log(arr)
// true
console.log(arr[0] === arr[1])
複製程式碼

當傳入多個個引數的時候,用這個引數的值填充部分陣列:

const arr = [{ id: 1 }, { id: 2 }, { id: 3 }]
// 從陣列下標索引為1的元素開始填充
arr.fill({ id: 4 }, 1)
// [{ id: 1 }, { id: 4 }, { id: 4 }]
console.log(arr)

// 填充的元素不包括終止的索引元素。
const numbers = [1, 2, 3, 4]
numbers.fill(0, 1, 2)
// [1, 0, 3, 4]
console.log(numbers)
複製程式碼

flat()

將巢狀的陣列,變成一維的陣列。返回一個新陣列。

Array.flat()引數語法:

  1. 第一個引數(可選):指定要提取巢狀陣列的結構深度,預設值為 1。

展開一層

const arr = [1, 2, [3, 4]]
const newArr = arr.flat()
//[1,2,3,4]
console.log(newArr)
複製程式碼

展開兩層

const arr = [1, 2, [3, [4, 5]]]
const newArr = arr.flat(2)
// [1, 2, 3, 4, 5]
console.log(newArr)
複製程式碼

使用 Infinity,可展開任意深度的巢狀陣列

var arr = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
const newArr = arr.flat(Infinity)
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
console.log(newArr)
複製程式碼

移除陣列中的空項

var arr = [1, 2, , 4, 5]
const newArr = arr.flat()
// [1, 2, 4, 5]
console.log(newArr)
複製程式碼

flatMap()

對原陣列的每個成員執行一個函式,然後對返回值組成的陣列執行flat()方法。該方法返回一個新陣列,不改變原陣列。

Array.flatMap()引數語法:

  1. 第一個引數(必填): callback遍歷函式。該函式接收三個引數:
element index array
當前元素 當前元素的索引(可選) 陣列物件本身(可選)
  1. 第二個引數(可選):當執行回撥函式時this的值。
var arr = [1, 2]
const newArr = arr.flatMap(el => [el, el * 2])
[1,2,2,4]
console.log(newArr)
複製程式碼

flatMap()只能展開一層陣列

var arr = [1, 2]
const newArr = arr.flatMap(el => [[el, el * 2]])
// [[1,2],[2,4]]
console.log(newArr)
複製程式碼

includes()

判斷一個陣列是否包含一個指定的值,如果包含則返回true,否則返回false。使用 includes()比較字串和字元時是區分大小寫的。

Array.includes()引數語法:

  1. 第一個引數:需要查詢的元素值。

  2. 第二個引數:表示搜尋的起始位置,預設為0

const obj = { id: 1 }
var arr = [obj, { id: 2 }]
// true
console.log(arr.includes(obj))
複製程式碼

傳入第二個引數

console.log([1, 2, 3].includes(3));    // true
console.log([1, 2, 3].includes(3, 3))  // false
console.log([1, 2, 3].includes(3, 2))  // true
複製程式碼

五、排序方法

sort()

對陣列的元素進行排序,並返回排序後的原陣列。

Array.sort()引數語法:

  1. 第一個引數(可選):用來指定按某種順序進行排列的函式。如果省略,元素按照轉換為的字串的各個字串的ASCII碼進行排序。該函式接收二個引數:
first second
第一個用於比較的元素 第二個用於比較的元素
// Array的sort()方法預設把所有元素先轉換為String再排序,結果'10'排在了'2'的前面,因為字元'1'比字元'2'的ASCII碼小。
const arr = [10, 20, 1, 2].sort()
//[1, 10, 2, 20]
console.log(arr);
複製程式碼

可以接收一個比較函式作為引數,實現自定義的排序。該函式接收兩個引數,如果第一個引數應該位於第二個之前則返回一個負數,如果兩個引數相等返回0,如果第一個引數應該位於第二個之後則返回一個正數

const arr = [10, 20, 1, 2]
arr.sort((value1, value2) => {
  if (value1 < value2) {
    return -1
  }
  if (value1 > value2) {
    return 1
  }
  return 0
})
// [1, 2, 10, 20]
console.log(arr)
複製程式碼

reverse()

將陣列中元素的反轉,並返回該陣列。該方法會改變原陣列。

const values = [1, 2, 3, 4, 5]
values.reverse()
//[5, 4, 3, 2, 1]
console.log(values)
複製程式碼

六、 轉換方法

toLocaleString()

toLocaleString() 返回一個字串表示陣列中的元素。陣列中的元素將使用各自的 toLocaleString 方法轉成字串,這些字串將使用一個特定語言環境的字串,並用逗號隔開。

const array1 = [1, 'a', { id: 1 }, new Date()]
// 1,a,[object Object],2020/1/15 上午7:50:38
console.log(array1.toLocaleString())
複製程式碼

toString()

返回一個由逗號連線起來的字串。

const array1 = [1, 'abc', { id: 1 }]
// 1,abc,[object Object]
console.log(array1.toString())
複製程式碼

join()

將一個陣列的所有元素連線成一個字串並返回這個字串。如果陣列只有一個元素,那麼將返回該元素,而不使用分隔符。

Array.join()引數語法:

  1. 第一個引數(可選):指定一個字串來分隔陣列的每個元素。如果不傳,預設陣列元素用逗號(,)分隔。如果是空字串(""),則所有元素之間都沒有任何字元。
const arr = [1, 2, 3]
// 1,2,3
console.log(arr.join())
// 123
console.log(arr.join(''))
// 1+2+3
console.log(arr.join('+'))
複製程式碼

七、 歸併方法(迭代陣列的所有項,然後構建一個最終返回的值)

reduce()

reduce()方法從陣列的第一項開始,迭代陣列的所有元素,構建一個最終返回的值,返回函式累計處理的結果。

Array.reduce()引數語法:

  1. 第一個引數(必填): callback執行陣列中每個值的函式。該函式接收四個引數:
prev cur index array
初始值, 或者上一次呼叫回撥函式返回的值(必填) 當前元素值 (必填) 當前元素的索引值(可選) 陣列物件本身(可選)

這個函式返回的任何值都會作為第一個引數自動傳給下一項。

  1. 第二個引數(可選): initialValue作為第一次呼叫callback函式時的第一個引數的值。如果沒有提供初始值,則將使用陣列中的第一個元素。在沒有初始值的空陣列上呼叫reduce將報錯。
 //Uncaught TypeError: Reduce of empty array with no initial value
 [].reduce(() => {})
複製程式碼
const arr = ['L', 'O', 'V', 'E'].reduce((prev, cur) => {
  console.log('prev: ', prev)
  console.log('cur: ', cur)
  return prev + cur
})
// LOVE
console.log(arr)
複製程式碼

第一次執行回撥函式,prev 是 L,cur 是 O。第二次,prev 是 LO,cur 是 V(陣列的第三項)。這個過程會持續到把陣列中的每一項都訪問一遍,最後返回結果LOVE。

reduceRight()

reduceRight()reduce()作用類似,使用reduce()還是reduceRight(),主要取決於要從哪頭開始遍歷陣列。除此之外,它們完全相同。

var values = [1,2,3,4,5]
var sum = values.reduceRight(function(prev, cur, index, array){
  return prev + cur
});
//15
alert(sum)
複製程式碼

第一次執行回撥函式,prev 是 5,cur 是 4。第二次,prev 是 9(5 加 4 的結果),cur 是 3(陣列的第三項)。這個過程會持續到把陣列中的每一項都訪問一遍,最後返回結果。

八、demo

實現由短劃線分隔的單詞變成駱駝式的

camelize("background-color") === 'backgroundColor'

function camelize(str) {
  return str
    .split('-') // my-long-word -> ['my', 'long', 'word']
    .map(
      (word, index) => index == 0 ? word : word[0].toUpperCase() + word.slice(1)
    ) // ['my', 'long', 'word'] -> ['my', 'Long', 'Word']
    .join(''); // ['my', 'Long', 'Word'] -> myLongWord
}
複製程式碼

陣列去重

function unique(arr) {
  let result = [];
  for (let str of arr) {
    if (!result.includes(str)) {
      result.push(str)
    }
  }
  return result
}
複製程式碼

在已有的陣列上建立一個物件,id作為鍵,陣列的每一項作為值。

let users = [
  { id: '111', name: "zhangsan", age: 20 },
  { id: '222', name: "lisi", age: 24 },
  { id: '333', name: "wangwu", age: 31 },
]
function groupById(array) {
  return array.reduce((obj, value) => {
    obj[value.id] = value
    return obj
  }, {})
}
/* 
  {
    111: { id: "111", name: "zhangsan", age: 20 },
    222: { id: "222", name: "lisi", age: 24 },
    333: { id: "333", name: "wangwu", age: 31 }
  } 
*/
console.log(groupById(users))
複製程式碼

參考連結

JavaScript高階程式設計(第3版)

10 JavaScript array methods you should know

【乾貨】js 陣列詳細操作方法及解析合集

陣列的擴充套件

MDN Array www.ecma-international.org/ecma-262/8.…

陣列方法

相關文章