1. 程式人生 > >ES6非常棒的特性-解構

ES6非常棒的特性-解構

好的程式碼實踐

我們有一個方法:buildAnimal(),它需要三個引數:accessory, animal, color。

function buildAnimal(accessory, animal, color){...}
  •  

然後我們需要加一個引數,我們需要怎麼做?很簡單啊,直接在方法名後面加不就好了嗎。

但是我們是好的程式設計師,怎麼能這麼沒追求啊是不是:

“Functions should have a small number of arguments. No argument is best, followed by one, two, and three. More than three is very questionable and should be avoided with prejudice.”
Robert C. Martin’s Clean Code

我們開始重構,把所有的引數放到一個物件裡面:animalData,它有下面三個屬性:animal, color, hairType

function buildAnimal(animalData){...}
  •  

如果要加引數,直接加到animalData的屬性裡面就好了。
但是,又有一個問題了。如果我們要衝物件裡面拿資料:可能要這樣:

function buildAnimal(animalData){
    let accessory = animalData.accessory,
        animal = animalData.animal,
        color = animalData.color,
        hairType = animalData.hairType;
    ...
}

程式碼重複了很多,很不優雅對不對!

解構

先定義一個物件:

let obj = {
    accessory: 'horn',
    animal: 'horse',
    color: 'purple',
    hairType:'curly'
}
  •  

解構的原理是:從一個物件一次性解析出多個屬性給不同變數,比如陣列中解析出元素,從map/set中解析出資料等。

模式

任何解構都有兩個部分
1 解構源: 等號右邊是要解構的物件。
2 解構目標:等號左邊是要解構的物件。

物件解構(解構源)

上面的例子,解構的寫法可以這樣:

function buildAnimal(animalData){
    let {accessory, animal, color, hairType} = animalData;
    ...
}

animalData的物件屬性給到變數:accessory, animal, color, hairType

console.log(accessory);//horn
console.log(animal); //horse
...
你可能要問,如果是多層巢狀的物件怎麼解構?
比如:
```javascript
let person = {
    name: 'Maya',
    age: 30,
    phone: '123',
    address:{
        zipcode: 1234,
        street: 'rainbow',
        number: 42
    }
}




<div class="se-preview-section-delimiter"></div>

我們可以這麼做:

let {address: {zipcode, street, number}} = person;
console.log(zipcode, street, number); //1234 rainbow 42




<div class="se-preview-section-delimiter"></div>

或者:

let {zipcode, street, number} = person.address;
console.log(zipcode, street, number); //1234 rainbow 42




<div class="se-preview-section-delimiter"></div>

可能有人說我們需要,我們的變數名需要和屬性名一樣。實際上不需要。我們可以重新修改它的名字:比如

let {name: fullName} = person;
console.log(fullName); //Maya
console.log(name); //ReferenceError: name is not defined.




<div class="se-preview-section-delimiter"></div>

解構陣列

比如我們定義這樣一個數組:

var arr = ["one", "two", "three", "four"];




<div class="se-preview-section-delimiter"></div>

這一次我們左邊就不能用{},而應該用[]:

var [first, second] = arr; //解構開始的兩個元素
var [,,third, four] = arr; //解構最後的兩個元素 【行2】
var [one, two, three, four] = arr //解構所有元素




<div class="se-preview-section-delimiter"></div>

說明:如果不要解構某一個元素,直接逗號隔開就行了,參考:【行2】。要注意的是逗號的位置和數量。
解構巢狀陣列:

var arr2 = [['one', 'two'], 'three', 'four'];
var [[one, two]] = arr2; //one = 'one', two = 'two'




<div class="se-preview-section-delimiter"></div>

解構可遍歷的物件:比如Map,Set,字串等

var [a, b] = new Set([1,2]); //a = 1, b = 2;
var [a, b] = new Map([[1,2], [2,3]]); //a= [1,2], b = [2,3]
var [x, y] = "xyz"; //x = "x", y = "y"




<div class="se-preview-section-delimiter"></div>

解構賦值

多個變數的宣告和初始化:

let a, b, c, d;
a = 2;
b = 3;
c = { id: 4 };
d = 5;
//Or: let a = 2, b = 3, c = { id: 4 }, d = 5;




<div class="se-preview-section-delimiter"></div>

解構賦值的話,我們可以這麼寫:

let a, b, c, d;
[a, b, c, d] = [2, 3, { id: 4 }, 5];
//Or: let [a, b, c, d] = [2, 3, { id: 4 }, 5];




<div class="se-preview-section-delimiter"></div>

解構帶上預設值

如果我們要解構的物件的屬性沒有值,甚至屬性不存在。這個時候,我們需要一個預設值:
通常我們可能會這麼寫:

let name = person.name || "default name"; // and so on




<div class="se-preview-section-delimiter"></div>

在解構裡面,我們可以這麼寫:

let {name = "default name"} = obj;




<div class="se-preview-section-delimiter"></div>

如果屬性不存在,name 會被賦值一個預設的值。
或者:

let {name: myFullName = "default name"} = obj;




<div class="se-preview-section-delimiter"></div>

如果屬性不存在,myFullName 會被賦值一個預設的值。

多引數: …操作符

比方說我們有一個數組,我們想要陣列的第一個元素,剩餘的元素用作其他用途。
一般我們會這麼寫:

let first = arr[0],
    rest = arr.slice(1);




<div class="se-preview-section-delimiter"></div>

ES6解構我們可以這麼寫:

let [first, ...rest] = arr;
console.log(first);// "one"
console.log(rest); //["two", "three", "four"]




<div class="se-preview-section-delimiter"></div>

注意:…操作符只能放到最後。

let [...rest, last] = arr;
//SyntaxError: Rest element must be last element




<div class="se-preview-section-delimiter"></div>

交換

function swap(arr, i, j){
    let temp = arr[i];
    arr[i] = arr[j];
    arr[j] = temp;
}




<div class="se-preview-section-delimiter"></div>

我們經常會有上面的交換兩個元素的程式碼。
有了解構以後,我們可以這麼寫:

function swap(arr, i, j){
   [arr[i], arr[j]] = [arr[j], arr[i]];
}




<div class="se-preview-section-delimiter"></div>

解構在函式中的好處

在上面的例子中,我們是這麼做的:

function buildAnimal(animalData){
    let {accessory, animal, color, hairType} = animalData;
    console.log(`I'm a ${color} ${animal} with ${accessory} and ${hairType} hair`};
}




