# 常用的陣列處理方法
###### tags: `JavaScript`
陣列的處理方法有非常多種,這邊依照類別舉出幾種我覺得比較常使用的方法。

## 改變原始陣列
### 新增/刪除
#### push()
`push()`可以將值加入到陣列中的最後一個位置。
```javascript=
let a = [1,2,3,4,5]
a.push(6);
console.log(a); // [1,2,3,4,5,6]
```
#### pop()
`pop()`可以移除(取出)陣列中最後一個值。
```javascript=
let a = [1,2,3,4,5]
let b = a.pop();
console.log(a); // [1,2,3,4]
console.log(b); // 5
```
#### shift(), unshift()
`shift()` 和 `unshift()` 分別可以移除(取出)和新增第一個值。
```javascript=
let a = [1,2,3,4,5]
let b = a.shift()
console.log(a) // [2,3,4,5]
console.log(b) // 1
a.unshift(1)
console.log(a) // [1,2,3,4,5]
```
#### splice()
`splice()`可以移除或取代陣列中指定位置的值。它包含了三個函數,第一個是**起始位置(必填-從0開始)**,第二個是**指定的長度(選填)**,最後一個是**取代的內容(選填-可以有多個)**。假如第二個參數不添加的話,預設是將起始位置後的參數全部刪除。
```javascript=
let a = [1,2,3,4,5]
a.splice(0);
console.log(a); // []
a.splice(0,5,1,2,3,4,5)
console.log(a); // [1,2,3,4,5]
a.splice(2,1)
console.log(a); // [1,2,4,5]
```
### 排序
#### reverse()
`reverse()`會反轉整個陣列的排序。
```javascript=
let a = [1,2,3,4,5]
a.reverse()
console.log(a) // [5,4,3,2,1]
```
#### sort()
`sort()`預設會將陣列中的值轉換成字串,並依照[UTF-16](https://https://asecuritysite.com/coding/asc2)的順序做排列。若想要依照數字大小排列的話就必須加入compareFunction(a,b),依照回傳值的不同給予相對應的排列順序。
| 回傳的值| 排列順序 |
| -------- | -------- |
| >0 | b在a前面 |
| <0 | a在b前面 |
| ===0 | 保持原本的排序 |
```javascript=
// 依照字串規則排序
let a = [1,20,3,40,5]
a.sort();
console.log(a) // [1,20,3,40,5]
// 依照數字大小排序
// 降序
a.sort((x,y)=>y-x);
console.log(a) // [40,20,5,3,1]
// 升序
a.sort((x,y)=>x-y);
console.log(a) // [1,3,5,20,40]
```
### 取代
#### copyWithin()
`copyWithin()`能夠複製陣列中某段值並取代指定的段落。它總共有三個參數,第一個是**取代的起始位置(必填)**,第二個是**複製的起始位置(選填-預設為0)**,最後是**複製結束的後一個位置(選填-預設等於陣列長度)**
```javascript=
let a = [1,2,3,4,5]
a.copyWithin(2);
console.log(a); // [1,2,1,2,3] 超過的部分會忽略
a.copyWithin(3,1,3);
console.log(a); // [1,2,1,2,1]
```
#### fill()
`fill()`能夠取代陣列中的所有值。它總共有三個參數,第一個是**取代的值(必填)**,第二個是**取代的起始位置(選填-預設為0)**,最後是**取代結束的後一個位置(選填-預設等於陣列長度)**
```javascript=
let a = [1,2,3,4,5]
a.fill(2);
console.log(a); // [2,2,2,2,2]
a.fill(3,1,3);
console.log(a); // [2,3,3,2,2]
```
## 查詢
### 陣列資訊
#### length
`length`可以查詢陣列長度。
```javascript=
let a = [1,2,3,4,5]
a.length; // 5
```
### 索引
#### indexOf(), lastIndexOf()
`indexOf()`和`lastIndexOf()`都可以用來判斷陣列中是否有某個值,並回傳其**第一個**索引值,假如沒有的話就回傳 -1。 兩者的差別在於判斷方向,`indexOf()`從頭開始判斷而`lastIndexOf()`則從尾巴開始判斷。兩者 都有兩個參數,第一個是**查詢的值(必填)**,第二個則稍微不同,`indexOf()`是**查詢的起始位置(選填-預設為0)**,`lastIndexOf()`是**判斷的結束位置(選填-預設為陣列的最後一個位置)**
```javascript=
let a = [2,3,3,2,2]
a.indexOf(2); // 0
a.indexOf(2,1); // 3
a.indexOf(1); // -1
a.lastIndexOf(2); // 4
a.lastIndexOf(3,3); // 2
// 判斷的陣列為[2,3,3,2],不是[2,2]
```
### 值
#### includes()
`includes()`可以查詢陣列中是否有某個值,有就回傳true,沒有則回傳false。
```javascript=
let a = [1,2,3,4,5]
a.includes(3); // true
a.includes(6); // false
```
### 符合條件
#### 值
##### find()
`find()`可以查詢陣列中符合條件的第一個值,如果沒有則回傳undefined。
```javascript=
let a = [1,2,3,4,5]
a.find(item=>item>3); // 4
a.find(item=>item>6); // undefined
```
#### filter()
`filter()`可以查詢陣列中符合條件的值,並將所有符合的值以一個新的陣列回傳,如果沒有則回傳[]。
```javascript=
let a = [1,2,3,4,5]
a.filter(item=>item>3); // [4,5]
a.filter(item=>item>6); // []
```
#### 索引
##### findIndex()
`findIndex()`可以查詢陣列中符合條件的第一個值,並回傳其索引值,如果沒有則回傳-1。
```javascript=
let a = [1,2,3,4,5]
a.findIndex(item=>item>3); // 3
a.findIndex(item=>item>6); // -1
```
#### Boolean
##### every()
`every()`可以用來判別陣列中所有的值有沒有符合條件,如果有則回傳true,沒有則回傳false。
```javascript=
let a = [1,2,3,4,5]
a.every(item=>item>0); // true
a.every(item=>item>3); // false
```
##### some()
`some()`可以用來判別陣列中有沒有值符合條件,如果有則回傳true,沒有則回傳false。
```javascript=
let a = [1,2,3,4,5]
a.some(item=>item>3); // true
a.some(item=>item>6); // false
```
## 針對每一個值做處理
### forEach()
`forEach()`可以依序處理陣列中的每一個值。它的參數是一個函式,裡面總共有三個參數,第一個參數代表**目前的值(必填)**,第二個則是**目前的索引值(選填)**,最後則是**原本的陣列(選填)**。
```javascript=
let a = [1,2,3,4,5]
a.forEach((item,index,arr)=>{
console.log(item,index,arr)
})
// 1 0 [1,2,3,4,5]
// 2 1 [1,2,3,4,5]
// 3 2 [1,2,3,4,5]
// 4 3 [1,2,3,4,5]
// 5 4 [1,2,3,4,5]
```
## 創造
### 字串
#### join()
`join()`可以藉由指定的字將整個陣列合併成一個字串,**預設為逗號**。
```javascript=
let a = [1,2,3,4,5]
a.join(); // '1,2,3,4,5'
a.join(''); // '12345'
```
### 陣列
#### concat()
`concat()`可以將兩個陣列合併為一個新的陣列。
```javascript=
let a = [1,2,3]
let b = [4,5]
a.concat(b); // [1,2,3,4,5]
[...a,...b]; // [1,2,3,4,5] ES6語法
```
#### slice()
`slice()`可以擷取陣列中的段落回傳一個新的陣列。它有兩個必填的參數,第一個是**起始位置**,第二個是**結束的後一個位置**。
```javascript=
let a = [1,2,3,4,5]
a.slice(2,4); // [3,4]
```
#### map()
`map()`可以依序處理陣列中的每一個值並回傳一個新的陣列。它的參數是一個**函式(必填)**和**this(選填)**。函式裡面又另外有三個參數,第一個參數代表**目前的值(必填)**,第二個則是**目前的索引值(選填)**,最後則是**原本的陣列(選填)**。
```javascript=
let a = [1,2,3,4,5]
a.map((item,index,arr)=>{
return item+1
},1) // [2,3,4,5,6]
a.map(function(item){
return item+this
},1) // [2,3,4,5,6]
a.map((item,index,arr)=>{
return item+this
},1)
// 無法使用箭頭函式,因為此時的this是window
console.log(a) // [1,2,3,4,5]
```
### 數字
#### reduce(), reduceRight()
`reduce()`和`reduceRight()`可以將陣列中每個值依序做計算,每次計算完的結果再跟下個值做計算直到結束。兩者的差別在於判斷方向,`reduce()`從頭開始計算而`reduceRight()`則從尾巴開始計算。兩者 都有兩個參數,第一個是**自訂的計算函式(必填)**,第二個是**初始值(選填-若無則分別為第一個值和最後一個值)**,函式內又有四個參數,第一個是**目前計算的總值(必填)**,第二個是**目前取得的值(必填)**,第三個是**該值的索引值(選填)**,第四個則是**原本的陣列(選填)**。
```javascript=
let a = [1,2,3,4,5]
a.reduce(function(total,item){
return total+item;
},10) // 25 (10+1+2+3+4+5=25)
a.reduceRight(function(total,item){
return total-item
}) // -5 (5-4-3-2-1=-5)
```
## 參考資料
[1] [JavaScript Array 陣列操作方法大全 ( 含 ES6 )](https://www.oxxostudio.tw/articles/201908/js-array.html#array_every)