[toc]
### 解構的相關概念
#### 什么是解構
ES6中制定了一種語法規則,可以將一個對象或數組的某個屬性提取到指定的變量中。
#### 解構的分類
ES6中解構可以分為對象解構和數組解構兩種。
#### 解構的作用
解構可以很方便的從對象或數組中提取對應屬性的值,減少代碼量的書寫。
### 對象解構
**對象的解構不會對被解構的對象產生任何影響,僅是從被解構的對象中獲取數據。**
#### 對象解構的標準寫法
```js
const student =?{
classNum:?3,
name:?"John",
age:?16,
address:?{
province:?'黑龍江',
city:?'哈爾濱'
}
}
//上面定義了一個學生信息的對象,傳統寫法中若想要提取出對象的每一個屬性會使用下面的方法
let classNum = student.classNum;
let name = student.name;
let age = student.age;
let address = student.address
//這樣的寫法在對象屬性多的時候會增加代碼量
//ES6中使用解構的方式來達到上方同樣的效果,寫法如下:
let?{classNum,?name,?age,?address}?= student;
//上面的代碼表示:先定義4個變量,然后從對象中讀取同名屬性,并將其value賦值給變量。
```
#### 解構中使用默認值
在對象解構的過程中(尤其是在ajax請求返回的對象中),很多時候我們并不確定對象中是否存在我們想要的屬性。此時我們想實現一個效果:當對象中存在這個屬性,就獲取其屬性值。當對象中不存在這個屬性,就給需要取值的變量一個默認值。在解構中可以這樣寫:
```js
const student =?{
classNum:?3,
name:?"John",
age:?16,
address:?{
province:?'黑龍江',
city:?'哈爾濱'
????}
}
let?{classNum,?name,?age,?address,?abc}?= student;
//上面的代碼中,student對象中并沒有abc的屬性。但在解構過程中abc的這個變量已被創建,所以其值為undefined。
let?{classNum,?name,?age,?address,?abc = 123}?= student;
//為了防止對象中不存在abc的屬性,我們給abc屬性一個默認值123,當student對象中存在abc屬性,則abc使用student對象中同名屬性的值,如果student對象中不存在abc這個屬性,則abc的值為123。
```
#### 非同名屬性的解構
如果在解構的過程中,定義的變量名與對象中的屬性名不相同時,使用如下方法解構:
```js
//變量名與對象屬性名不同時,使用{屬性名:變量名}的方式。
const student = {
classNum: 3,
name: "John",
age: 16,
address: {
province: '黑龍江',
city: '哈爾濱'
}
}
//如果想用classNumber變量獲取對象中classNum屬性,可在屬性名后面加冒號和變量名
//若想同時使用默認值,可以直接在新的變量名后面加默認值即可。
let?{classNum:?classNumber = 3,?name,?age,?address,?abc}?= student;
```
#### 對象的深層解構
對于上面的student對象,如果我們只想獲取name和city兩個屬性,可以使用下面的方法:
```js
let?{name,?address:?{city}}?= student;
//這條語句表示從address中進一步解構,獲取city的值,并賦值給變量city
//若city中還存在更深層的對象,可以再嵌套進行解構。
//非同名或默認值的方法同上
```
### 數組解構
#### 數組解構的標準寫法
在對象解構中獲取數據的變量使{ }來包裹,數組解構中使用[ ]來包裹變量,例如:
```js
const arr =?[1,2,3,4,5,6];
//如果想獲取數組中前三位的值,寫法如下
let?[n1,?n2,?n3]?= arr;
//此時n1=1,n2=2,n3=3????
```
>數組解構中默認值的用法與對象相同。
>數組的解構是按照變量的排列順序對應在數組中的排列順序進行賦值的,所以如果需要不重名的變量,直接在解構變量的對應位置上修改變量名就可以
>如果只想獲取數組中第1位和第3位的數據,只需把不需要獲取數據的那位空出來就可以
```js
let?[n1,,n3]?= arr;???//n1=1,n3=3
```
>同樣,如果變量組的變量個數超出了數組的長度,多的變量可以賦默認值,或默認為undefined
#### 數組的深層解構
若數組中還嵌套著數組,需要獲取深層數組中某個下標的值,例如:
```js
const arr1 =?[1,?2,?3,?[11,?22,?33],?5,?6,?9];
//若要獲取數組中第4位的數組中第3位的數據,只需把前面的下標空位,并嵌套數組解構即可
let?[,,,[,,n]]?= arr1;???//n的值為33
```
若數組中嵌套對象,可以使用數組解構嵌套對象解構的方式
```js
const arr3 =?[1,?2,?3,?{a:?11,?b:?22,?c:?66},?5,?6,?9];
let?[,,,{c:?res}]?= arr3;????//res的值為66
```
>默認值和非同名屬性解構等規則也同樣適用
### 剩余項解構
無論是對象解構還是數組解構,如果我們需要獲取第一位上的值給一個變量,其它除第一項以外的剩余部份賦值給一個新的數組。可以使用展開運算符。
```js
//針對對象的剩余解構
const student =?{
class:?3,
name:?"John",
age:?16,
address:?{
province:?'黑龍江',
city:?'哈爾濱'
}
}
let?{name,?...other}?= student;
//name值為John,other對像中包含student對象中除name以外剩余所有屬性。
//針對數組的剩余解構
const num =?[1,?2,?3,?[11,?22,?33],?5,?6,?9];
let?[,?n1,?...nums]?=num;
//n1值為2,nums中包含從數組第3位開始到最后的所有數據(即:nums中并不包含數組下標第一位的1)。
```
**兩者區別:對象剩余解構會獲取除單獨解構以外的所有屬性值。數組解構僅會獲取最后一個單獨解構的位置之后的所有剩余屬性,之前的數組下標的值,即使沒有被其它變量獲取,也不會被放在剩余解構的變量中**
### 解構的其它用途
#### 實現兩個變量值的交換
```js
let a = 11,?b = 22;
[b,?a]?=?[a,?b];????//通過數組解構的方式進行變量交換
console.log(a,?b);??//a的值22,b的值11
```
#### 參數解構(重點撐握)
當我們的函數的參數是一個對象,且函數體中需要用到參數對象的各個值,可以直接在參數位置進行解構。
```js
function print({class,?name,?age,?address:{province,?city}}){
console.log('班級',?class);
console.log('姓名',?name);
console.log('年齡',?age);
console.log('所屬省份',?province);
console.log('所在城市',?city);
}
print(student);
//在參數中解構就可以在函數體中直接使用對象中的屬性。例如城市名就無需在函數體中寫student.address.city了。
```
>參數解構會存在一個問題,當用戶調用時沒有給參數。那么系統默認參數為undefined或null,但是這兩個對象是無法被解構的,即使在解構中設置了默認值也一樣會報錯。為了解決這個問題,可以結合參數默認值的方法。例如
```js
function ajax({method= 'get',?url= '/app'}?=?{}){
//函數體
}
//我們把解構對象看做一個參數,如果沒有值,默認值參數是一個空對象。這樣就可以使用解構對象中的默認值。
ajax();
//method值為'get',url值為'/app'
```