js 試煉旅程
今天要來學一下關於操作陣列的手法,其實JavaScript提供了許多操作陣列的方法
如果能在適當時機使用,肯定會對於開發效率有正面的影響。
我們可以透過查看陣列的原型物件了解
console.log(Array.prototype);
就讓我們對於一些常用的方法好好的一探究竟吧!
陣列轉字串
arr.join([separator])
join()方法可以將陣列或者類陣列的所有元素串接並合併成一個字串回傳
而我們也可以自訂元素彼此之間的連接方式
let array =[1,2,'test',4,5];
let string = array.join("-");//使用-分隔轉為字串後的每個元素
console.log(string);
原陣列會改變
會反轉原陣列內的元素
let array =[1,2,3,4,5];
let newArray = array.reverse();
console.log(newArray);//[5,4,3,2,1]
原陣列會改變
arr.sort([compareFunction])
會在原陣列內將元素排序並回傳排序後的陣列。
Ex: 不帶引數時,依照字母排序
let array = ['g','f','a','v','r'];
console.log(array.sort());
Ex2 : 將陣列內的數字依大小排列
let array =[55,2,7,66,97,66];
let newArray = array.sort(function(param1,param2){
return param1 - param2;
});
console.log(newArray);
Ex3: 不區分大小寫的排序
let array = ['Bug','apple','lion','Cat'];
let newArray = array.sort(function(param1,param2){
let s = param1.toLowerCase();
let t = param2.toLowerCase();
//如果s的字母順位較t的字母順位高,往後排序
if(s > t)
return 1;
//如果t的字母順位較s的字母順位高,往前排序
if(t > s)
return -1;
return;
});
console.log(newArray);
原陣列會改變
arr.unshift(element1[, ...[, elementN]])
可以將一個或多個元素夾到陣列的開頭,並回傳陣列的新長度
var array = [1,2];
//新增單一元素到陣列
console.log(array.unshift(4,5,6));
console.log(array);
原陣列會改變
會移除並回傳陣列的第一個元素。
var array = [4,5,6,7,8];
var delElement = array.shift();
console.log(delElement);
console.log(array);
原陣列會改變
arr.push(element1[, ...[, elementN]])
可以在陣列最後面的位置新增一個或多個元素
var array = [4,5,6,7,8];
array.push('新增的文字');
console.log(array);
原陣列會改變
會移除並回傳陣列的最後一個元素。
var array = [4,5,6,7,8];
var delElement = array.pop();
console.log(delElement);
console.log(array);
原陣列會改變
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
start
開始,要加入到陣列的元素。可刪除或新增元素到陣列中,也可以同時執行這兩件事情
let array =[1,2,3,4,5,6,7,8,9];
let newArray = array.splice(2,4); // 從索引位置2(包含)刪除四個元素
console.log(newArray);// [3,4,5,6]
console.log(array);// [1,2,7,8,9]
let array2 =[1,2,3,4,5,6,7,8,9];
let newArray2 = array2.splice(2,4,'aa','bb');
console.log(array2);// [3,4,5,6]
console.log(newArray2);// [1,2,'aa','bb',7,8,9]
回傳新陣列,原陣列不改變
需要合併兩個或多個陣列時使用
var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
var new_array = old_array.concat(value1[, value2[, ...[, valueN]]])
要注意的是concat()中的引數若是一維陣列,則會將陣列的元素值串接回傳。但若是與二維(或多維)陣列合併的話,則會將裡面的陣列一併串接。
let array = [1,2,3];
// [1,2,3,4,5,6]
console.log(array.concat([4,5,6]));
// [1,2,3,7,8,9,Array(2)];
console.log(array.concat([7,8,9,[10,11]]));
回傳新陣列,原陣列不改變
arr.slice([begin[, end]])
slice(-2)
表示要拷貝陣列的最後兩個元素slice(1,-1)
表示拷貝陣列中的第二個元素至倒數第二個元素要注意的是在slice方法中,兩個數字皆為索引值,但是在splice的第二個參數是要刪除的元素數量。
const array = [1,2,3,4,5,6,7,8,[9,10]];
// 回傳從索引位置2到索引位置5之前的陣列元素
const newArray = array.slice(2,5);
console.log(newArray);
// 原陣列沒有被修改,所以回傳索引位置2之後至最後一個元素之前的所有元素
const newArray2 = array.slice(2,-1);
console.log(newArray2);
回傳新陣列,原陣列不改變
var new_array = arr.map(function callback(currentValue[, index[, array]]) {
// Return element for new_array
}[, thisArg])
map的意思是映射,維基百科中對於映射的定義是:
設 A,B 是兩個非空集合,若對 A 中的任一元素 x , 依照某種規律(或法則)f , 恆有 B 中的唯一確定的元素 y 與之對應,則稱對應規律 f 為一個從 A 到 B 的映射」
要簡單一點的解釋可以想成當輸入一個x值時,會有一個對應的y值輸出
且若是一個稀疏的陣列,則使用map()時,會將稀疏的位置一樣回傳
//一個稀疏陣列
const array = [1,2,,3];
const newArray = array.map(value => value * value);
console.log(newArray);
console.log(array);
回傳新陣列,原陣列不改變
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
filter的中文翻譯是「過濾」,可想而知就是可以用來作為資料篩選時使用
且filter()會跳過稀疏陣列的空值部分,永遠只會是個密集陣列
const array = [1,2,3,4,,5,6];
const newArray = array.filter((element,index) => (index + 1) % 2);
console.log(newArray);
console.log(array);
回傳值,原陣列不改變
arr.reduce(callback[accumulator, currentValue, currentIndex, array], initialValue)
使用reduce()
時,累加器與下一個元素值進行運算並得到一個值,且這個值會成為累加器的值並繼續跟下一個元素運算
而且處理陣列元素順序為由索引低至索引高(由左至右)
/*
執行步驟:
1. 初始值=1,此時accumulator=1,currentValue=1(陣列索引值0的值),並帶入函式運算得到 1*1 =1,accumulator的值變為1
2. accumulator值=1,accumulator=1,currentValue=2,並帶入函式運算得到 1*2 =2,accumulator的值變為2
3. accumulator值=2,accumulator=2,currentValue=3,並帶入函式運算得到 2*3 =6,accumulator的值變為6
4. 回傳最後運算的值 = 6
*/
const array = [1,2,3];
const value = array.reduce((accumulator,currentValue) => accumulator * currentValue,1);
console.log(value);
console.log(array);
回傳值,原陣列不改變
和reduce()行為相同,但處理陣列元素順序為由索引高至索引低(由右至左)
/*
執行步驟:
1. 初始值=1,此時accumulator=1,currentValue=3(陣列索引值2的值),並帶入函式運算得到 1*3 = 3,此時accumulator的值變為3
2. accumulator值=3,currentValue=2,並帶入函式運算得到 3*2 = 6,accumulator的值變為6
3. accumulator值=6,currentValue=1,並帶入函式運算得到 6*1 = 6,accumulator的值變為6
4. 回傳最後運算的值 = 6
*/
const array = [1,2,3];
const value = array.reduceRight((accumulator,currentValue) => accumulator * currentValue,1);
console.log(value);
console.log(array);
回傳布林值
當元素都回傳true時,才會回傳true,如果有任一個元素為false則回傳false並停止走訪陣列
every()
最終會回傳的值是一個布林值
const array = [1,3,5];
// 檢查是否有餘數,餘數不為0時回傳 true
const checkRemainder = array.every(value => value % 2 );
console.log(checkRemainder);
回傳布林值
當元素都回傳false時,才會回傳false,如果有任一個元素回傳true,則回傳true,並停止走訪整個陣列
const array = [1,3,5];
// 檢查是否有餘數,餘數為0時回傳 true
const checkRemainder = array.some(value => !value % 2);
console.log(checkRemainder);
單純走訪陣列
逐一將陣列元素值傳入自定義的函式中運算
沒有提供方法可以停止foreach走訪陣列,如果需要停止則需要丟出(throw)例外
mdn:除非是拋出異常,否則並沒有中止 forEach() 迴圈的辦法。如果你需要這樣做,forEach() 就是錯誤的用法,相反的,應該要用簡單的迴圈。如果你要測試陣列裡面的元素並回傳布林值,可以用 every() 或 some()。如果可以的話,新的方法 find() 或 findIndex() 也可以用於 true 值之後提前終止。
const array =[1,2,3];
array.foreach(function(value,index){
console.log(value);
console.log(index);
});
回傳索引值或元素值
arr.indexOf(searchElement[, fromIndex])
在陣列中由左至右找尋元素並回傳第一個被找到的元素索引值,沒有的話回傳-1
const array = ['a','b','c'];
// 回傳 index = 0
console.log(array.indexOf('a'));
// 在索引值2的位置開始找元素a,所以找不到元素,index = -1
console.log(array.indexOf('a',2));
回傳索引值或元素值
arr.lastIndexOf(searchElement, fromIndex)
行為和 indexOf()相反,從陣列最後面找尋元素並回傳第一個符合的索引值
const array = ['a','b','b','c'];
// 回傳 index = 0
console.log(array.lastIndexOf('a'));
// 回傳 index = 2
console.log(array.lastIndexOf('b',2));
原陣列會改變
copyWithin() 方法會對陣列的一部分進行淺拷貝至同一陣列的另一位置並回傳此陣列,而不修改其大小。
arr.copyWithin(target)
arr.copyWithin(target, start)
arr.copyWithin(target, start, end)
這邊要注意的是要拷貝的陣列不包含end索引值上的值
讓我們看看下面的例子加速理解
Ex:
var array = ['a', 'b', 'c', 'd', 'e'];
// 被拷貝的陣列元素:b,c,從元素a的位置開始取代
// ['b', 'c', 'c', 'd', 'e']
console.log(array.copyWithin(0,1,3));
Ex2:
var array1 = ['a', 'b', 'c', 'd', 'e'];
// 被拷貝的陣列元素:b,c,d,e,從元素a的位置開始取代
// ['b', 'c', 'd', 'e', 'e']
console.log(array1.copyWithin(0,1));
Ex3:
var array2 = ['a', 'b', 'c', 'd', 'e'];
// 被拷貝的陣列元素:c,d,從元素e的位置開始取代
// 要注意的是如果要取代的位置後方已經沒有元素,則只會取代存在的元素
// ['a', 'b', 'c', 'd', 'c'];
console.log(array2.copyWithin(-1,-3,-1));
回傳索引值或元素值
keys() 方法會回傳一個包含陣列中的 每一個索引鍵(keys) 的新Array Iterator物件。
關於 Array Iterator物件,在mdn中有這麼一段解釋:
可迭代協議: 可迭代(iterable)協議允許 JavaScript 物件定義或客制他們的迭代行為,例如哪些值可在 for..of 語法結構中被迭代出來。
可迭代協議
可以先理解成能否使用for..of將值取出
const array = [1,2,3,4];
const iterator = array.keys();
for(let key of iterator){
console.log(key);
}
回傳索引值或元素值
values() 方法會回傳一個包含陣列中的 每一個索引之對應值(values) 的新 Array Iterator 物件。
const array = ['aa','bb','cc','dd'];
const iterator = array.values();
for(let value of iterator){
console.log(value);
}
entries() 方法會回傳一個包含陣列中 每一個索引之鍵值對(key/value pairs) 的新陣列迭代器(Array Iterator)物件。
const array = ['aa','bb','cc','dd'];
const iterator = array.entries();
for(let [key,value] of iterator){
console.log(`索引值為:${key},值為: ${value}`);
}
回傳索引值或元素值
find() 方法會回傳第一個滿足所提供之測試函式的元素值。否則回傳 undefined。
arr.find(callback[, thisArg])
const array = [1,-5,55,4,5];
const value = array.find(value=> value >= 3);
console.log(value);
回傳索引值或元素值
與Array.prototype.find()行為類似,只是回傳的為元素的索引值
const array = [1,-5,55,4,5];
const value = array.findIndex(value=> value >= 3);
console.log(value);
原陣列會改變
fill() 方法會將陣列中索引的第一個到最後一個的每個位置全部填入一個靜態的值。
arr.fill(value[, start[, end]])
const array = [1,-5,55,4,5];
//從索引值2的位置將值取代為4
const value = array.fill(4,2);
//[1, -5, 4, 4, 4]
console.log(value);
//將索引值2至索引值3(不包含)間的元素值取代為4
//[1, -5, 8, 4, 5]
const value2 = array.fill(8,2,3);
console.log(value2);
回傳布林值
includes() 方法會判斷陣列是否包含特定的元素,並以此來回傳 true 或 false。
arr.includes(searchElement[, fromIndex])
const array = [1,-5,55,4,5];
const value = array.includes(-5);
console.log(value);
const value2 = array.includes(-9);
console.log(value2);
回傳新陣列,原陣列不改變
flat() 函數以遞迴方式將特定深度的子陣列重新串接成為一新的陣列
var newArray = arr.flat([depth]);
透過這個方法我們可以很快速地攤平多維陣列,變成一維陣列
const array = [1,-5,[55,33,1],4,[[5,7,9]]];
const value = array.flat();
console.log(value);
const value2 = array.flat(2);
console.log(value2);
在這之前的方法是運用reduce()搭配concat()完成
var arr1 = [1, 2, [3, 4]];
arr1.reduce((acc, val) => acc.concat(val), []);
回傳新陣列,原陣列不改變
是將flat()與map()合併運用,先透過map()映射每個元素後再透過flat()將多維陣列攤平成一維陣列。
這邊要注意的是flat()的深度=1,意思是只能將二維陣列攤平成一維陣列
var new_array = arr .flatMap(function callback(currentValue [,index [,array]]){
//返回new_array的元素
} [,thisArg ])
var array = [1, 2, 3, 4];
const newArray = array.flatMap(value => [value * value]);
console.log(newArray);
以上是陣列的方法,相信如果能妥善運用的話,肯定在陣列的操作上功力會大增!!
但你以為這樣就結束了嗎XD
除了陣列以外有些很常與陣列方法搭配運用的方法也需要提一提~
字串轉陣列
str .split([ separator [,limit ]])
let str ='1/2/4/5/7/6';
let array = str.split("/");//透過/切割字串
console.log(array);
這麼多的方法是要怎麼記啊!!!
所以底下我整理成了一個表格,記憶方式的參考依據為這個陣列方法使用後所得到的結果
對於我來說,我可以很快速地了解使用了這個方法會得到什麼值
陣列轉字串 | join() | ||||||||
原陣列會改變 | reverse() | sort() | unshift() | shift() | push() | pop() | splice() | copyWithin() | fill() |
回傳新陣列,原陣列不變 | concat() | slice() | map() | filter() | flat() | flatMap() | |||
回傳值,原陣列不變 | reduce() | reduceRight() | |||||||
回傳布林值 | every() | some() | includes() | ||||||
走訪陣列 | foreach() | ||||||||
回傳索引值或元素值 | indexOf() | lastIndexOf() | keys() | values() | entries() | find() | findIndex() | ||
字串轉陣列 | spilt() |
關於陣列方法的介紹就到這裡囉!