uncategorized

解構賦值(Destructuring Assignment)

解構賦值是 ES6 的新特性,可以將陣列或物件中的資料取出成獨立變數。

陣列解構

陣列解構強調順序,左右對照相對應的元素,右邊陣列的值即可對左邊陣列相對應的元素賦值。

1
2
3
4
5
6
var foo = ['a', 'b', 'c'];

var [one, two, three] = foo;
console.log(one); // "a"
console.log(two); // "b"
console.log(three); // "c"

陣列解構

1
2
3
4
5
6
7
8
9
var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

物件解構

陣列的解構賦值強調順序,而物件的解構賦值強調的則是屬性名稱,屬性名稱必須相互對應才能夠取得到值。 在物件解構賦值中,冒號前是用來對應物件的屬性名稱,冒號後才是真正建立的變數名稱和被賦值的對象。

1
2
3
4
5
6
7
let {aaa, bbb} = {aaa:4, bbb:9}
console.log(aaa) //4
console.log(bbb) //9

let {name} = {name:'Max', age: 28}
console.log(name) //左側的 name 屬性有對應到右側 name 屬性,所以 console name 有值
console.log(age) //左側的 age 屬性沒有對應到右側 age 屬性,所以 age is not undefined

物件的模式匹配不像陣列需要對應索引值,因此在物件的解構賦值中順序不影響結果。

1
2
3
4
5
6
7
let { apple, banana } = { apple: "good", banana: "bad" };
console.log(apple) // "good"
console.log(banana) // "bad"

let { banana , apple } = { apple: "good", banana: "bad" };
console.log(apple) // "good"(即使順序不同,參照相同的索引值,還是不影響結果)
console.log(banana) // "bad"

如果變數與屬性名都沒有對應的名稱則變數的值會是 undefined

1
2
let { orange } = { apple: "good", banana: "bad" };
console.log(orange); // undefined

也可以屬性值來當作變數對應等號後方的屬性值,寫法會是類似這樣:

1
2
3
4
5
6
7
8
let { apple: "feel" } = { apple: "good", banana: "bad" };  
// 這樣會出錯,前面的引號必須拿掉

let { apple: feel } = { apple: "good", banana: "bad" }
//不用加引號

console.log(feel); // "good"
console.log(apple); //報錯

console.log(apple) 會報錯,因為物件(object)的解構賦值的內部機制,是先找到同名屬性,然後再賦給對應的變量。真正被賦值的是後者,而不是前者,在上例中,apple 是匹配的模式,feel 才是變量。真正被賦值的是變量 feel。

1
2
3
4
5
6
7
8
var {a:aa = 10, b:bb = 5} = {a: 3};
console.log(aa) // 3
console.log(a) //a is not defined

let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
console.log(f); // 'hello'
console.log(l); // 'world'
1
2
const { menu: currentMenu } = this.props;
// 這樣的意思是,把 this.props 裡頭的 menu 屬性取出,並另外以 currentMenu 命名之。

不完全解構

即等號左邊的模式,只匹配一部分的等號右邊的數組。這種情況下,解構依然可以成功。下面兩個例子,都屬於不完全解構,但是可以成功。

1
2
3
let [x, y] = [1, 2, 3];
x // 1
y // 2

1
2
3
4
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2, not [2, 3]
d // 4
1
2
3
4
5
var [a,b,c] = [d,e,f]
// 報錯,d, e, f is not defined

var [x,y,z] = [function(){return 3}, {i:'ii',o:'oo'}, [9,9,9]]
// ok

如果等號的右邊不是陣列,解構將不被接受。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 報錯
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

以下部分也會報錯
{u,i,o} = {"","",""}
{u,i,o} = { , , }

但以下可以
[u, i, o] = []
[u, i, o] = [ , , ]
[u, i, o] = [ '', '', '']

解構賦值允許指定默認值。

1
2
3
4
let [foo = true] = [];
console.log(foo) // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
Share