帶你深刻的理解數組和對象的解構賦值。

es6提供了一個很是好的特性,即變量的解構賦值。從而咱們能夠方便的從數組和對象中提取數據並將它們賦值給變量。這是很是必要的。先來看在這個新特性發布以前咱們是如何從數組中提取數據的。以下:javascript

let nums = [1,2,3,4,5];
let num1 = nums[0];
let num2 = nums[1];

console.log(num1); // logs 1
console.log(num2); // logs 2
複製代碼

爲了從 nums 數組中提取到數據,咱們屢次重複着相同的代碼。es6的解構賦值將會讓這個操做變得很是的容易且易於理解。java

數組的解構賦值

從數組中取值並按照對應位置對變量進行賦值。以下:es6

let [num1,num2,num3] = [1,2,3];
 console.log({num1},{num2},{num3})
複製代碼

「模式匹配」賦值

這屬於「模式匹配」,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值。數組

let [num_s,nums,num_e] = [1,[2,3,4],5];
console.log(num_s) // logs 1
console.log(nums) // logs [2,3,4]
console.log(num_e) // logs 5
複製代碼

用逗號跳過元素

let [num1,,,num4] = [1,2,3,4];
console.log(num1) // logs 1
console.log(num4) // logs 4

let [,num2,,num4] = [1,2,3,4];
console.log(num2) // logs 2
console.log(num4) // logs 4
複製代碼

查看變量賦值左側的數組。注意這裏不是隻有一個逗號,而是三個。逗號分隔符用於跳過數組中的值。因此若是你想要跳過數組中的一個項,只要用逗號就能夠了。函數

數組中的其他部分的賦值

若是咱們想將數組中的一些元素賦值給變量,而將數組中的其他元素存爲一個數組賦值給指定的變量怎麼辦?在這種狀況下,咱們能夠這樣作:ui

let [num1,...nums] = [1,2,3,4];
console.log(num1) // logs 1
console.log(nums) // logs [2,3,4]
複製代碼

應用這種方式,你能夠輕鬆的把剩餘的元素賦值給一個指定的變量。spa

解構失敗,賦值undefined

let [num1] = [];
let [num2, num3] = [1];
console.log(num1) // logs undefined
console.log(num3) // logs undefined
複製代碼

代碼中的變量num1與變量num3 按照模式匹配原則,並無對應的值與之匹配,故而返回undefined。而變量num2 按照模式匹配原則,被賦值爲2。3d

函數的解構賦值

解構賦值還能夠從函數返回的數組中提取數據。假設咱們有一個返回數組的函數,以下例所示:code

function getLists() {
    let lists = [1,2,3,4,5]
    return lists;
}
let [num1,...nums] = getLists();

console.log(num1); // logs 1
console.log(nums); // logs [2,3,4,5]
複製代碼

使用默認值

數組的解構賦值能夠給變量設定默認值,以防萬一從數組中提取的值是 undefined(防止解構失敗的狀況)cdn

let [name = "暫無姓名",sex = "女"] = ["April"];

console.log(name); // "April"
console.log(sex); // "女"
複製代碼

代碼中變量name 默認的值爲 "暫無姓名" 可是按照左右模式匹配的原則,name 被賦值爲 "April" ,由於變量sex並未匹配到值,因此它的值依舊是默認值"女"

注意點1:ES6 內部使用嚴格相等運算符(===),判斷一個位置是否有值。因此,只有當一個數組成員嚴格等於undefined,默認值纔會生效。

let [num1 = 1] = [undefined];
console.log(num1) // logs 1

let [num2 = 2] = [null];
console.log(num2) // logs null
複製代碼

代碼中,由於null不嚴格等於undefined,默認值就不會生效。故而輸出了 null

注意點2:若是默認值是函數,這個函數就會很是的懶,即只有在用到的時候,纔會執行函數。

function getLists(){
    let lists = [1,2,3,4,5]
    return lists; 
 }
let [lists = getLists()] = [1];
console.log(lists) // logs 1
// 由於變量 lists 能夠匹配到值,因此函數 getLists() 並不會執行。

 function getLists(){
    let lists = [1,2,3,4,5]
    return lists; 
 }
let [lists = getLists()] = [];
console.log(lists) // logs [1,2,3,4,5]
// 由於變量 lists 沒法匹配到值,函數 getLists() 就會執行。故而返回數據 [1,2,3,4,5]
複製代碼

注意點3:默認值能夠引用解構賦值的其餘變量,但該變量必須已經聲明。

let [x = 1, y = x] = [];     // logs x=1; y=1
let [x = 1, y = x] = [2];    // logs x=2; y=2
let [x = 1, y = x] = [1, 2]; // logs x=1; y=2
let [x = y, y = 1] = [];     //logs 這就要報錯啦,由於x用y作默認值時,y尚未聲明。
複製代碼

交換變量

let num1 = 1;
let num2 = 2;

[num1,num2] = [num2,num1];

console.log({num1}); // logs 2
console.log({num2}); // logs 1
複製代碼

對象的解構賦值

爲何要用對象的解構賦值呢??

let profiles = {
    name:'April',
    nickname:"二十七刻",
    sign:"不以物喜,不以己悲。"
 }
           