<div class="se-preview-section-delimiter"></div>

實際上,我們希望直接從引數列表裡解構出來:

function buildAnimal({accessory, animal, color, hairType}}{...}




<div class="se-preview-section-delimiter"></div>

甚至可以定義預設值:

function buildAnimal({accessory = "", animal = "cat", color = 'rainbow', hairType = 'straight'}){...}




<div class="se-preview-section-delimiter"></div>

呼叫的方式這樣:

buildAnimal({accessory = "horn", animal = "horse", color = 'purple', hairType = 'curly'}};
//I'm a purple horse with a horn and curly hair.




<div class="se-preview-section-delimiter"></div>

注意一點:如果我們要預設引數,我們需要傳遞一個物件進去:

buildAnimal({}); //Works
buildAnimal(); //Not working.




<div class="se-preview-section-delimiter"></div>

我們能不傳遞一個空物件嗎?可以。

function buildAnimal({accessory = "", animal = "cat", color = 'rainbow', hairType = 'straight'} = {}){...}




<div class="se-preview-section-delimiter"></div>

我們給我們的引數一個預設的值:{}

陣列也是類似:

function sum([a = 0, b = 0, c = 0]=[]) { return a + b + c;}
console.log(sum([1, 2, 3])); //6
console.log(sum()); //0




<div class="se-preview-section-delimiter"></div>

解構不好的地方

1 我們不能解構,如果沒有采用宣告的語法,或者()包起來
因為解構是以{}開頭,而{}在JavaScript中當做一個塊,而不是物件常量。

let a, b;
{a, b} = {a: 1, b: 2}; //Error!!!
({a,b}) = {a: 1, b: 2}; //Error!!
({a, b} = {a: 1, b: 2}); //OK

2 巢狀物件的屬性必須存在否則會解構失敗

以上就是今天的主要內容,感謝閱讀。

原文連結,點選閱讀原文

## 解構不好的地方
1 我們不能解構,如果沒有采用宣告的語法,或者()包起來
因為解構是以{}開頭,而{}在JavaScript中當做一個塊,而不是物件常量。
```javascript
let a, b;
{a, b} = {a: 1, b: 2}; //Error!!!
({a,b}) = {a: 1, b: 2}; //Error!!
({a, b} = {a: 1, b: 2}); //OK

2 巢狀物件的屬性必須存在否則會解構失敗

 

轉載: https://blog.csdn.net/maoxunxing/article/details/79772946