解构: 从数组和对象中提取值,对变量进行赋值,
数组的解构赋值
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 [head, ...tail] = [1, 2, 3, 4];
head // 1
tail // [2, 3, 4]
let [x, y, ...z] = ['a'];
x // "a"
y // undefined
z // []
解构不成功变量会被赋值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 接口),那么将会报错
例如: 右边是Set结构,也是可以使用数组的解构赋值
let [x, y, z] = new Set(['a', 'b', 'c']);
x // "a"
解构默认值:
let [x = 1] = [undefined];
x // 1
如果默认值是一个表达式,那么这个表达式是惰性求值,只有在用到时才会求值
function f() {
console.log('aaa');
}
let [x = f()] = [1]; // 在x可以取到值时,f函数不会执行
let [x = 1, y = x] = []; // x=1; y=1
let [x = 1, y = x] = [1, 2]; // x=1; y=2
let [x = y, y = 1] = []; // ReferenceError: y is not defined 此时x用y做默认值,y还未声明
对象的解构
let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
对象的解构: 数组的元素是按次序排列的,变量的取值由位置决定。对象的属性没有次序,变量必须与属性名同名,才可以取到正确的值。 同样解构失败值等于undefined
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined
对象的解构可以将现有对象的方法,赋值给某个变量
//例一将`Math`对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。例二将`console.log`赋值到`log`变量
// 栗一
let { log, sin, cos } = Math;
// 栗二
const { log } = console;
log('hello') // hello
如果变量名和属性名不一致,需要写成下面这样:
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'
对象解构赋值的内部机制: 先找到同名属性,然后赋给对应的变量。真正被赋值的是后者不是前者
栗子:
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined
其中foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,不是模式foo
对象的解构也适用于嵌套结构
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p, p: [x, { y }] } = obj;
x // "Hello"
y // "World"
p // ["Hello", {y: "World"}]
//等号左边对象defoo属性,对应一个子对象。该子对象的bar属性,解构会报错
//因为foo此时等于undefined,再取子属性会报错
let {foo : {bar}} = { baz: 'baz'}
//对象的解构可以用一下方式
const obj1 = {};
const obj2 = { foo: 'bar' };
Object.setPrototypeOf(obj1, obj2);
const { foo } = obj1;
foo // "bar"
也可以设置默认值,默认值生效条件是,对象的属性值严格等于(===)undefined