let name = profiles.name;
let nickname = profiles.nickname;
let sign = profiles.sign;

console.log({name}) // "April"
console.log({nickname})// "二十七刻"
console.log({sign}) // "不以物喜,不以己悲。"
複製代碼

假設咱們要從對象profiles中獲取數據並賦值給新變量。就得不斷的重複着取值與賦值。代碼冗長且不利於維護。利用對象的解構賦值,就不存在這一問題了。

同屬性名賦值

對象的解構賦值變量必須與屬性同名,才能取到正確的值。以下:

let profiles = {
     name:'April', 
     nickname:"二十七刻", 
     sign:"不以物喜,不以己悲。"
}
let {name,nickname,sign} = profiles;

console.log({name})    // logs "April"
console.log({nickname})// logs "二十七刻"
console.log({sign})    // logs "不以物喜,不以己悲。"
複製代碼

解構失敗,賦值undefined

let profiles = {
    name:'April',
    nickname:"二十七刻",
    sign:"不以物喜,不以己悲。"
}
let {name,sex} = profiles;

console.log(name) // logs "April"
console.log(sex) // logs undefined
複製代碼

上面代碼中,由於profiles對象沒有 sex屬性,因此變量sex取不到值,因此就賦值undefined

在賦值以前申明變量

在對象的解構賦值中,變量能夠在賦值以前申明。以下:

let profiles = {
    name:'April',
    nickname:"二十七刻",
    sign:"不以物喜,不以己悲。"
}
let name,nickname,sign;
{name,nickname,sign} = profiles;

console.log(name) // logs Error : "Unexpected token ="
複製代碼

嘿呀~報錯了!爲何???

緣由:由於忘記在{}外層寫()了。

注意1 :當使用沒有聲明的對象字面量解構賦值時,必須使用()的賦值語句。由於 JavaScript 引擎會將{name,nickname,sign}理解成一個代碼塊,而不是對象字面量。

注意2 :使用此語法時,上一行代碼必定要以;結束掉,不然的話會被看成函數,執行上一行的代碼。

就是這個奇怪的語法 :({} = '');

正確的作法以下:

let profiles = {
    name:'April',
    nickname:"二十七刻",
    sign:"不以物喜,不以己悲。"
}
let name,nickname,sign;
({name,nickname,sign} = profiles);

console.log({name},{nickname},{sign})
// logs {name: "April"} {nickname: "二十七刻"} {sign: "不以物喜,不以己悲。"}
複製代碼

使用新的變量名

若是咱們想用新的變量名來替代對象的屬性名怎麼辦呢?代碼以下:

let profiles = {
    name:"April",
    age:"27"
}
let {name:userName,age:userAge} = profiles;

console.log(userName) // logs "April"
console.log(userAge) // logs "27"
複製代碼

由此可知,對象的解構賦值其實就是let {name:name,age:age} = {name:"April",age:"27"}代碼的簡寫。也就是說,對象的解構賦值的內部機制,是先找到同名屬性,而後再賦給對應的變量。真正被賦值的是後者,而不是前者。

上面代碼中,name是匹配的模式,userName纔是變量。真正被賦值的是變量userName,而不是模式name

使用默認值

對象的解構賦值能夠給變量設定默認值,以防萬一從對象中獲取的值是 undefined(防止解構失敗的狀況)須要注意的是:默認值生效的條件是,對象的屬性值嚴格等於undefined

let staff = {name: "April", country: "China", job: "Developer"};
let {name = "暫無姓名", age = "暫無年齡"} = staff;

console.log({name}); // logs "April"
console.log({age}); // logs "暫無年齡"
複製代碼

代碼中變量name的默認值爲「暫無姓名」,可是對象staff中有屬性爲name的字段,因此就被賦值April,而對象staff中並無age這個屬性,因此被賦值爲"暫無年齡",取了它本身的默認值。

計算屬性名稱

計算屬性名是另外一個對象特性,也適用於對象的解構賦值。你能夠經過一個表達式指定一個屬性的名稱,把它放在[]中,以下:

let staff = {name: "April", country: "China", job: "Developer"};
let prop = "name";
let {[prop]: name} = staff;

console.log({name}); // logs "April"
複製代碼

對象中的其他部分的賦值

解構運算也能夠被應運到解構賦值當中,來獲取那些尚未被賦值的鍵值對,這些鍵值對都被放在一個新的對象裏。以下:

let staff = {name: "April", country: "China", job: "Developer",nickname:"二十七刻"};
let {country,...infos} = staff;

console.log(country) //logs "China"
console.log(infos) // logs {name: "April", job: "Developer", nickname: "二十七刻"}
複製代碼

嵌套對象的解構賦值

let staffs = {
    group1:[ { id:"007", name:"April"}]
}
let {group1,group1:[{id,name}]} = staffs;

console.log(group1) // logs [{ id:"007", name:"April"}]
console.log(id) // logs "007"
console.log(name) // logs "April"
複製代碼

注意,代碼中group1是模式,不是變量。若是想把group1也做爲變量賦值,就要先進行定義再去賦值。

總結

數組和對象的解構賦值,本文就總結這麼多。不足之處,萬望指出。

相關文章
相關標籤/搜索