用一個(gè)經(jīng)常遇到的問題來說明這一賦值的好處之一漏策,對兩個(gè)變量的值進(jìn)行替換膀估,通常我們得另外聲明一個(gè)變量來作為兩個(gè)變量交換的媒介舀寓,而現(xiàn)在如下代碼就可以解決:
{
let a=1;
let b=2;
[a,b]=[b,a];
console.log(a,b); //2,1
}
解構(gòu)賦值上述的用法是對數(shù)組的解構(gòu)賦值,總的來說結(jié)構(gòu)賦值大致可以分為數(shù)組解構(gòu)賦值怒允,對象解構(gòu)賦值,字符解構(gòu)賦值识虚,數(shù)值和布爾解構(gòu)賦值肢扯,函數(shù)參數(shù)解構(gòu)賦值妒茬。
無論何種解構(gòu)賦值担锤,解構(gòu)賦值表達(dá)式的左邊部分,即解構(gòu)的目標(biāo)乍钻,而右邊的值肛循,即左邊解構(gòu)的源,都遵循一個(gè)左右互相匹配的規(guī)則银择,只要等號兩邊的模式相同多糠,左邊的變量就會(huì)被賦予對應(yīng)的值。
數(shù)組解構(gòu)賦值
上述的代碼就是數(shù)組解構(gòu)賦值的基本用法浩考。以下是數(shù)組解構(gòu)賦值的其它使用方式
//嵌套
{
let [a, [[b], c]] = [1, [[2], 3]];
console.log(a,b,c); //1,2,3
}
//可忽略
{
let [a, , b] = [1, 2, 3];
console.log(a,b);
}
//剩余運(yùn)算符
{
let a,b,rest;
[a,b,...rest] = [1,2,3,4,5,6];
console.log(a,b,rest); //1,2,[4,5,6]
}
//不完全解構(gòu)
{
let [a,b] = [1,2,3];
}
上述的變量全都可以成功賦值夹孔,也就是成功解構(gòu),但也有無法解構(gòu)成功的析孽,比如:
let [a] = [];
let [b, d,...c] = [1];
console.log(a); //undefined
console.log(b,d,c); //1,undefined,[]
當(dāng)解構(gòu)目標(biāo)在解構(gòu)的源對應(yīng)位置找不到值,則無法成功解構(gòu),變量的值就會(huì)變成undefined
,...剩余運(yùn)算符的變量為[]
.
在實(shí)際開發(fā)場景中返回的值可能有多種情況,可能你想要的值在某個(gè)位置確實(shí)沒有,那么還可以使用默認(rèn)值搭伤。
let [a,b = 1] = [1];
console.log(a,b); //1,1
let [c = 1,d = 2] = [undefined,null];
console.log(c,d); //1,null
ES6 內(nèi)部使用嚴(yán)格相等運(yùn)算符(===),判斷一個(gè)位置是否有值袜瞬。只有當(dāng)一個(gè)數(shù)組成員嚴(yán)格等于undefined
怜俐,默認(rèn)值才會(huì)生效
默認(rèn)值可以引用解構(gòu)賦值的其他變量,但該變量必須已經(jīng)聲明邓尤。
let [a = 1, b = a] = []; // a=1; b=1
let [a = 1, b = a] = [2]; // a=2; b=2
let [a = 1, b = a] = [1, 2]; // a=1; b=2
let [a = b, b = 1] = []; // ReferenceError: b is not defined
如果解構(gòu)的源不是數(shù)組拍鲤,就會(huì)報(bào)錯(cuò)
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
對象解構(gòu)賦值
對象解構(gòu)賦值同樣遵循左右互相匹配的規(guī)則,類似數(shù)組一樣有嵌套汞扎,默認(rèn)值等季稳,但要注意的是變量名稱需要和對象中的屬性值要對應(yīng),因?yàn)閿?shù)組的位置相對應(yīng)來說是有序的澈魄,而對象中是無序的景鼠,只能通過屬性來作為位置查找。如果要使用其它的變量名稱一忱,可以使用:
重新指定變量名稱莲蜘,注意此時(shí)引用地址已被新變量接收,:
左邊的變量就沒有地址了,再訪問的話是空的帘营,是真的輸出為空的字符票渠,在下面示例代碼中有對應(yīng)的寫法:
//基本
{
let {a,b} = {a:1,b:2}
console.log(a,b);
let {name:newName} = {name:'tony'}
console.log(name)//''
console.log(newName)//tony
}
//默認(rèn)值
{
let {x = 3} = {};
let {a,b = 2}={a:1};
}
//嵌套
{
const obj = {
name:{
chinese_name:{
first_name:'Chen',
last_name:'chuhai'
},
english_name:{
first_name:'Chen',
last_name:'tony'
}
}
};
let {name,name:{chinese_name},name:{chinese_name:{last_name:my_name}}} = obj;
console.log(name);//{chinese_name: {...},english_name: {...}}
console.log(chinese_name);//{first_name: "Chen",last_name: "chuhai"}
console.log(my_name)//chuhai
}
和數(shù)組一樣,對象解構(gòu)也有嵌套芬迄,只是這個(gè)嵌套容易讓人犯暈聘萨,別怕,回顧著之前講的死姚,一層層剝析濒持。
先看解構(gòu)賦值的左邊,前面說了叫做解構(gòu)的目標(biāo)尖坤,第一個(gè)為name變量,這個(gè)很簡單了,這個(gè)就對應(yīng)著右邊解構(gòu)源叫做name的屬性值蚀腿,然后是第二個(gè)解構(gòu)目標(biāo),根據(jù)左右匹配的規(guī)則扫外,可以得出chinese_name就是右邊解構(gòu)源name屬性值對象中chinese_name的屬性值莉钙,最后第三個(gè),last_name就是對應(yīng)結(jié)構(gòu)源上"chuhai"這個(gè)值了筛谚,只是用:
重新指定了變量的名稱為my_name磁玉。
結(jié)構(gòu)目標(biāo)最后只有一個(gè),即得出最后的變量只有一個(gè)驾讲,第二次和第三次過程中分別出現(xiàn)的name和chinese_name蚊伞,只是得到解構(gòu)目標(biāo)過程中為了和解構(gòu)源相匹配而出現(xiàn)的,這樣說應(yīng)該就能解決大部分人對在解構(gòu)目標(biāo)出現(xiàn)的多個(gè)變量的迷惑了(可能只是我剛一接觸時(shí)有這種迷惑)吮铭,那些不是最終的變量时迫,而是為了匹配解構(gòu)源對應(yīng)位置的
解構(gòu)賦值也并不是一定需要聲明變量來賦值的,還可以通過下面的方式進(jìn)行賦值
let obj = {};
let arr = [];
({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });
obj // {prop:123}
arr // [true]
代碼很容易看明白沐兵,拋出一個(gè)注意點(diǎn)别垮,解構(gòu)賦值的表達(dá)式用了一個(gè)括號,為什么呢扎谎?
因?yàn)椴荒敲磳憰?huì)報(bào)錯(cuò)碳想。解構(gòu)賦值用的變量在之前有聲明過,而{}
恰好會(huì)被作為代碼塊理解,這樣上下文出現(xiàn)兩個(gè)相同名稱的變量解析時(shí)就會(huì)報(bào)錯(cuò)毁靶,放在一個(gè)圓括號里面胧奔,就可以正確執(zhí)行。詳細(xì)原因請大家看大神阮一峰e(cuò)s6入門--圓括號問題
對象解構(gòu)賦值和數(shù)組差不多预吆,有沒有獨(dú)特一點(diǎn)的龙填?
有的,對象的解構(gòu)賦值還可以拿到繼承的屬性拐叉,然后數(shù)組是特殊的對象岩遗,其實(shí)也能用對象解構(gòu)的方式來解構(gòu)數(shù)組。上代碼
//繼承
const obj1 = {};
const obj2 = { foo: 'bar' };
Object.setPrototypeOf(obj1, obj2);
const { foo } = obj1;// "bar"
//數(shù)組解構(gòu)
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr;
first // 1
last // 3
字符串的解構(gòu)賦值
后面的幾種解構(gòu)賦值基本上也是從對象解構(gòu)或者數(shù)組解構(gòu)延伸出來的凤瘦,字符串可以看成一個(gè)被分割為數(shù)組的對象宿礁,所以,可以這么用
{
//作為數(shù)組
let [a,b,c,d] = 'tony';
console.log(a,b,c,d);//t o n y
//作為對象解構(gòu)還能這么用
let {length} = 'tony';
console.log(length);//4
}
數(shù)值和布爾解構(gòu)賦值
解構(gòu)賦值按照左右匹配規(guī)則來說蔬芥,只要解構(gòu)的源有數(shù)值梆靖,有結(jié)構(gòu)控汉,那么都可以進(jìn)行解構(gòu),關(guān)鍵是看以什么解構(gòu)規(guī)則進(jìn)行解構(gòu)返吻,除去上面的數(shù)組對象字符串姑子,其它的只要能轉(zhuǎn)成對象,有結(jié)構(gòu)测僵,有數(shù)值街佑,就可以進(jìn)行解構(gòu),像undefined
和null
沒值沒結(jié)構(gòu)的恨课,就無法進(jìn)行解構(gòu)了舆乔,而布爾和數(shù)值可以岳服。
{
//轉(zhuǎn)為對象后繼承了字符對象的toString方法
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
}
函數(shù)參數(shù)解構(gòu)賦值
這部分函數(shù)解構(gòu)賦值并不是簡單的這樣
{
function f(){
return [1,2]
}
let a,b;
[a,b]=f();
console.log(a,b);
}
這樣實(shí)際是拿函數(shù)的執(zhí)行結(jié)果來進(jìn)行解構(gòu)賦值太小兒科剂公,我也曾想過為什么不能是{} = f
這樣的解構(gòu)賦值,方法里面雖然有結(jié)構(gòu)有內(nèi)容吊宋,但是纲辽,誰能告訴怎么個(gè)一一對應(yīng)法,這不可能璃搜,所以拖吼,只能拿方法的傳參講講了。
{
function add([a, b]){
return a + b;
}
console.log(add([1, 2])) // 3
console.log([[1, 2], [3, 4]].map(([a, b]) => a + b)) //[3,7];
}
在傳參的過程中進(jìn)行解構(gòu)賦值这吻,原理和前面講的解構(gòu)賦值是一樣的吊档。
至此結(jié)構(gòu)賦值的類型都說完了,回到最初說明這一運(yùn)算的用途唾糯,除了交換變量怠硼,還有其它的用途,在此一一列舉:
至此結(jié)構(gòu)賦值的類型都說完了移怯,回到最初說明這一運(yùn)算的用途香璃,除了交換變量,還有其它的用途舟误,在此一一列舉:
- 交換變量
- 處理函數(shù)返回值(見上述函數(shù)參數(shù)解構(gòu)賦值的第一段代碼)
- 處理函數(shù)傳參(還是見上述函數(shù)參數(shù)解構(gòu)賦值的代碼)
- 處理JSON數(shù)據(jù)
- 函數(shù)參數(shù)的默認(rèn)值
- 遍歷 Map 結(jié)構(gòu)
- 引入模塊的指定方法
import { loginHtml, loginResultPage, userWxBinding, consolidatedAccountContent} from '../../html/login';
以上為解構(gòu)賦值的筆記內(nèi)容葡秒,如有補(bǔ)充和需探討的,歡迎留言評論~