ES6+ 解構(gòu)賦值
1. 前言
本節(jié)我們會(huì)學(xué)習(xí)到 ES6 中的解構(gòu)賦值語(yǔ)法,它是 JavaScript 中的一種表達(dá)式。在本節(jié)中你可以了解以下內(nèi)容:
- 什么是解構(gòu)賦值
- 數(shù)組的解構(gòu)賦值
- 對(duì)象的解構(gòu)賦值
- 如何解構(gòu)嵌套對(duì)象和數(shù)組
解構(gòu)賦值就是分解一個(gè)數(shù)據(jù)的結(jié)構(gòu),并從這數(shù)據(jù)解構(gòu)中提取數(shù)據(jù)的過(guò)程,它可以從數(shù)組中取出值賦給變量或是將對(duì)象中的屬性提取出來(lái)賦給另一個(gè)對(duì)象的屬性。解構(gòu)的目的是為了簡(jiǎn)化提取數(shù)據(jù)的過(guò)程,增強(qiáng)代碼的可讀性。 把變量放在 []
或者 {}
中來(lái)獲取目標(biāo)對(duì)象上的對(duì)應(yīng)的值。
2. 數(shù)組的解構(gòu)賦值
2.1 基本用法
數(shù)組的解構(gòu)賦值是,通過(guò)新建一個(gè)數(shù)組,數(shù)組內(nèi)的變量和目標(biāo)數(shù)組是一一對(duì)應(yīng)的,按照索引的方式去獲取值,然后賦值給指定索引上的變量。在 ES6 之前,想獲取數(shù)組中的值,需要通過(guò) Array[index]
的方式來(lái)獲取值,這種方式的好處在于可以獲取數(shù)組上指定索引的值,如果我們想把數(shù)組的每一項(xiàng)的值都取出來(lái),賦給變量,這樣的寫(xiě)法就顯得很笨拙:
var arr = [10, 20];
console.log(arr[0]); // 10
console.log(arr[1]); // 20
上面的取值方式是 ES6 之前的寫(xiě)法,有了 ES6 的解構(gòu)賦值就簡(jiǎn)單了很多,下面看 ES6 解構(gòu)賦值是怎么取數(shù)組的對(duì)應(yīng)值的:
var [a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20
上面的例子中先聲明一個(gè)數(shù)組,分別在數(shù)組的 0 和 1 的索引位置上放置變量 a 和 b,對(duì)應(yīng)著需要獲取數(shù)組的索引位置,這樣就可以從數(shù)組當(dāng)中取到我們想要的值了。
2.2 默認(rèn)值
在解構(gòu)一個(gè)未知的數(shù)組時(shí),需要對(duì)未能取的值的變量賦一個(gè)默認(rèn)值,為了防止從數(shù)組中取出一個(gè)值為 undefined
的對(duì)象,可以在表達(dá)式的左邊的數(shù)組中為任意變量預(yù)設(shè)一個(gè)默認(rèn)的值。
let [a=3, b=9] = [1]; // a=1 b=9
let [a, b = 1] = [10, '']; // a=10, b=''
let [a, b = 1] = [10, undefined]; // a=10, b=1
Tips: 在 ES6 中,判斷一個(gè)數(shù)組中是否有值,使用嚴(yán)格相等運(yùn)算符(===)來(lái)進(jìn)行判斷,只有當(dāng)一個(gè)數(shù)組成員嚴(yán)格等于 undefined,默認(rèn)值才會(huì)生效。所以第三個(gè) b 使用了默認(rèn)值。
let [a = 1] = [null]; // a=null
我們知道 null==undefined
返回的是 true,null===undefined
返回的是 false。所以數(shù)組成員是 null,默認(rèn)值就不會(huì)生效。
2.3 交換變量
在 ES6 之前如果我們想交換兩個(gè)變量的值時(shí),我們需要借助一個(gè)中間的值來(lái)過(guò)渡,下面是要交換 a、b 值的過(guò)程:
var a = 1;
var b = 4;
var m = a;
a = b;
b = m // a=4, b=1
在交換 a、b 值時(shí),需要借助中間的變量來(lái)中轉(zhuǎn),使用 ES6 解構(gòu)賦值就很簡(jiǎn)單:
var a = 1;
var b = 4;
[a, b] = [b, a] // a=4, b=1
2.4 跳過(guò)某項(xiàng)值使用逗號(hào)隔開(kāi)
在解構(gòu)數(shù)組時(shí),可以忽略不需要解構(gòu)的值,可以使用逗號(hào)對(duì)解構(gòu)的數(shù)組進(jìn)行忽略操作,這樣就不需要聲明更多的變量去存值了:
var [a, , , b] = [10, 20, 30, 40];
console.log(a); // 10
console.log(b); // 40
上面的例子中,在 a、b 中間用逗號(hào)隔開(kāi)了兩個(gè)值,這里怎么判斷間隔幾個(gè)值呢,可以看出逗號(hào)之間組成了多少間隔,就是間隔了多少個(gè)值。如果取值很少的情況下可以使用下標(biāo)索引的方式來(lái)獲取值。
2.5 剩余參數(shù)中的使用
通常情況下,需要把剩余的數(shù)組項(xiàng)作為一個(gè)單獨(dú)的數(shù)組,這個(gè)時(shí)候我們可以借助展開(kāi)語(yǔ)法把剩下的數(shù)組中的值,作為一個(gè)單獨(dú)的數(shù)組,如下:
var [a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]
在 rest 的后面不能有 逗號(hào) 不然會(huì)報(bào)錯(cuò),程序會(huì)認(rèn)出你后面還有值。...rest
是剩余參數(shù)的解構(gòu),所以只能放在數(shù)組的最后,在它之后不能再有變量,否則則會(huì)報(bào)錯(cuò)。
3. 對(duì)象的解構(gòu)賦值
3.1 基本用法
對(duì)象的解構(gòu)和數(shù)組基本類(lèi)似,對(duì)象解構(gòu)的變量是在 {}
中定義的。對(duì)象沒(méi)有索引,但對(duì)象有更明確的鍵,通過(guò)鍵可以很方便地去對(duì)象中取值。在 ES6 之前直接使用鍵取值已經(jīng)很方便了:
var obj = { name: 'imooc', age: 7 };
var name = obj.name; // imooc
var age = obj.age; // 7
但是在 ES6 中通過(guò)解構(gòu)的方式,更加簡(jiǎn)潔地對(duì)取值做了簡(jiǎn)化,不需要通過(guò)點(diǎn)操作增加額外的取值操作。
var obj = { name: 'imooc', age: 7 };
var { name, age } = obj; // name: imooc, age: 7
在 {}
直接聲明 name 和 age 用逗號(hào)隔開(kāi)即可得到目標(biāo)對(duì)象上的值,完成聲明賦值操作。
3.2 默認(rèn)值
對(duì)象的默認(rèn)值和數(shù)組的默認(rèn)值一樣,只能通過(guò)嚴(yán)格相等運(yùn)算符(===)來(lái)進(jìn)行判斷,只有當(dāng)一個(gè)對(duì)象的屬性值嚴(yán)格等于 undefined
,默認(rèn)值才會(huì)生效。
var {a = 10, b = 5} = {a: 3}; // a = 3, b = 5
var {a = 10, b = 5} = {a: 3, b: undefined}; // a = 3, b = 5
var {a = 10, b = 5} = {a: 3, b: null}; // a = 3, b = null
所以這里的第二項(xiàng) b 的值是默認(rèn)值,第三項(xiàng)的 null === undefined
的值為 false,所以 b 的值為 null。
3.3 重命名屬性
在對(duì)象解構(gòu)出來(lái)的變量不是我們想要的變量命名,這時(shí)我們需要對(duì)它進(jìn)行重命名。
var {a:x = 8, b:y = 3} = {a: 2};
console.log(x); // 2
console.log(y); // 3
這里把 a 和 b 的變量名重新命名為 x 和 y。
3.4 剩余參數(shù)中的使用
在對(duì)象的解構(gòu)中也可以使用剩余參數(shù),對(duì)對(duì)象中沒(méi)有解構(gòu)的剩余屬性做聚合操作,生成一個(gè)新的對(duì)象。
var {a, c, ...rest} = {a: 1, b: 2, c: 3, d: 4}
console.log(a); // 1
console.log(c); // 3
console.log(rest); // { b: 2, d: 4 }
對(duì)象中的 b、d 沒(méi)有被解構(gòu),通過(guò)剩余參數(shù)語(yǔ)法把沒(méi)有解構(gòu)的對(duì)象屬性聚合到一起形成新的對(duì)象。
4. 解構(gòu)字符串
當(dāng)然字符串也是可以被解構(gòu)的,字符串可以當(dāng)作數(shù)組被解構(gòu)。
const [a, b, c, d, e] = 'imooc';
console.log(a); // "i"
console.log(b); // "m"
console.log(c); // "o"
console.log(d); // "o"
console.log(e); // "c"
字符串可以被看成類(lèi)數(shù)組的東西,類(lèi)似數(shù)組的對(duì)象都有一個(gè) length 屬性,字符串也可以被當(dāng)作對(duì)象來(lái)解構(gòu),但是由于字符串方法只有 length 屬性,所以只能解構(gòu)出 length 的值。
let {length : len} = 'hello';
console.log(len); // 5
5. 解構(gòu)復(fù)雜的數(shù)據(jù)結(jié)構(gòu)
了解了數(shù)組和對(duì)象的解構(gòu),下面我們看下對(duì)于復(fù)雜數(shù)據(jù)解構(gòu)應(yīng)該如何去解構(gòu)呢?看下面的例子:
var data = {
a: 1,
arr: [
{
b: 2,
c: 3
}
]
}
var {
a: newA,
arr: [
{
b: newB
}
]
} = data;
console.log(newA, newB) // 1, 2
上面的例子中 data 的數(shù)據(jù)解構(gòu)還算是比較復(fù)雜的,對(duì)于解構(gòu)這種既有對(duì)象又有數(shù)組的數(shù)據(jù)解構(gòu),我們要先聲明一個(gè)和目標(biāo)對(duì)象有著相同的數(shù)據(jù)嵌套,才能去拆解目標(biāo)對(duì)象。這里解構(gòu)的是 data 中的 a 和 b 的值,而且把 a 和 b 重命名為 newA 和 newB。
6. 小結(jié)
本節(jié)講解了 ES6 解構(gòu)賦值的使用方法,總結(jié)下來(lái)一共有以下幾點(diǎn):
- 解構(gòu)賦值一般針對(duì)對(duì)象和數(shù)組,如果解構(gòu)對(duì)象是
undefined
或是null
都會(huì)報(bào)錯(cuò); - 默認(rèn)值的生效條件是,只有當(dāng)解構(gòu)的對(duì)象的值是嚴(yán)格模式下的
undefined
的情況下,默認(rèn)值才會(huì)生效; - 可以不借助中間變量來(lái)交換兩個(gè)值;
- 在解構(gòu)復(fù)雜的數(shù)據(jù)解構(gòu)時(shí),注意聲明的對(duì)象要和目標(biāo)的對(duì)象有著相同的解構(gòu)形式,才能去解構(gòu)目標(biāo)對(duì)象。