置頂 0%

JavaScipt Array 常用方法

前言

JS的陣列(Array)是我認為最基本且常用的一個物件,所以善用JS提供的Array操作方法就顯得相當重要,過去在使用時每次都要查一下MDN上的Array文件 ,因此這篇就來記錄最常使用的操作方法及過去用錯的地方,希望可以更熟悉來讓程式碼更加簡潔乾淨!

陣列定義

JS中的陣列其實和Java的陣列差不多,兩者都可以當成是由資料所組成的一種資料結構,並且透過索引值(index)來存取裡面的資料,但JS的陣列有幾個特點,分別是:

  1. JS的陣列也算是一種物件(Object)
  2. 可存放不同資料型態的元素,且是一個有序的集合
  3. 可覆寫length屬性來增加移除元素

ES5操作方法

push(element…)

放進push的參數不限數量(一個或多個),並且進一步將參數中的所有值放進陣列的最後一項

1
2
3
4
let arr = ['a', 'b', 'c', 'd'];
arr.push('e', 'f');
arr.push('d');
console.log(arr); //["a","b","c","d","e","f","d"]

pop()

這和Java的Stack物件有點像,pop()會返回(return)最後一項的元素,並且在陣列中移除該元素

1
2
3
let arr = ['a', 'b', 'c', 'd'];
console.log(arr.pop()); //d
console.log(arr); //["a","b","c"]

unshift(element…)

功能和push差不多,只是unshift是將參數的元素加入到陣列的第一項

1
2
3
let arr = ['a', 'b', 'c', 'd'];
arr.unshift('e','f')
console.log(arr); //["e","f","a","b","c","d"]

shift()

功能和pop差不多,但是針對陣列的第一項元素來操作

1
2
3
let arr = ['a', 'b', 'c', 'd'];
console.log(arr.shift()) //a
console.log(arr); //["b","c","d"]

splice(startIndex, deleteCount, item1…)

splice()是一個來抽換元素很好的方法,第一個參數是必填外,其他都是選填,並且這個方法會返回移除的元素。

  • 第一個參數指定要移除並擦入的索引
  • 第二個參數則表明是第一個參數後面的幾個元素(有點類似substr(index, length)的length),放空則第一個參數索引後的元素都會被移除,如不想移除就放0就都會保留元素
    1
    2
    3
    4
    5
    6
    7
    let arr = ['a', 'b', 'c', 'd'];
    console.log(arr.splice(1)); // ["b","c","d"]
    console.log(arr); //["a"]

    let arr2 = [1, 2, 3, 4, 5];
    console.log(arr2.splice(1, 0)); // []
    console.log(arr2); //[1,2,3,4,5]
  • 第三個參數放置要擦入的元素,一樣是可以不限數量(一個或多個)
1
2
3
4
5
6
7
let arr = ['a', 'b', 'c', 'd'];
console.log(arr.splice(1, 2, 'e', 'f')); //["b","c"]
console.log(arr); //["a","e","f","d"]

let arr2 = [1, 2, 3, 4, 5];
console.log(arr2.splice(0, 0, -2, -1, 0)); //[] 第二個參數為0表示沒有元素被移除
console.log(arr2); //[-2,-1,0,1,2,3,4,5]

reverse()

將陣列的元素順序反轉

1
2
3
let arr = ['a', 'b', 'c', 'd'];
arr.reverse();
console.log(arr); //["d","c","b","a"]

sort(compareFn)

顧名思義就是進行陣列的排序,如果參數放空的話,則會將元素都轉換成字串,並使用第一字元的 Unicode code 來遞增排序,因此,可在sort的參數中傳入一個涵式,其包含兩個參數,兩個參數分別代表陣列中的某一個索引及下一個索引,所以兩者相減為正表示使用遞增排序

  • If compareFunction(a, b) returns a value > than 0, sort b before a.
  • If compareFunction(a, b) returns a value ≤ 0, leave a and b in the same order.
1
2
3
4
5
6
7
8
9
10
let arr = [1, 5, 3, 4, 6, 2];
arr.sort((a, b) => a - b);
console.log(arr); //[1,2,3,4,5,6]
arr.sort((a, b) => b - a);
console.log(arr); //[6,5,4,3,2,1]

