JavaScript 筆記:Array基本介紹與進階方法
JavaScript中的array與其他程式語言相似,Properties 幾乎相同故不作介紹,以下簡介一下Array專屬的methods:
array.push(item);
array.pop();
array.shift();
array.unshift(item1, item2, ...);
push() 會添加一個或多個元素至陣列的末端,並且回傳陣列的新長度;
pop() 會移除並回傳陣列的最後一個元素。此方法會改變陣列的長度;
shift() 會移除並回傳陣列的第一個元素。此方法會改變陣列的長度;
unshift() 會添加一個或多個元素至陣列的開 頭,並且回傳陣列的新長度。
let arr1 = ['1' ,'1' ,'2' ,'3' ];
console.log(arr1.pop()); // Output: 3
console.log(arr1.push('4')) // 陣列的新長度--> 4
console.log(arr1.unshift('0')); //陣列的新長度--> 5
console.log(arr1); // Array ['0', '1', '1', '2', '4']
console.log(arr1.shift()); // Output: 0
console.log(arr1); // Array ['1', '1', '2', '4']
Array.splice()用法
從陣列中添加或刪除項目,回傳被刪除的項目。會改變原陣列。
array.splice(start);
array.splice(start, deleteCount);
array.splice(start, deleteCount, item1, item2, ...);
start 增加/刪除項目的位置,負數代表從後方算起。
deleteCount 刪除的個數,如為0則不會刪除。
item… 添加的新項目。
/* 刪除指定index的元素 */
let arr1 = ['1' ,'1' ,'2' ,'3' ];
console.log(arr1.splice(1, 1)) //1
console.log(arr1) // [1, 2, 3]
/* 刪除指定元素 */
let arr2 = ["apple", "orange", "banana", "citrus"]
let removeElement = "orange";
for(let i=0; i<arr2.length; i++){
if(arr2[i] === removeElement){
arr2.splice(i, 1);
//當arr2[i] === "orange" 刪除一個元素(orange)
i--; //刪減元素後字串倒退前元素
}
}
forEach() Function
forEach() 的用法與傳統for loop類似,都能夠loop through Array,但forEach()的可讀性和使用性一般都比for loop來的高。
forEach需要一個Function(CallBack Function)作爲其parameter:
let luckyNumbers = [7, 15, 23, 66, 91, 10, 13];
//直接在forEach裏declare function
luckyNumber.forEach(function checkNum(n){
if(n > 20) console.log(n); // Expected output: 23, 66, 91
});
//在外部declare function然後再作使用,注意checkNum在forEach裏不用加上()及在內的parameter
luckyNumber.forEach(checkNum); // Expected output: 23, 66, 91
function checkNum(n){
if(n > 20) console.log(n);
}
//等效for loop用法
for(i=0; i<luckyNumber.length; i++){
if(luckyNumber[i] > 20) console.log(n); // Expected output: 23, 66, 91
}
在forEach()裏更能夠執行Arrow Function Expression,這樣看起來寫法更短了:
let luckyNumbers = [7, 15, 23, 66, 10, 91, 13];
//forEach with Arrow Function Expression
luckyNumbers.forEach((n) => {
if (n > 20) console.log(n); // Expected output: 23, 66, 91
});
//CallBack Function裏亦可加入多個parameter
luckyNumbers.forEach((n, index) => {
if (n > 20) {
console.log(n);
console.log(n + " is at index " + index);
}
});
至於什麼是CallBack Function,這邊的解析更好所以我直接丟連結:
什麼是Callback函式 (Callback function)
Array.concat()
JavaScript中的Array沒辦法直接使用加號串接,兩Array相加時形態會轉爲string,在此可以使用Array.concat():
let arr1 = ['1', '2', '3'];
let arr2 = ['4', '5', '6'];
let arr = arr1 + arr2;
console.log(arr); // 1,2,34,5,6
console.log(typeof arr); // string
arr = arr1.concat(arr2);
console.log(arr); // Array(6) ["1","2","3","4","5","6"]
Array.isArray()
用於判斷型別是否爲Array,注意.isArray是Array物件裏的method:
let arr1 = ['1', '2', '3'];
console.log(Array.isArray(arr)); // true
Spread Operator
上述Array串接的動作也可以透過Spread Operator實現:
let arr1 = ['1', '2', '3'];
let arr2 = ['4', '5', '6'];
//Spread Operator(...)允許多個parameter輸入
let arr = [...arr1, ...arr2];
console.log(arr); // Array(6) ["1","2","3","4","5","6"]
JavaScript裏的Object與Array是Reference Data Type!!!
當你在定義 b: array = a: array 的時候,b: array 實則會指到 a: array 的記憶體位置,等於 a 跟 b 會共用同一塊記憶體,導致 a 的值被變更的時候同時會帶動 b 改變:
let arr1 = ["1", "2", "3"];
let arr2 = arr1;
arr1.push("4"); // 只對arr1.push("4")
console.log(arr1); // Array(4) ["1","2","3","4"]
console.log(arr2); // Array(4) ["1","2","3","4"]
// 結果連同arr2一起修改了
可以透過spread operator複製Array:
let arr1 = ['1', '2', '3'];
let arr2 = [...arr1];
arr2.push('4');
console.log(arr1) // Array(3) ["1", "2", "3"]
console.log(arr2) // Array(4) ["1", "2", "3", "4"]
進階的Array Function
在操作Array上還有一些實用的方法可以大大提升開發效率:
map()
find()
filter()
some()
every()
sort()
reduce()
map() 方法會建立一個新的陣列,其內容為原陣列的每一個元素經由回呼函式運算後所回傳的結果之集合。
find() 方法會回傳第一個滿足所提供之測試函式的元素值。否則回傳 undefined。
filter() 方法會建立一個經指定之函式運算後,由原陣列中通過該函式檢驗之元素所構成的新陣列。
some() 方法會透過給定函式、測試陣列中是否至少有一個元素,通過該函式所實作的測試,回傳布林值。
every() 方法會測試陣列中的所有元素是否都通過了由給定之函式所實作的測試,同樣回傳布林值。
sort() 方法會對一個陣列的所有元素進行排序,並回傳此陣列。預設的排序順序是根據字串的 Unicode 編碼位置而定。
reduce() 比較複雜,本節下部分再講解。
let languages = ["JavaScript", "C++", "Python", "C"];
//map(),注意Array.map()會return一個新的Array
upperLanguages = languages.map((i) => return i.toUpperCase());
console.log(upperLanguages); // Array(4) [ "JAVASCRIPT", "C++", "PYTHON", "C" ]
// Object Array
const languages2 = [
{ name: "Python", rating: 9.5 },
{ name: "JavaScript", rating: 8.0 },
];
//find(),回傳第一個與CallBack Function條件相符的物件
const highRatingLangs = languages2.find((lang) => {
return lang.rating > 7.5;
});
console.log(highRatingLangs); // Object { name: "Python", rating: 9.5 }
//filter(),回傳所有與CallBack Function條件相符的物件
const allHighRatingLangs = languages2.filter((lang) => {
return lang.rating > 7.5;
});
console.log(allHighRatingLangs); // Array [ {…}, {…} ]
// 0: Object { name: "Python", rating: 9.5 }
// 1: Object { name: "JavaScript", rating: 8 }
//some(),如Array中存在與CallBack Function條件相符的物件回傳true
const someHighRate = languages2.some((lang) => {
return lang.rating > 8.5;
});
console.log(someHighRate); // true
//every(),如Array中所有物件都跟CallBack Function條件相符回傳true
const someHighRate = languages2.every((lang) => {
return lang.rating > 8.5;
});
console.log(someHighRate); // false
let arr = ["Watermelon", "Apple", "Oranges"];
arr.sort(); // Array.sort()會直接更動原Array
console.log(arr); // Array(3) [ "Apple", "Oranges", "Watermelon" ]
// 按Unicode 編碼位置排序
//指定sort()函數爲字串長度排序(小至大)
arr.sort((a, b) => {return a.length - b.length;});
console.log(arr); // Array(3) [ "Apple", "Oranges", "Watermelon" ]
// 大至小 arr.sort((a, b) => {return b.length - a.length;});
let numArr = [1, 99, 10, 4, 56];
console.log(numArr.sort()); // Array(5) [ 1, 10, 4, 56, 99 ]
// 處理數字依然預設按Unicode 編碼位置排序
//指定sort()函數爲數字大小排序(小至大)
numArr.sort((a, b) => {return a - b;});
console.log(numArr); // Array(5) [ 1, 4, 10, 56, 99 ]
// 大至小 numArr.sort((a, b) => {return b-a;});
至於reduce(),先參照一下MDN的講解:
reduce() 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。
基礎語法爲:
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
- accumulator:用來累積回呼函式回傳值的累加器
- currentValue:原陣列目前所迭代處理中的元素
- currentIndex:原陣列目前所迭代處理中的元素之索引
- array:呼叫 reduce() 方法的陣列
- initialValue:於第一次呼叫 callback 時要傳入的累加器初始值,假如於一個空陣列呼叫 reduce() 方法且沒有提供累加器初始值,將會發生錯誤
- 回傳的爲一個值,不見得一定是陣列
reduce()的用法頗多,在此只示範稍微基礎的部分,進階用法有機會會作補充。
//陣列數值加總,未提供initialValue,accumulator取用陣列的第一個元素
const arr = [1, 2, 3, 4, 5];
const accumulatedArr = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 1, 3, 6, 10
console.log(currentValue); // 2, 3, 4, 5
return accumulator + currentValue;
});
console.log(accumulatedArr); // 15
//陣列數值加總,initialValue爲5,accumulator從5開始累加
const accumulatedArr2 = arr.reduce((accumulator, currentValue) => {
console.log(accumulator); // 5, 6, 8, 11, 15
console.log(currentValue); // 1, 2, 3, 4, 5
return accumulator + currentValue;
}, 5);
console.log(accumulatedArr); // 20
//合併陣列(平坦化、降維),要把initialValue設定成空陣列不然會報錯
const nestedArr = ['a', ['a', 'b'], 'c', ['c', 'd'], ['e', 'f']];
const flattenArr = nestedArr.reduce((accumulator, currentValue) => {
return accumulator.concat(currentValue);
}, []);
console.log(flattenArr); // [ 'a', 'a', 'b', 'c', 'c', 'd', 'e', 'f' ]
//計算相同字串出現的次數並回傳物件,initialValue是空物件
const elementArr = ['h1', 'h1', 'p', 'button', 'button', 'button', 'event'];
const countElement = elementArr.reduce((accumulator, currentValue) => {
if(accumulator[currentValue]) {
accumulator[currentValue]++;
} else {
accumulator[currentValue] = 1;
}
return accumulator;
}, {});
console.log(countElement); // { h1: 2, p: 1, button: 3, event: 1 }