JS陣列方法總覽及遍歷方法耗時統計
國慶7天假,6天加班,苦澀:joy:。
因為對陣列的處理方法有些還是有點模糊,因此這裡整理彙總一下,方便日後自己查閱。:stuck_out_tongue_winking_eye:
01、push(value)
將value新增到陣列的最後,返回陣列長度(改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.push(1) console.log(result)// 6 console.log(a)// [1, 2, 3, 4, 5, 1] 原陣列被改變 // More a = [1, 2, 3, 4, 5] result = a.push('a', 'b') // 可一次新增多個值 console.log(result)// 7 console.log(a)// [1, 2, 3, 4, 5, 'a', 'b'] 複製程式碼
02、unshift()
新增元素到陣列的開頭,返回陣列的長度(改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.unshift(1) console.log(result)// 6 console.log(a)// [1, 1, 2, 3, 4, 5] // More result = a.unshift('a', 'b')// 可一次新增多個值 console.log(result)// 8 console.log(a)// ['a', 'b', 1, 1, 2, 3, 4, 5] 複製程式碼
03、pop()
刪除陣列中最後一個元素,返回被刪除元素(改變原陣列)
// Base let a = [5] let result = a.pop() console.log(result)// 5 console.log(a)// [] // More result = a.pop()// 陣列元素為空後會返回undefined console.log(result)// undefined console.log(a)// [] 複製程式碼
04、shift()
刪除陣列第一個元素,返回刪除的元素(改變原陣列)
// Base let a = [5] let result = a.shift() console.log(result)// 5 console.log(a)// [] // More result = a.shift()// 陣列元素為空後會返回undefined console.log(result)// undefined console.log(a)// [] 複製程式碼
05、join(value)
將陣列用value連線為字串(不改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.join(',') console.log(result)// '1,2,3,4,5' console.log(a)// [1, 2, 3, 4, 5] // More let obj = { toString() { console.log('呼叫了toString()方法!') return 'a' }, toValue() { console.log('toValue()方法!') return 'b' } } result = a.join(obj) // 使用物件時會呼叫物件自身的toString方法轉化為字串,我們這裡重寫了toString,從而覆蓋了原型鏈上的toString // 呼叫了toString()方法! console.log(result)// 1a2a3a4a5 console.log(a)// [1, 2, 3, 4, 5] // join的一個相對的方法是字串的split方法 console.log('1a2a3a4a5'.split('a')) // [1, 2, 3, 4, 5] 複製程式碼
06、reverse()
反轉陣列(改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.reverse() console.log(result)// [5, 4, 3, 2, 1] console.log(a)// [5, 4, 3, 2, 1] // More a = [1, [2, 3], [4, 5]] result = a.reverse() console.log(result)// [[4, 5], [2, 3], 1] console.log(a)// [[4, 5], [2, 3], 1] // 可以看到這裡的反轉只是基於陣列的第一層,屬於淺反轉。 // 一個簡單的深反轉,使用遞迴實現 const deepReverse = (array) => { let temp = array.reverse() temp.forEach(v => { if(Object.prototype.toString.call(v) === '[object Array]') { deepReverse(v) } }) return temp } a = [1, [2, 3], [4, 5]] result = deepReverse(a) console.log(result)// [[5, 4], [3, 2], 1] 複製程式碼
07、slice(start, end)
返回新陣列,包含原陣列索引start的值到索引end的值,不包含end(不改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.slice(2, 4) console.log(result)// [3, 4] console.log(a)// [1, 2, 3, 4, 5] // More console.log(a.slice(1))// [2, 3, 4, 5]只有一個引數且不小於0,則從此索引開始擷取到陣列的末位 console.log(a.slice(-1))// [5]只有一個引數且小於0,則從倒數|start|位擷取到陣列的末位 console.log(a.slice(-1, 1))// []反向擷取,不合法返回空陣列 console.log(a.slice(1, -1))// [2, 3, 4]從第一位擷取到倒數第一位,不包含倒數第一位 console.log(a.slice(-1, -2))// []反向擷取,不合法返回空陣列 console.log(a.slice(-2, -1))// [4]倒數第二位擷取到倒數第一位 複製程式碼
08、splice(index, count, value)
從索引為index處刪除count個元素,插入value(改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.splice(1, 2, 0) console.log(result)// [2, 3] console.log(a)// [1, 0, 4, 5] // More a = [1, 2, 3, 4, 5] console.log(a.splice(-2))// [4. 5] console.log(a)// [1, 2, 3] a = [1, 2, 3, 4, 5] console.log(a.splice(-1))// [5] console.log(a)// [1, 2, 3, 4]當引數為單個且小於0時,將從陣列的倒數|index|位擷取到陣列的末位 a = [1, 2, 3, 4, 5] console.log(a.splice(0))// [1, 2, 3, 4, 5] console.log(a)// [] a = [1, 2, 3, 4, 5] console.log(a.splice(1))// [2, 3, 4, 5] console.log(a)// [1]當引數為單個且不小於0時,將從當前數代表的索引位開始擷取到陣列的末位 a = [1, 2, 3, 4, 5] console.log(a.splice(-1, 2))// [5] console.log(a)// [1, 2, 3, 4]從倒數第一位開始擷取兩個元素,元素不夠,只返回存在的元素 a = [1, 2, 3, 4, 5] console.log(a.splice(0, 2, 'a', 'b', 'c'))// [1, 2] console.log(a)// ["a", "b", "c", 3, 4, 5]擷取後將value一次填充到陣列被擷取的位置,value的數量大於擷取的數量時,陣列中剩餘的元素後移 複製程式碼
09、sort()
對陣列元素進行排序(改變原陣列)
// Base let a = [31, 22, 27, 1, 9] let result = a.sort() console.log(result)// [1, 22, 27, 31, 9] console.log(a)// [1, 22, 27, 31, 9] // More a = ['c', 'ac', 'ab', '1c', 13, 12, '13', '12', '3', '2', '1b', '1a', 1, 'aa', 'a', 3, 'b', 2] a.sort() console.log(a) // [1, 12, "12", 13, "13", "1a", "1b", "1c", "2", 2, "3", 3, "a", "aa", "ab", "ac", "b", "c"] // 可以看出sort排序是根據位來進行排序,而非值的大小,先比較第一位數字在前,字母在後,若相同則比較後面位(實際是比較各個值轉化為字串後的各個位點的unicode位點) a = [31, 22, 27, 1, 9] a.sort((a, b)=>{ return a - b }) console.log(a)// [1, 9, 22, 27, 31]按數值大小正序排列 a = [31, 22, 27, 1, 9] a.sort((a, b)=>{ return b - a }) console.log(a)// [31, 27, 22, 9, 1]按數值大小倒序排列 複製程式碼
10、toString()
將陣列中的元素用逗號拼接成字串(不改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.toString() console.log(result)// 1,2,3,4,5 console.log(a)// [1, 2, 3, 4, 5] 複製程式碼
11、indexOf(value)
從索引為0開始,檢查陣列是否包含value,有則返回匹配到的第一個索引,沒有返回-1(不改變原陣列)
// Base let a = [1, 2, 3, 2, 5] let result = a.indexOf(2) console.log(result)// 1 console.log(a)// [1, 2, 3, 2, 5] result = a.indexOf(6) console.log(result)// -1 console.log(a)// [1, 2, 3, 2, 5] 複製程式碼
12、lastIndexOf(value)
從最後的索引開始,檢查陣列是否包含value,有則返回匹配到的第一個索引,沒有返回-1(不改變原陣列)
// Base let a = [1, 2, 3, 2, 5] let result = a.lastIndexOf(2) console.log(result)// 3 console.log(a)// [1, 2, 3, 2, 5] result = a.lastIndexOf(6) console.log(result)// -1 console.log(a)// [1, 2, 3, 2, 5] 複製程式碼
13、concat(value)
將陣列和/或值連線成新陣列(不改變原陣列)
// Base let a = [1, 2], b = [3, 4], c = 5 let result = a.concat(b, c) console.log(result)// [1, 2, 3, 4, 5] console.log(a)// [1, 2] // More b = [3, [4]] result = a.concat(b, c) console.log(result)// [1, 2, 3, [4], 5] concat對於巢狀陣列無法拉平 console.log(a)// [1, 2] 複製程式碼
14、fill(value, start, end)
使用給定value填充陣列,從索引start開始end結束,不包含end(改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.fill(0, 2, 3) console.log(result)// [1, 2, 0, 4, 5] console.log(a)// [1, 2, 0, 4, 5] // More a = [1, 2, 3, 4, 5] console.log(a.fill(1))// [1, 1, 1, 1, 1]引數一個時,將該引數覆蓋填充到陣列每一項 a = [1, 2, 3, 4, 5] console.log(a.fill(1, 2))// [1, 2, 1, 1, 1]只有start時,從索引start開始填充到陣列末位 a = [1, 2, 3, 4, 5] console.log(a.fill(1, -2))// [1, 2, 3, 1, 1]只有start且為負數時,從倒數|start|位開始填充到陣列末位 複製程式碼
15、flat()
將二維陣列變為一維陣列(不改變原陣列)
// Base let a = [1, 2, 3, [4, 5]] let result = a.flat() console.log(result)// [1, 2, 3, 4, 5] console.log(a)// [1, 2, 3, [4, 5]] let a = [1, 2, 3, [4, 5, [6, 7, [8, 9]]]] let result = a.flat() console.log(result)// [1, 2, 3, 4, 5, [6, 7, [8, 9]]] 很顯然只能將第二層巢狀陣列“拉平” console.log(a)// [1, 2, 3, [4, 5, [6, 7, [8, 9]]]] 複製程式碼
16、flatMap()
相當於map與flat的結合(不改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.flatMap((currentValue)=>{ return [currentValue, currentValue * 2] }) console.log(result)// [1, 2, 2, 4, 3, 6, 4, 8, 5, 10] console.log(a)// [1, 2, 3, 4, 5] 複製程式碼
17、copyWithin(target, start, end)
將陣列從start到end索引的元素(不包含end)複製到target開始的索引位置(改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.copyWithin(0, 3, 5) console.log(result)// [4, 5, 3, 4, 5] console.log(a)// [4, 5, 3, 4, 5]索引3到5的元素為4和5,複製到從0開始的位置,替換掉了1和2 // More a = [1, 2, 3, 4, 5] console.log(a.copyWithin(2))// [1, 2, 1, 2, 3]引數只有一個時,start預設為0,end預設為陣列長度-1 複製程式碼
18、entries()
返回一個新的Array迭代器物件,可用for...of遍歷(不改變原陣列)
// Base let a = [1, 2, 3, 4, 5] let result = a.entries() console.log(result.next())// {value: [0, 1], done: false}value陣列中第一個元素為索引,第二元素為索引對應的值 ... console.log(result.next())// {value: [4, 5], done: false} console.log(result.next())// {value: undefined, done: true} console.log(result)// Array Iterator {} console.log(a)// [1, 2, 3, 4, 5] result = a.entries() for(let value of result) { console.log(value) } // [0, 1] // [1, 2] // [2, 3] // [3, 4] // [4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() result = a.entries() for(let v of result) { } let dateEnd = Date.now() console.log(dateEnd - dateStart)// 執行三次,三次的耗時數 518ms 515ms 530ms 複製程式碼
19、keys()
返回一個新的Array迭代器物件,可用for...of遍歷(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.keys() console.log(result.next())// {value: 0, done: false}value為索引 ... console.log(result.next())// {value: 3, done: false} console.log(result.next())// {value: 4, done: false} console.log(result)// Array Iterator {} console.log(a)// [1, 2, 3, 4, 5] result = a.keys() for(let value of result) { console.log(value) } // 0 // 1 // 2 // 3 // 4 // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() result = a.keys() for(let v of result) { } let dateEnd = Date.now() console.log(dateEnd - dateStart)// 執行三次,三次的耗時數 223ms 262ms 300ms 複製程式碼
20、values()
返回一個新的迭代器(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.values() console.log(result.next())// {value: 1, done: false}value為索引 ... console.log(result.next())// {value: 4, done: false} console.log(result.next())// {value: 5, done: false} console.log(result)// Array Iterator {} console.log(a)// [1, 2, 3, 4, 5] result = a.values() for(let value of result) { console.log(value) } // 1 // 2 // 3 // 4 // 5 // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() result = a.values() for(let v of result) { } let dateEnd = Date.now() console.log(dateEnd - dateStart)// 執行三次,三次的耗時數 254ms 270ms 273ms 複製程式碼
21、forEach()
遍歷陣列(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.forEach((v, i)=>{ console.log(v, i) // 1 0 // 2 1 // 3 2 // 4 3 // 5 4 }) console.log(result)// undefined console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.forEach(v=>{}) let dateEnd = Date.now() console.log(dateEnd - dateStart)// 執行三次,三次的耗時數 182ms 188ms 180ms 複製程式碼
22、every(fn)
判斷陣列中是否所有元素都滿足fn函式中的條件(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.every((currentValue)=>{ return currentValue > 0 }) console.log(result)// true顯然所有元素都大於0 result = a.every((currentValue)=>{ return currentValue > 1 }) console.log(result)// false1並不大於1 console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.every(v=> v > -1 ) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 執行三次,三次的耗時數 176ms 200ms 186ms dateStart = Date.now() a.every(v=> v > 8 ) dateEnd = Date.now() console.log(dateEnd - dateStart) // 0ms 0ms 0ms 不超過1ms,可見every的判斷是在識別到不滿足的條件時,立刻停止 複製程式碼
23、filter(fn)
返回陣列中滿足fn函式中條件的集合(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.filter((currentValue)=>{ return currentValue > 4 }) console.log(result)// [5] 只有5滿足條件 console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.filter(v=> v > -1 ) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 執行三次,三次的耗時數 584ms 660ms 552ms 全部值都滿足條件的情況 a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.filter(v=> v < 0 ) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 200ms 194ms 183ms 這個時候才個forEach接近,這也是與forEach本身只有遍歷的功能,沒有執行其他邏輯相關 複製程式碼
24、find(fn)
返回陣列中第一個匹配fn函式中條件的值沒有則返回undefined(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.find((currentValue)=>{ return currentValue > 3 }) console.log(result)// 4 console.log(a)// [1, 2, 3, 4, 5] let result = a.find((currentValue)=>{ return currentValue > 5 }) console.log(result)// undefined console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.find(v=> v < 0 ) let dateEnd = Date.now() console.log(dateEnd - dateStart)// 185ms 197ms 203ms 全部不滿足的情況下,效率與forEach相當 a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.find(v=> v > 10 ) let dateEnd = Date.now() console.log(dateEnd - dateStart)// 0ms 0ms 0ms 小於1ms,可以判斷當匹配到滿足條件的第一個值後,立刻停止迴圈,與every相當 複製程式碼
25、findIndex(fn)
返回陣列中第一個匹配fn函式中條件的索引沒有則返回undefined(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.findIndex((currentValue)=>{ return currentValue > 3 }) console.log(result)// 3 console.log(a)// [1, 2, 3, 4, 5] let result = a.findIndex((currentValue)=>{ return currentValue > 5 }) console.log(result)// -1 console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.findIndex(v=> v < 0 ) let dateEnd = Date.now() console.log(dateEnd - dateStart)// 185ms 183ms 187ms 與find相當 a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.findIndex(v=> v > 10 ) let dateEnd = Date.now() console.log(dateEnd - dateStart)// 0ms 0ms 0ms 與find相當 複製程式碼
26、includes()
返回一個布林值,表示某個陣列是否包含給定的值(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.includes(2) console.log(result)// true console.log(a)// [1, 2, 3, 4, 5] result = a.includes(6) console.log(result)// false console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.includes(10) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 0ms 0ms 0ms a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.includes(10000000-1) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 22ms 18ms 27ms 效能不錯 複製程式碼
27、map(fn)
以fn函式中返回值組成新的陣列返回(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.map((v, i)=>{ return 9 }) console.log(result)// [9, 9, 9, 9, 9] console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.map(v=>1) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 2158ms 2007ms 2079ms 耗時比較大 複製程式碼
28、reduce()
累計器(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.reduce((accumulator, currentValue, currentIndex, array)=>{ console.log(accumulator, currentValue, currentIndex, array) return accumulator + currentValue // 51 0 [1, 2, 3, 4, 5]第一次accumulator的值為reduce第二個引數5, currentValue為陣列第一個元素 // 62 1 [1, 2, 3, 4, 5]第二次accumulator的值為5加上陣列a中的第一個值,即是第一次迴圈時return的值 // 83 2 [1, 2, 3, 4, 5]同上 // 11 4 3 [1, 2, 3, 4, 5]同上 // 15 5 4 [1, 2, 3, 4, 5]同上 }, 5) console.log(result)// 20 為最終累計的和 console.log(a)// [1, 2, 3, 4, 5] // 無初始值時,accumulator的初始值為陣列的第一個元素,currentValue為陣列第二個元素 result = a.reduce((accumulator, currentValue, currentIndex, array)=>{ console.log(accumulator, currentValue, currentIndex, array) return accumulator + currentValue // 12 1 [1, 2, 3, 4, 5] // 33 2 [1, 2, 3, 4, 5] // 64 3 [1, 2, 3, 4, 5] // 10 5 4 [1, 2, 3, 4, 5] }) console.log(result)// 15 為最終累計的和 console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.reduce((accumulator, currentValue, currentIndex, array)=>{ return accumulator + currentValue }) let dateEnd = Date.now() console.log(dateEnd - dateStart) // 200ms 258ms 257ms 效率與forEach相差也不多,而且比forEach多個累計的功能 複製程式碼
29、reduceRight()
與reduce功能一樣,只是從陣列末尾開始進行累計(不改變原陣列)
略... 複製程式碼
30、some(fn)
檢查陣列中是否含有滿足fn函式條件的值(不改變原陣列)
let a = [1, 2, 3, 4, 5] let result = a.some((v)=>{ return v > 2 }) console.log(result)// true console.log(a)// [1, 2, 3, 4, 5] result = a.some((v)=>{ return v > 6 }) console.log(result)// false console.log(a)// [1, 2, 3, 4, 5] // Time a = [] for(let i = 0; i < 10000000; i++) { a.push(i) } let dateStart = Date.now() a.some(v=>{ return v < 0 }) let dateEnd = Date.now() console.log(dateEnd - dateStart)// 171ms 176ms 188ms 全部不滿足的情況下效率與forEach相當 複製程式碼
31、toLocaleString()
將陣列中的每個元素使用各自的toLocaleString()轉換後用,
拼接(不改變原陣列)
let a = [1, new Date(), 'a', {m: 1}] let result = a.toLocaleString() console.log(result)// '1,2018/10/3 下午9:23:59,a,[object Object]' console.log(a)// [1, Wed Oct 03 2018 21:23:59 GMT+0800 (中國標準時間), "a", {m: 1}] 複製程式碼
32、[@@iterator]()
陣列自帶的迭代器方法(不改變原陣列)
使得陣列原生可以使用for...of進行遍歷 複製程式碼