//把number轉成string後,根據字元的Unicode code大小來遞增排序
let arr2 = [1, 5, 3, 4, 6, 2, 100, 111];
arr2.sort();
console.log(arr2); //[1,2,3,4,5,6] //[1,100,111,2,3,4,5,6]

copyWithin(target, start, end)

有點類似splice(),但這個方法是用陣列裡面自己的元素來做複製,有三個參數而第一個參數為必填

  • 第一個參數為要置換位置的索引
  • 第二個參數為要複製的元素起始索引,放空的話預設會從0開始
  • 第三個參數為要複製的元素截止索引(不包含自己),放空預設就是陣列長度
1
2
3
4
5
6
7
let arr = ['a', 'b', 'c', 'd'];
arr.copyWithin(2);
console.log(arr); //["a","b","a","b"] 等同於arr.copyWithin(2, 0, 4)

let arr2 = ['a', 'b', 'c', 'd'];
arr2.copyWithin(1, 0, 2);//在'b'(index: 1)的位置貼上從'a'(index: 0)開始到'b'(index: 1)的元素
console.log(arr2); //["a","a","b","d"]

fill(value, start, end)

有點類似copyWithin,但比較單純就是把value的值置換到從start到end的索引,且一樣也是不包含end自己,然後第一個參數為必填,其他兩個則為選填

1
2
3
4
5
6
7
let arr = ['a', 'b', 'c', 'd'];
arr.fill('f'); //如同arr.fill('f',0, 4) 4是arr.length
console.log(arr); //["f","f","f","f"]

let arr2 = ['a', 'b', 'c', 'd'];
arr2.fill('f', 1, 3);
console.log(arr2); //["a","f","f","d"]

indexOf(searchElement, fromIndex)

有另外一個類似的方法是lastIndexOf(searchElement, fromIndex),其實就是判斷元素的陣列索引位置,如果陣列沒有此元素則回傳-1

1
2
3
4
5
let arr = ['a', 'b', 'c', 'd'];
console.log(arr.indexOf('b')); //1
console.log(arr.indexOf('b', 2));//從'c'開始往後看['c', 'd']
console.log(arr.lastIndexOf('b')); //1
console.log(arr.lastIndexOf('c', 1));//從'b'開始往前看,只判斷['a', 'b']

ES6操作方法

find(callbackFn)

從陣列中的第一項元素開始放進參數傳入的functoin裡面,來去找出第一個符合判斷條件的元素,如全部都沒有則返回undefined

1
2
3
let arr = [1, 2, 3, 4, 5, 6];
console.log(arr.find(e => e%2 === 0)); //陣列中第一個偶數 2
console.log(arr.find(e => e%2 === 2)); //undefined

findIndex(callbackFn)

和find其實差不多,只差在findIndex是回傳第一個找到元素的索引位置,沒有符合條件的元素一樣是回傳一個undefined

1
2
3
let arr = [1, 2, 3, 4, 5, 6];
console.log(arr.findIndex(e => e%2 === 0)); //1
console.log(arr.find(e => e%2 === 2)); //undefined

filter(callbackFn)

將每一個元素代入callbackFn中,並將符合條件的元素回傳一個新的陣列

1
2
3
let arr = [1, 2, 3, 4, 5, 6];
console.log(arr.filter(e => e%2 === 0)); //[2,4,6]
console.log(arr); //原來陣列還是一樣[1,2,3,4,5,6]

forEach(callbackFn)

過去使用ExtJs裡面就有這種用法,顧名思義就是去迭代這個陣列的元素,針對元素來做一些處理,而callbackFn有三個元素

  • 第一個參數為目前迭代元素的值(必填)
  • 第二個參數為目前迭代的索引值
  • 第三個參數為呼叫該方法的陣列
    1
    2
    3
    4
    5
    let arr = [1, 2, 3, 4, 5, 6];
    arr.forEach((item, index, array) => {
    array[index] = item * 10;
    })
    console.log(arr); //[10,20,30,40,50,60]

join(separator)

join可以把陣列的元素組合再一起,並且使用參數符號來區隔每一個元素,如果放空預設會用「逗號」來進行合併

1
2
3
let arr = [1, 2, 3, 4, 5, 6]; //console.log(arr.join()); //"1,2,3,4,5,6"
console.log(arr.join('-')); //"1-2-3-4-5-6"
console.log(arr); //[1,2,3,4,5,6]

