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
也做爲變量賦值,就要先進行定義再去賦值。
數組和對象的解構賦值,本文就總結這麼多。不足之處,萬望指出。