基本語法
let a = 1;
let b = 2;
let c = 3;
可以寫成:
let [a, b, c] = [1, 2, 3];
只要等號兩邊的模式相同,左邊變量就會被賦予對應的值。
let [foo, [[bar], baz]] = [1, [[2], 3]];
foo // 1
bar // 2
baz // 3
let [ , , third] = ['foo', 'bar', 'baz'];
third // 'baz'
let [x, , y] = [1, 2, 3]
x // 1
y // 3
let [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // 'a'
y // undefined
z // []
如果解構不成功,變量的值就等于 undefined
let [foo] = [];
let [bar, foo] = [1];
以上兩種情況都屬于解構不成功,foo
的值就等于 undefined
對于Set解構,也可是使用數組的解構賦值
let [x, y, z] = new Set(['a', 'b', 'c']);
x // 'a'
事實上,只要某種數據結構具有 Iterator 接口,都可以采用數組形式的結構賦值。
默認值
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x = 'a', y = 'b'
let [x, y = 'b'] = ['a', undefined]; // x = 'a', y = 'b'
let [x = 1] = [null];
x // null
ES6 內部使用嚴格相等運算符(===
),判斷是否有值。如果一個數組成員不嚴格等于 undefined
,默認值是不會生效的。
如果默認值是一個表達式,那么這個表達式是惰性求值的,即只有在用到的時候,才會求值
function f() {
console.log('aaa');
}
let [x = f()] = [1];
上面代碼中,因為 x
能取到值,所以函數 f
根本不會去執行。
默認值可以引用結構賦值的其它變量,但該變量 必須已經聲明。
let [x = y, y = 1] = []; //ReferenceError
對象的結構賦值
let { foo, bar } = { foo: 'aaa', bar: 'bbb' }
foo // 'aaa'
bar // 'bbb'
如果變量名與屬性名不一致,必須寫成下面這樣,
var { foo: baz } = { foo: 'aaa', bar: 'bbb' }
baz // 'aaa'
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
解構也可以用于嵌套解構的對象
let obj = {
p: [
'hello',
{ y: 'world' }
]
}
let { p: [x, { y }] } = obj;
x // 'hello'
y // 'world'
注意,這時 p
是模式,不是變量,因此不會被賦值。如果 p
也要作為變量賦值,可以寫成
let {p, p: [x, { y }]} = obj;
x // 'hello'
y // 'world'
p // ['hello', {y: 'world'}]
字符串的結構賦值
const [a, b, c, d, e] = 'hello';
a // 'h'
b // 'e'
c // 'l'
d // 'l'
e // 'o'
類似數組的對象都有一個 length
屬性,因此還可以對這個屬性結構賦值。
let {length: len} = 'hello';
len // 5
數值和布爾值的結構賦值
如果等號右邊是數值和布爾值,則會先轉為對象。
let { toString: s } = 123;
s === Number.prototype.toString // true
數值的包裝對象有toString屬性,因此變量 s
能取到值。
結構賦值的規則是,只要等號右邊的值不是對象或數組,就先將其轉為對象。由于 undefined
和 null
無法轉為對象,所以對它們進行結構賦值,都會報錯。
let { prop: x } = undefined; // TypeError
let { prop: y} = null; // TypeError
函數參數的解構賦值
function add([x, y]) {
return x + y;
}
add([1, 2]); // 3
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [3, 7]
圓括號問題
對于編譯器來說,一個式子到底是模式,還是表達式,沒有辦法從一開始就知道,必須解析到(或即系不到)等號才能知道。
所以最好不要在模式中放置圓括號。
不能使用圓括號的情況
- 變量聲明語句
let [(a)] = [1];
- 函數參數
function f([(z)]) { return z; }
- 賦值語句的模式
({p: a}) = { p: 42 }
以上代碼全部報錯。
可以使用圓括號的情況
[(b)] = [3]; // 正確
({ p: (d) } = {}); //正確
[(parseInt.prop)] = [3]; //正確
用途
- 交換變量的值
let x = 1;
let y = 2;
[x, y] = [y, x];
- 從函數返回多個值
function example() {
return [1, 2, 3];
}
let [a, b, c] = example();
- 函數參數的定義
- 提取JSON的數據
- 函數參數的默認值
function example({name = 'abc', age = 12}) {
}
- 遍歷Map解構
- 輸入模塊的指定方法
const { View, Span } = require("react-native");