concat(Array)

concat()可將兩個陣列合併再一起, ES6語法則能夠用擴展運算符…來代替

1
2
3
4
5
6
7
8
let arr = [1, 2, 3, 4, 5, 6];
let arr2 = [7, 8, 9];

let arr3 = arr.concat(arr2);
let arr4 = [...arr, ...arr2]; // 使用 ...

console.log(arr3); // [1,2,3,4,5,6,7,8,9]
console.log(arr4); // [1,2,3,4,5,6,7,8,9]

slice(start, end)

如同英文字一樣,slice就是把陣列切一段出來,區段一樣也是不包含end自己本身,
類似用途的方法還有 substr() 和 substring()
在使用slice()的時候,如果不給參數,或只給零,那麼slice()就會把陣列從頭到尾複製一份給我們

1
2
let arr = [1, 2, 3, 4];
console.log(arr.slice(1, 3)); // [2, 3]

map(callbackFn)

map是我在學react時,最常會來使用到的一個方法,他可以針對每一個元素做處理,並回傳一個新的陣列,他的callbackFn和forEach有點類似,有三個元素

  • 第一個參數為目前迭代元素的值(必填)
  • 第二個參數為目前迭代的索引值
  • 第三個參數為呼叫該方法的陣列
1
2
3
4
let arr = [1, 2, 3, 4, 5];
console.log(arr.map((e) => {
return e*10; //[10,20,30,40,50]
}))

reduce(callbackFn[accumulator, currentValue, currentIndex, array], initialValue)

根據官方定義是The reduce() method executes a reducer function (that you provide) on each member of the array resulting in a single output value.,所以可以知道reduce會回傳一個值,他的參數可以分成

  • accumulator:由 currentValue 加總的累計值
  • currentValue:目前迭代的元素值
  • currentIndex:目前迭代的索引值
  • array:呼叫該方法的陣列
  • initialValue:預設值,放在 function 的最後方,非必填

有另外一個相對應的方法reduceRight,更多應用可參考JavaScript reduce 在做什麼? 這篇

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let arr = [1, 2, 3, 4, 5];
let reduceArr = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 1, 3, 6, 10
console.log(currentValue); // 2, 3, 4, 5
return accumulator + currentValue
});

//有給initialValue值0
let arr = [1, 2, 3, 4, 5];
let reduceArr = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 0, 1, 3, 6, 10
console.log(currentValue); // 1, 2, 3, 4, 5
return accumulator + currentValue
}, 0);

Array.from()

將「類陣列物件」或是「可迭代的物件」轉換成陣列

  • 第一個參數為「類陣列物件」或「可迭代的物件」( 必填 )
  • 第二個參數為改變轉換成陣列元素的函式,參數分別是(element, index)
    其中根據MDN定義array-like objects (objects with a length property and indexed elements); or iterable objects (objects such as Map and Set).可以知道類陣列物件具有 length 屬性以及索引化 index 的元素,所以會有下面arr3的處理
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    let arr = Array.from('KEVIN', e => {
    return e + 's'; //[10,20,30,40,50]
    });
    console.log(arr); //["Ks","Es","Vs","Is","Ns"]

    let arr2 = Array.from('KEVIN');
    console.log(arr2); // ["K","E","V","I","N"]

    let arr = Array.from({length: 5});
    console.log(arr); //[undefined,undefined,undefined,undefined,undefined]

    let arr = Array.from({length: 5}, (element, index) => {
    return index;
    });
    console.log(arr); //[0,1,2,3,4]

補充

1
2
3
4
5
6
7
8
9
let arr = [1, 2, 3, 4, 5];
console.log(Array.isArray(arr)); //true
arr.length = 2;
console.log(arr); //[1, 2]
arr.length = 4;
console.log(arr); // [1, 2, undefined, undefined]
console.log(arr[2]); //undefined
arr[5] = 7;
console.log(arr); // [1, 2, undefined, undefined, undefined, 7]

參考

補充

HTMLCollection 或 NodeList 轉陣列方法

var arr = Array.prototype.slice.call( htmlCollection )
var arr = [].slice.call(htmlCollection);
// es6
var arr = Array.from(htmlCollection);
var arr = […htmlCollection];