相較於常規的賦值方式,解構賦值最主要的是'解構'兩個字,在賦值的過程中要清晰的知道等號右邊的結構.
先簡單地看一下原來的賦值方式.
var a=[1,2]
分析一下這句代碼的幾個點:
(1)變量申明和賦值
var a; a=[1,2] //你可以理解這兩個操作是分開的,雖然是一句代碼.聲明變量都會出現變量名的提升(也就是是聲明變量的這句代碼會被提升到生效作用域的最前面),區別在於'var'聲明的是全局變量,而'let const'聲明的是塊級作用域變量.
(2)結構對應
var a; a=[1,2]; a=12; a={name:'小明',age:18}
解構賦值
結合上面的的例子,假如我現在只想要{name:'小明',age:18}這個對象中的'name'屬性,原來的做法
var a={name:'小明',age:18} console.log(a.name)
就需要通過點語法去獲取,實際開發中,我們的數據很多時候是嵌套很多層的,所以就會出現類似'a.b.c.d'這類代碼.看着讓人頭暈,而解構賦值就是解決這個問題的方案之一
基本用法
(1)聲明和賦值
數組
let [a] = [1];
[變量名]:變量名可隨意
對象
let {name} = {name:'小明',age:18}
{變量名}:變量名必須是對象中的屬性名
(2)結構對應(重難點)
數組(要位不要名)
對象(要名不要位)
完全解構
數組:
a:按順序
let [a, b, c] = [1, 2, 3]; console.log(a,b,c) //1,2,3
這樣賦值的語義是我知道右邊是一個有三個元素的數字,所以我聲明了一個數組,三個元素分別是a,b,c和右邊的三個元素對應.所以a=1,b=2,c=3
b:打亂順序
let [a, c, b] = [1, 2, 3]; console.log(a,b,c) //1,3,2
因為三個變量的位置變了,所以其對應的元素(值)也就變量
對象:
a:按順序
let {name,age} ={name:'小明',age:18} console.log(name,age) //小明,18
b:打亂順序
let {age,name} ={name:'小明',age:18} console.log(name,age) //小明,18
雖然變量的聲明前后順序變了,但是對象中的值沒變,它最終還是根據屬性名去找值,所以結果沒變
c:不存在的屬性名
let {name,sex} ={name:'小明',age:18} console.log(name,sex) //小明,undefined
嵌套解構
數組:
let [a, [b,c], d] = [1, [2, 3], 4]; console.log(a,b,c,d) //1,2,3,4 //反正結構和位置一一對應就行了.
對象
const obj={ man:{ student:{ name:'小明', age:18 } } } let {man:{student}} = obj //obj里面有個man,然后里面有個student,注意這一行代碼里變量就只有一個student,並沒有man console.log(man,student) // undefined,{name:'小明',age:18} let {man:{student:{name}}} = obj //同理,逐層拿到最后的name值,而且也只有name這一個屬性 console.log(name) //小明 //如何同時拿到嵌套的每層的數據 let {man,man:{studengt},man:{student:{name}}} = obj console.log(man,student,name) //{student:{name:'小明',age:18}},{name:'小明',age:18},18
不完全解構
let [a, b] = [1, 2, 3]; console.log(a,b,c) //1,2 //這里變量只有兩個,但是數組中元素有三個.這里還是根據位置對應原理就行.a表示數組中的第一個元素,b表示第2個.而第三個元素我不要. let [a, [b], d] = [1, [2, 3], 4]; console.log(a,b,d) //1,2,4 //嵌套解構同樣也可以不完全解構,根據實際需要,需要哪個就解構賦值哪個 let [, , c] = [1, 2, 3]; console.log(c) //3 //注意這里是完全解構,只不過前兩個元素我雖然解構了,但是我不要.因為位置對應的關系,所以必須有兩個占位的,才能拿到第三個. //放在這里是為了方便理解為啥前面兩個明明不要還得寫兩個','
超量賦值(自己瞎編的詞)
let [a,b,c,d] = [1,2,3] onsole.log(a,b,c,d) //1,2,3,undefined //因為前三個元素都能對應找到,而第四個找不到,但是已經聲明了,沒有值. //對象同理,如果出現了對象中沒有的屬性就會得到undefined
(3)重命名(先取再重命名)
數組:我們上面說過,數組解構的時候只要注意位置對應就行了,名稱啥的無所謂,你喜歡叫什么變量名就什么變量名
對象:對象解構的時候是要屬性名對應才能取到值.但是沒有說取到值之后不能重命名啊.一定要取到值之后在命名
let {name:myName,age} ={name:'小明',age:18} //這里name:myName的意思是:取到name屬性值,冒號后面的變量名沒有花括號,意思是把我取到的值交給冒號后面的變量名,即'myName'.相當於把name變量重命名為myName //而student:{name},同樣是'屬性名:'意思一樣,取里面對應的屬性,冒號后面還有花括號,所以再解構,取student里面的name屬性 console.log(name,myName,age) //undefined,小明,18
(4)默認值(先取再默認)
數組
let [a=0, b=0,c=10] = [1, 2]; console.log(a,b,c) //1,2,10 //這里a,b,c在左邊都先給了個默認值,但是這里是超量解構,a和b都成功取到值,但是c沒取到,所以最終是默認值10,如果沒有默認值就是undefined
對象
let {name:sex='男'} ={name:'小明',age:18} console.log(sex) //小明 let {name:{sex='男'}} = {name:'小明',age:18} console.log(sex) //男 //這里剛好通過這兩個例子區分一下重命名和嵌套
(5)字符串解構
字符串的解構可以理解為一維數組的解構,這在處理字符串的時候特別方便.
let [a,b,c] ='123' console.log(a,b,c,typeof c) //1,2,3,string 解構出來的是字符類型的數據
長度
let {length:s} ='123' console.log(s,typeof s) //3,number //同理,數組也有長度 let {length:s} = [1,2,3] console,log(s,typeof s) //3,number
(6)函數參數自動解構
function look([x,y]){ console.log(x,y) } look([1,2]) //1,2
參數默認值陷阱單獨再寫一篇
(7)先聲明再賦值(少用)
數組
let a; let b; [a,b]=[1,2] console.log(a,b) //1,2
對象
let x; {x}={x:1,y:1} //報錯 主要還是大括號的原因,js在行首遇到{}會把它當做代碼塊執行,所以會報錯. ({x}={x:1,y:1}) //這樣可以解決問題,但是盡量別引入(),問題會變得復雜
到這里為止,解構賦值的日常使用沒問題了,它帶來了不少方便,但也會產生一些新bug,比如:let {data} =res 的寫法,假如res里面並沒有data屬性,那就會undefined,所以還是得明確等號右邊的解構.