1、數(shù)組的解構賦值
解構:從數(shù)組和對象中提取值,對變量進行賦值
解構賦值的規(guī)則:只要等號右邊的值不是對象或數(shù)組,就先將其轉為對象。由于undefined和null無法轉為對象,所以對它們進行解構賦值,都會報錯。
- 基本用法
“模式匹配”:只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值
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 // []
let [foo] = []; // undefined,解構不成功
let [bar, foo] = [1]; // undefined,解構不成功
不完全解構:
let [x, y] = [1, 2, 3];
x // 1
y // 2
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4
以下例子,因為等號右邊的值,要么轉為對象以后不具備 Iterator 接口(前五個表達式),要么本身就不具備 Iterator 接口(最后一個表達式)
// 報錯
let [foo] = 1;
let [foo] = false;
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};
成功
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
function* fibs() {
let a = 0;
let b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
let [first, second, third, fourth, fifth, sixth] = fibs();
sixth // 5
- 默認值
let [foo = true] = [];
foo // true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
只有當一個數(shù)組成員嚴格等于undefined,默認值才會生效。
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null,(null不嚴格等于undefined。)
//默認值可以引用解構賦值的其他變量,但該變量必須已經(jīng)聲明。
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [2]; // x=2; y=2
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined,x用y做默認值時,y還沒有聲明
2、對象的解構賦值
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"
//沒有對應的同名屬性,導致取不到值
let { baz } = { foo: "aaa", bar: "bbb" };
baz // undefined
對象的解構賦值的內(nèi)部機制,是先找到同名屬性,然后再賦給對應的變量
變量名與屬性名不一致,必須寫成下面這樣:
//foo是匹配的模式,baz才是變量。真正被賦值的是變量baz,而不是模式foo
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
3、字符串的解構賦值
const [a, b, c, d, e] = 'hello';
a // "h"
b // "e"
c // "l"
d // "l"
e // "o"
let {length : len} = 'hello';
len // 5
4、數(shù)值和布爾值的解構賦值
//如果等號右邊是數(shù)值和布爾值,則會先轉為對象
let {toString: s} = 123;
s === Number.prototype.toString // true
let {toString: s} = true;
s === Boolean.prototype.toString // true
let { prop: x } = undefined; // TypeError
let { prop: y } = null; // TypeError
5、函數(shù)參數(shù)的解構賦值
[[1, 2], [3, 4]].map(([a, b]) => a + b);
// [ 3, 7 ]
//函數(shù)move的參數(shù)是一個對象,通過對這個對象進行解構,得到變量x和y的值
function move({x = 0, y = 0} = {}) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, 0]
move({}); // [0, 0]
move(); // [0, 0]
//為函數(shù)move的參數(shù)指定默認值,而不是為變量x和y指定默認值
function move({x, y} = { x: 0, y: 0 }) {
return [x, y];
}
move({x: 3, y: 8}); // [3, 8]
move({x: 3}); // [3, undefined]
move({}); // [undefined, undefined]
move(); // [0, 0]
不能使用圓括號的情況
- (1). 變量聲明語句,模式不能使用圓括號
// 全部報錯
let [(a)] = [1];
let {x: (c)} = {};
let ({x: c}) = {};
let {(x: c)} = {};
let {(x): c} = {};
let { o: ({ p: p }) } = { o: { p: 2 } };
- (2)函數(shù)參數(shù)
//函數(shù)參數(shù)也屬于變量聲明,因此不能帶有圓括號。
// 報錯
function f([(z)]) { return z; }
// 報錯
function f([z,(x)]) { return x; }
- (3)賦值語句的模式
// 全部報錯
({ p: a }) = { p: 42 };
([a]) = [5];
// 報錯
[({ p: a }), { x: c }] = [{}, {}];
可以使用圓括號的情況
//都是賦值語句,而不是聲明語句
[(b)] = [3]; // 正確
({ p: (d) } = {}); // 正確
[(parseInt.prop)] = [3]; // 正確