解構(gòu)賦值的意思是指:按照一定的模式從數(shù)組和對象中提取值,將提取的值對變量進(jìn)行賦值。
數(shù)組的解構(gòu)模式:
1:按照等號(hào)兩側(cè)的數(shù)組對應(yīng)的位置進(jìn)行取值賦值,
1.1:如果等號(hào)兩側(cè)的數(shù)組結(jié)構(gòu)和嵌套結(jié)構(gòu)相同,則可以成功解構(gòu)
1.2:如果等號(hào)兩個(gè)的數(shù)組解構(gòu)或嵌套解構(gòu)不同,則解構(gòu)不成功,解構(gòu)不成功則對應(yīng)位置的變量就賦值為undefined,數(shù)組(左).length > 數(shù)組(右).length
1.3:如果等號(hào)左側(cè)的模式只匹配到一部分的等號(hào)右側(cè)的數(shù)組,則可以成功解構(gòu),數(shù)組(左).length < 數(shù)組(右).length
1.4:如果右側(cè)不是數(shù)組,將會(huì)報(bào)錯(cuò)
1.5:set等具有Iterator接口的結(jié)構(gòu)都可以進(jìn)行解構(gòu)
2:解構(gòu)的同時(shí)可以賦值默認(rèn)值
let [foo = true] = []//foo = true
默認(rèn)值生效規(guī)則:
2.1:使用嚴(yán)格相等運(yùn)算符(===),判斷一個(gè)位置是否有值,只有當(dāng)?shù)忍?hào)右側(cè)數(shù)組的一個(gè)成員嚴(yán)格等于undefined,默認(rèn)值才會(huì)生效。如果一個(gè)數(shù)組成員是null,默認(rèn)值不會(huì)生效,因?yàn)閚ull 不嚴(yán)格等于undefined。
let [foo = 1] = [null]//foo = null
2.2:如果默認(rèn)值是一個(gè)表達(dá)式,那么這個(gè)表達(dá)式是惰性求值,即只有在用到的時(shí)候,才會(huì)求值
function f(){
console.log('111')
}
let [x=f()] = [1]//x = 1
let [x=f()]=[]//x=f()
2.3:默認(rèn)值可以引用解構(gòu)賦值的其他變量,但該變量必須已經(jīng)聲明,否則會(huì)報(bào)錯(cuò)
let [x=1,y=x] = [];//x=1,y=2
let [x=y,y=1] = [];//ReferenceError:y is not defined
對象的解構(gòu)賦值
1.1:對象的解構(gòu)模式不同于數(shù)組,數(shù)組按照元素次序,對象沒有次序,但變量必須與對象屬性同名,才能取到正確的值
1.2:當(dāng)代碼中使用的變量名和對象解構(gòu)的屬性名不同時(shí),可以進(jìn)行轉(zhuǎn)義:
let {foo:baz} = {foo:'aaa',bar:'bbb'};//baz = 'aaa';baz是自己定義的變量名,foo是對象的屬性名,此處是匹配的模式,這樣就可以在代碼中還使用變量baz獲取對象中foo中的值,真正賦值的是變量baz,而模式foo并沒有被賦值
1.3:同數(shù)組一樣,解構(gòu)也可以用于嵌套結(jié)構(gòu)的對象;
對象嵌套結(jié)構(gòu)的解構(gòu)需要注意:
let obj = {
p:[
'Hello',
{y:'World'}
]
};
let {p:[x,{y}]} = obj//此時(shí)p是模式,不會(huì)真正被賦值,被賦值的只有x,y
let {p,p:[x,{y}]} = obj//這種才能解構(gòu)出p
1.4:解構(gòu)賦值時(shí)子對象所在的父屬性不存在,將會(huì)報(bào)錯(cuò),相當(dāng)于對undefined取.xxx,當(dāng)然會(huì)報(bào)錯(cuò)
1.5:對象解構(gòu)賦值可以取到繼承的屬性
2:解構(gòu)時(shí)賦值默認(rèn)值
2.1:默認(rèn)值生效的條件時(shí)對象屬性嚴(yán)格等于undefined
2.2:已經(jīng)聲明的變量再進(jìn)行解構(gòu)會(huì)報(bào)錯(cuò);js引擎會(huì)將{}理解為代碼塊,從而發(fā)生語法錯(cuò)誤,只有不將大括號(hào)寫在行首,避免js將其解釋為代碼塊,才能解決問題。
let x;
({x} = {x:1})
2.3:數(shù)組也可以解構(gòu)成對象屬性
let arr = [1,2,3]
let {0:first,[arr.length-1]:last} = arr//此時(shí)first,last分別被賦值到arr中的1,3
3:字符串的解構(gòu)賦值
字符串被轉(zhuǎn)換成一個(gè)類似數(shù)組的對象。
3.1:解構(gòu)字符串內(nèi)容
let [a,b,c,d,e] = 'Hello'//a='H',b='e',c='l',d='l',e='o'
3.2:解構(gòu)字符串長度
let {length :len} = 'hello'//len=5
4:數(shù)值和布爾值的解構(gòu)賦值
將數(shù)值和布爾值先轉(zhuǎn)為對象
模式:只要等號(hào)右側(cè)的值不是對象或數(shù)組,就先將其轉(zhuǎn)換為對象,由于undefined和null無法轉(zhuǎn)為對象,所以對它們進(jìn)行解構(gòu)賦值都會(huì)報(bào)錯(cuò)。
5:函數(shù)的參數(shù)進(jìn)行解構(gòu)賦值
*參數(shù)賦值分給‘函數(shù)參數(shù)’賦默認(rèn)值 和 給給‘解構(gòu)參數(shù)’賦默認(rèn)值
5.1:給解構(gòu)參數(shù)賦默認(rèn)值:
function move({x=0,y=0}={}){//函數(shù)的參數(shù)是一個(gè)對象,對象解構(gòu)的參數(shù)x,y,給解構(gòu)的參數(shù)x,y賦值默認(rèn)值0
return [x,y]
}
給函數(shù)參數(shù)賦值默認(rèn)值
function move({x,y} = {x:0,y:0}){//賦值一個(gè)默認(rèn)的參數(shù):{x:0,y:0}當(dāng)函數(shù)入?yún)榭諘r(shí),即為undefined時(shí),才會(huì)將默認(rèn)參數(shù)解構(gòu)賦值給x,y
return [x,y]
}
6:解構(gòu)賦值的用途:
合理使用解構(gòu)賦值可以使代碼簡潔清晰
6.1:交換變量的值
let x=1;
let y=2;
[x,y]=[y,x]//x=2,y=1
6.2:從函數(shù)返回多個(gè)值
原本函數(shù)只能返回一個(gè)值
現(xiàn)在函數(shù)可以返回一個(gè)數(shù)組或是對象,然后通過解構(gòu)賦值取出更多的值來
6.3:函數(shù)參數(shù)的定義
可以通過解構(gòu),直接定義函數(shù)體中使用的參數(shù)
6.4:提取JSON數(shù)據(jù)
解構(gòu)賦值對提取JSON對象中的數(shù)據(jù),尤其有用
6.5:函數(shù)參數(shù)的默認(rèn)值***
給函數(shù)參數(shù)賦值默認(rèn)值,可以減少寫保底參數(shù)
let foo = config.foo || 'xxx'//不用再像這樣寫保底參數(shù)
function test(foo='xxx'){
conosle.log(foo)
}
test('kkk')//'kkk'
test()//'xxx',輸出保底'xxx'
6.6:遍歷Map結(jié)構(gòu)
使用for...of循環(huán)遍歷,通過解構(gòu)獲取鍵名和鍵值非常方便
6.7:輸入模塊的指定方法
根據(jù)需要使用加載的模塊,指定輸入哪些方法
const {SourceMapConsumer ,SourceNode} = require('source-map')