JavaScript 解構(gòu)賦值實用指南
今天來看看ES6 解構(gòu)賦值的實用技巧~
一、基本概念
為什么需要解構(gòu)呢,先來看一個例子:
const?student?=?{
????name:?'ZhangSan',
????age:?18,
????scores:?{
????????math:?19,
????????english:?85,
????????chinese:?100
????}
};
function?displayInfo(student)?{
????console.log('name:',?student.name);
????console.log('math:',?student.scores.math);
????console.log('english:',?student.scores.english);
????console.log('chinese:',?student.scores.chinese);
}
displayInfo(student);
這樣寫也能實現(xiàn)預(yù)期效果,但是代碼看起來比較冗余。并且,如果對象內(nèi)部嵌套較深時,那么對象的訪問鏈就會變得很長。雖然這并不是什么大問題,但是使用解構(gòu)賦值會讓代碼變得更簡單和易讀。
下面就來看看什么是解構(gòu)賦值。MDN 中對解構(gòu)賦值的描述:
解構(gòu)賦值語法是一種 Javascript 表達式。通過解構(gòu)賦值, 可以將屬性值從對象/數(shù)組中取出,賦值給其他變量。
實際上,結(jié)構(gòu)賦值就是將復(fù)雜的結(jié)構(gòu)分解為簡單的部分。解構(gòu)賦值語法可以用于變量聲明或者變量賦值。除此之外,還可以使用嵌套的解構(gòu)賦值語法來處理嵌套結(jié)構(gòu)。
比如,對上面例子中的對象進行解構(gòu):
function?displayInfo(student)?{
??const?{?name,?scores:?{math,?english,?chinese}?}?=?student;?
????console.log('name:',?name);
????console.log('math:',?math);
????console.log('english:',?english);
????console.log('chinese:',?chinese);
}
這樣看起來是不是簡潔多了。
二、解構(gòu)分類
根據(jù)MDN對解構(gòu)賦值的定義,我們可以將解構(gòu)賦值分為兩大類:
對象解構(gòu) 數(shù)組解構(gòu)
下面就分別來看看這兩種解構(gòu)賦值。
1. 對象的解構(gòu)賦值
對象解構(gòu)又稱為對象屬性分配模式,它允許我們將對象的屬性值分配給相應(yīng)的變量。它有兩種寫法:
let?obj?=??{x:?1,?y:?2,?z:?3};
let?{x:?a,?y:?b,?z:?c}?=?obj;
console.log(a,?b,?c)
let?{x,?y,?z}?=?obj;
console.log(x,?y,?z)
第一種(第3行)是對象解構(gòu)的完整形式,對象的每個屬性都將被分配一個變量,其中冒號前面的是源對象中的屬性,冒號后面的是要賦值屬性; 第二種(第5行)是對象解構(gòu)的簡寫形式,對象的屬性與要分配的屬性一致時可以使用這種形式。
如果需要給已有變量賦值,就需要額外注意了:
let?obj?=??{x:?1,?y:?2,?z:?3};
let?x?=?0,?y?=?0,?z?=?0;
({x,?y,?z}?=?obj)
console.log(x,?y,?z)
這里需要注意,需要將賦值表達式使用括號括起來,如果省略,解構(gòu)對象將被視為一個塊語句,而塊語句是不能放在賦值表達式左側(cè)的。
當(dāng)使用解構(gòu)賦值時,可以給變量傳遞一個默認(rèn)值:
const?person?=?{
????name:?'ZhangSan',
????height:?180
};
const?{?name,?height,?age?=?25?}?=?person;
console.log(name,?height,?age);
這里我們給age分配了一個默認(rèn)值,當(dāng)對源對象上不存在age屬性時,age就會被賦上默認(rèn)值25,而不是undefined。
如果分配的對象屬性為undefined,那么就會使用默認(rèn)值:
const?{x?=?2}?=?{x:?undefined};
console.log(x);????//?2
2. 數(shù)組的解構(gòu)賦值
在使用數(shù)組解構(gòu)時,實際上會使用迭代器將所需要的值與結(jié)構(gòu)源分開。因此,我們可以對可迭代值使用數(shù)組結(jié)構(gòu),包括字符串、數(shù)組、集合、函數(shù)映射、DOM元素。我們還可以將解構(gòu)賦值與擴展運算符結(jié)合使用。
(1)字符串
let?message?=?'Hello';
let?[a,?b]?=?message;
let?[x,?y,?...z]?=?message;
console.log(a,?b);????????//?H?e
console.log(x,?y,?z);?????//?H?e?['l',?'l',?'o']
(2)數(shù)組
let?numbers?=?[1,?2,?3];
let?[x,?y,?z]?=?numbers;
console.log(x,?y,?z);????//?1?2?3
(3)集合
let?set?=?new?Set().add('foo').add('bar');
let?[a,?b]?=?set;
console.log(a,?b);??????//?foo?bar
(4)Map
let?map?=?new?Map().set('a',?1).set('b',?2);
let?[x,?y]?=?map;
console.log(x,?y);????//?["a",?1]?["b",?2]
在數(shù)組的解構(gòu)中,存儲變量的數(shù)組中的每個變量都會映射到解構(gòu)數(shù)組上相同索引處的相應(yīng)項。
如果解構(gòu)中某一項不需要,可以使用逗號操作符進行分隔:
const?rgb?=?[200,?255,?100];
const?[,,?blue]?=?rgb;
console.log(blue);???//?100
與對象解構(gòu)一樣,可以使用數(shù)組解構(gòu)為局部變量設(shè)置默認(rèn)值:
const?rgb?=?[200];
const?[red?=?255,?green,?blue?=?255]?=?rgb;
console.log(`R:?${red},?G:?${green},?B:?${blue}`);
如果變量已經(jīng)存在,就可以這么寫:
let?red?=?100,?green?=?200,?blue?=?50;
const?rgb?=?[200,?255,?100];
[red,?green]?=?rgb;
console.log(`R:?${red},?G:?${green},?B:?${blue}`);
與對象解構(gòu)不同的是,這里不需要括號將數(shù)組括起來。
如果給變量分配的值是undefined,那么就會使用默認(rèn)值:
const?[x?=?1]?=?[undefined];
console.log(x);????//?1
這里的默認(rèn)值并不一定是一個固定值,它可以是一個計算屬性:
function?foo()?{
????return?1;
}
let?obj1?=?{x:?2};
let?obj2?=?{x:?undefined};
let?{x=foo()}?=?obj1;
console.log(x);?????//?2
let?{x=foo()}?=?obj2;
console.log(x);?????//?1
如果我們想將數(shù)組中的一些元素分配給變量,而將數(shù)組中的其余項分配給特定的變量就可以這樣做:
let?[greeting,...intro]?=?["Hello",?"I"?,?"am",?"CUGGZ"];
console.log(greeting);??//?"Hello"
console.log(intro);?????//?["I",?"am",?"CUGGZ"]
三、嵌套解構(gòu)
上面我們說的解構(gòu)的只是普通的數(shù)組和對象。實際上,解構(gòu)賦值可以用于嵌套數(shù)組和嵌套對象。比如,文章最開始的例子中,就是解構(gòu)的嵌套對象:
const?student?=?{
????name:?'ZhangSan',
????age:?18,
????scores:?{
????????math:?19,
????????english:?85,
????????chinese:?100
????}
};
const?{?name,?scores:?{math,?english,?chinese}?}?=?student;?
再來看一個嵌套數(shù)組解構(gòu)的例子:
let?numbers?=?[1,?[2,?3,?4],?5];
let?[a,?[b,?c,?d],?e]?=?numbers;
console.log(a,?b,?c,?d,?e);?//?1?2?3?4?5
四、使用技巧
1. 函數(shù)解構(gòu)
(1)解構(gòu)函數(shù)參數(shù)
可以對函數(shù)參數(shù)使用解構(gòu)賦值:
function?foo([a,?b])?{
????console.log(a?+?b);
}
foo([1,?2]);???????//?3
function?bar({x,?y})?{
????console.log(x,?y);
}
foo({x:?1,?y:?2});?//?1?2
可以對函數(shù)返回值使用解構(gòu)賦值:
function?getStudentInfo()?{
????return?{
????????name:?'ZhangSan',
????????age:?18,
????????scores:?{
????????????math:?19,
????????????english:?85,
????????????chinese:?100
????????}
????};
}
const?{?name,?scores:?{math,?english,?chinese}?}?=?getStudentInfo();
console.log(name,?math,?english,?chinese);
2. 循環(huán)中的解構(gòu)
當(dāng)我們需要循環(huán)中的對象鍵值時,也可以使用對象解構(gòu):
const?students?=?[
????{
????????'name':?'ZhangSan',
????????'grade':?80
????},
????{
????????'name':?'LiSi',
????????'grade':?75
????},
????{
????????'name':?'WangWu',
????????'grade':?95
????}
];
for(let?{name,?grade}?of?students){
????console.log(name,?grade);
}
3. 動態(tài)屬性解構(gòu)
很多時候我們不知道對象屬性的key,只有運行時才知道。比如有一個方法getStudentInfo,它以一個key為參數(shù),并返回相應(yīng)的屬性值:
getStudentInfo('name');?
getStudentInfo('age');?
這里傳遞給getStudentInfo方法的參數(shù)是動態(tài)的,因此可以這樣寫:
const?getStudentInfo?=?key?=>?{
??const?{[key]:?value}?=?student;
??return?value;
}
需要注意,包裹key的方括號不能少,否則會出現(xiàn)undefined值。
4. 交換變量
數(shù)組結(jié)構(gòu)一個很實用的功能就是實現(xiàn)交換局部變量。通常,我們會借助臨時變量來實現(xiàn)變量的交換:
let?width?=?300;
let?height?=?400;
let?temp?=?width;
width?=?height;
height?=?temp;
console.log(width,?height)
如果使用數(shù)組的解構(gòu)賦值,就會變得很簡單:
let?width?=?300;
let?height?=?400;
[width,?height]?=?[height,?width];
console.log(width,?height)
5. 數(shù)組拷貝
可以使用解構(gòu)賦值和rest運算符來實現(xiàn)數(shù)組的拷貝:
const?rgb?=?[200,?255,?100];
const?[...newRgb]?=?rgb;
//?等同于?const?newRgb?=?[...rgb]
console.log(newRgb)
結(jié)語
「關(guān)注公眾號IQ前端,一個專注于CSS/JS開發(fā)技巧的前端公眾號,更多前端小干貨等著你喔」
