1止邮、數(shù)組的解構(gòu)賦值
基本用法
本質(zhì)上,只要等號兩邊的模式相同奏窑,左邊的變量就會被賦予對應(yīng)的值农尖,...表示將剩下的值賦予此變量,無剩余則賦值為空數(shù)組良哲,解構(gòu)不成功則賦值為undefined盛卡。等號兩邊都要為數(shù)組。
let a = 1;
let b = 2;
let c = 3;
//ES6可以寫成
let [a, b, c] = [1, 2, 3];
//多重?cái)?shù)組的例子
let [a, [[b], c]] = [1, [[2], 3]];
a // 1
b // 2
c // 3
//對應(yīng)位置賦予對應(yīng)的值
let [ , , c] = ["1", "2", "3"];
c // "3"
let [a, , c] = [1, 2, 3];
a // 1
c // 3
//...語法有剩余值時(shí)
let [a, ...z] = [1, 2, 3, 4];
a // 1
z // [2, 3, 4]
//...語法無剩余值時(shí)
let [a, b, ...z] = ['a'];
a // "a"
b // undefined
z // [] 空數(shù)組
默認(rèn)值
解構(gòu)賦值可以使用默認(rèn)值筑凫,當(dāng)且僅當(dāng)變量的值全等于(===)undefined時(shí)滑沧,才會使用默認(rèn)值,即使是等于null時(shí)也不會使用默認(rèn)值巍实。
let [a = 1] = []; a // 1
let [a, b = '2'] = ['1']; // a='1', b='2'
let [a, b = '2'] = ['1', undefined]; // a='1', b='2'
let [x = 1] = [null]; x // null
當(dāng)默認(rèn)值是一個(gè)表達(dá)式的時(shí)候(例如一個(gè)行數(shù)表達(dá)式)滓技,若變量能夠取到值(值不全等于undefined),則表達(dá)式不會執(zhí)行棚潦。
function f() {
console.log('a');
}
let [x = f()] = [1]; //f()不會執(zhí)行令漂,y=1
默認(rèn)值可以引用解構(gòu)賦值中的其他變量,前提是變量已經(jīng)聲明
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // y在x引用的時(shí)候還沒有聲明丸边,所以報(bào)錯(cuò)叠必。
2、對象的解構(gòu)賦值
與數(shù)組的解構(gòu)賦值不同的是妹窖,數(shù)組解構(gòu)是按照元素的次序賦值的纬朝,而對象則不受次序的影響,變量必須與屬性同名骄呼,才能被賦值共苛,沒有同名屬性則賦值為undefined判没。
let { pro1, pro2 } = { pro1: "1", pro2: "2" };
pro1 // "1"
pro2 // "2"
//上述表述是一種縮寫,其本質(zhì)是
let { pro1:pro1, pro2:pro2 } = { pro1: "1", pro2: "2" };
//在等號左邊時(shí)隅茎,:號左邊的pro1和pro2是定義匹配模式澄峰,真正被賦值的是:號右邊的pro1和pro2,當(dāng)匹配模式和屬性名同名時(shí)辟犀,可以使用縮寫
let { proa:prox, prob:proy } = { proa: "1", prob: "2" };
prox //"1"
proy //"2"
對象解構(gòu)中左邊的變量一定是由:組成的一對匹配模式和屬性名俏竞。只有一個(gè)匹配模式時(shí),一定是匹配模式和屬性名相同踪蹬,使用了簡寫。
var obj= {
a: {
b: {
c: 1,
d: 2
}
}
};
var { a: { b: { c }} } = obj;
a // 報(bào)錯(cuò)臣咖,a在:左邊跃捣,是匹配模式,不是屬性名
b // 報(bào)錯(cuò)夺蛇,b在:左邊疚漆,是匹配模式,不是屬性名
c // 1
對象的解構(gòu)賦值同樣支持默認(rèn)值刁赦,規(guī)則與數(shù)組的解構(gòu)相似:
- 當(dāng)且僅當(dāng)變量值全等于(===)undefined時(shí)娶聘,才會取默認(rèn)值。
- 如果解構(gòu)失敗甚脉,變量的值等于undefined丸升。
當(dāng)大括號位于本行的首位時(shí),需要加上小括號牺氨,因?yàn)?{ } 表示一個(gè)代碼塊狡耻,不是一個(gè)單獨(dú)的語句。
let x;
{x} = {x: 1}; // 語法錯(cuò)誤猴凹,左邊是一個(gè)代碼塊夷狰,不是一個(gè)聲明。
({x} = {x: 1}); // 加上小括號郊霎,成為一個(gè)單獨(dú)的語句沼头,語法正確。
當(dāng)變量名與現(xiàn)有對象的屬性名相同時(shí)书劝,可以直接使用對象賦值进倍。
let { log, sin, cos } = Math;
log // Math.log
sin // Math.sin
cos // Math.cos
因?yàn)樵贘avaScript中,數(shù)組是特殊的對象购对,所以可以用數(shù)組進(jìn)行對象屬性的結(jié)構(gòu)背捌。
let arr = [1, 2, 3];
let {0 : a, [arr.length - 1] : b} = arr;
a // 1
b // 3
3、字符串的解構(gòu)賦值
字符串進(jìn)行結(jié)構(gòu)賦值時(shí)洞斯,被轉(zhuǎn)化為了一個(gè)類似數(shù)組的對象毡庆。
const [a, b, c, d, e] = 'hello';
a // 'h'
let {length : len} = 'hello';
len // 5 因?yàn)橛疫?hello'字符串被轉(zhuǎn)化為了一個(gè)類似數(shù)組的對象坑赡,具有l(wèi)ength屬性,所以可以直接賦值給左邊同名的匹配模式么抗。
4毅否、數(shù)值和布爾值的解構(gòu)賦值
解構(gòu)賦值時(shí),如果等號右邊是數(shù)值和布爾值蝇刀,則會先轉(zhuǎn)為對象螟加。
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
解構(gòu)賦值的規(guī)則是,只要右邊不是對象或者數(shù)組吞琐,就將其轉(zhuǎn)化為對象捆探,再進(jìn)行匹配賦值。
因?yàn)閡ndefined和null不能轉(zhuǎn)化為對象站粟,所以單獨(dú)將這兩個(gè)值當(dāng)做右邊的值進(jìn)行匹配賦值時(shí)會報(bào)錯(cuò)黍图。
let { prop: x } = undefined; // 報(bào)錯(cuò)
let { prop: y } = null; // 報(bào)錯(cuò)
5、函數(shù)參數(shù)的解構(gòu)賦值
function add([x, y]){
return x + y;
}
add([1,2]); // 傳輸數(shù)組參數(shù)相當(dāng)于執(zhí)行了 [x,y]=[1,2];x和y被分別賦值為1和2
函數(shù)參數(shù)的解構(gòu)也可以使用默認(rèn)值奴烙,但下面兩種情況不同:
function move({x = 0, y = 0} = {}) {
return [x, y];
}
這種方式表示x和y沒有給定值時(shí)默認(rèn)值為0助被,x和y是分開賦值的,只要參數(shù)中存在沒有傳入的項(xiàng)切诀,就使用其默認(rèn)值揩环。
即只要某一項(xiàng)參數(shù)不存在,就一定會使用其默認(rèn)值幅虑。
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
這種方式指定的是整個(gè)參數(shù)的默認(rèn)值丰滑,而不是單獨(dú)指定x和y,x和y是當(dāng)做一個(gè)整體倒庵。只有當(dāng)完全不傳任何參數(shù)時(shí)吨枉,才會使用默認(rèn)值(傳入空對象也不會使用默認(rèn)值),無論是單獨(dú)傳了x參數(shù)哄芜,還是單獨(dú)傳了y參數(shù)貌亭,未傳的項(xiàng)都不會使用默認(rèn)值。
即只要存在參數(shù)认臊,且參數(shù)不全等于(===)undefined圃庭,就一定不會使用默認(rèn)值。
6失晴、圓括號問題
ES6的規(guī)則是:只要有可能導(dǎo)致解構(gòu)歧義剧腻,就不得使用圓括號。
所以涂屁,在非必要情況下书在,沒有必要添加圓括號(事實(shí)上大部分圓括號都是沒有必要添加的)。
不允許使用圓括號的情況
- 聲明語句中不允許使用圓括號
- 函數(shù)參數(shù)中拆又,匹配模式不允許使用圓括號儒旬,因?yàn)楹瘮?shù)參數(shù)也屬于變量聲明
- 不能將整個(gè)模式或嵌套中的某一整層放在圓括號當(dāng)中栏账。
7、解構(gòu)用途
交換變量的值
let x = 1;
let y = 2;
[x, y] = [y, x]; // 簡潔易懂的交換
從函數(shù)返回多個(gè)值
當(dāng)函數(shù)需要返回多個(gè)值時(shí)栈源,將這些值組成一個(gè)數(shù)組或?qū)ο蟮簿簦祷剡@個(gè)數(shù)組或?qū)ο螅缓笤儆媒鈽?gòu)賦值來取的各項(xiàng)的值甚垦。
// 返回一個(gè)數(shù)組
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
// 返回一個(gè)對象
function example() {
return {
foo: 1,
bar: 2
};
}
let { foo, bar } = example();
函數(shù)參數(shù)的定義(包括函數(shù)參數(shù)使用默認(rèn)值)
// 參數(shù)是一組有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 參數(shù)是一組無次序的值
function f({x=0, y=0, z=0}) { ... }
f({z: 3, y: 2, x: 1});
提取JSON數(shù)據(jù)
let jsonData = {
id: 42,
status: "OK",
data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]