let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
console.log(foo); // "aaa"
console.log(bar); // "bbb"
// 对象解构时,是赋予键的值
变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
console.log(foo); // "aaa"
console.log(bar); // "bbb"
let { baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // undefined
// 第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。
// 第二个例子的变量没有对应的同名属性,导致取不到值,最后等于undefined。
let { foo } = { bar: 'baz' };
console.log(foo); // undefined
// 上面代码中,等号右边的对象没有foo属性,所以变量foo取不到值,所以等于undefined。
let { log, sin, cos } = Math;
console.log(log, sin, cos);
// 上面代码的例一将Math对象的对数、正弦、余弦三个方法,赋值到对应的变量上,使用起来就会方便很多。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // "aaa"
// 此例是想将右边对象的属性foo值赋予baz,但是由于变量名与属性名不一致,直接赋值baz会等于undefined
let { first: f, last: l } = { first: 'hello', last: 'world' };
console.log(f); // 'hello'
console.log(l); // 'world'
这实际上说明,对象的解构赋值是对象的简写形式,
let { foo: foo, bar: bar } = { foo: 'aaa', bar: 'bbb' };
// 也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
console.log(baz); // "aaa"
console.log(foo); // error: foo is not defined
// 上面代码中,foo是匹配模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p: [x, { y }] } = obj;
console.log(x); // "Hello"
console.log(y); // "World"
注意,这时p是模式,不是变量,因此不会被赋值。如果p也要作为变量赋值,可以写成下面这样
// 例子1:
let obj = {
p: [
'Hello',
{ y: 'World' }
]
};
let { p, p: [x, { y }] } = obj;
console.log(x); // "Hello"
console.log(y); // "World"
console.log(p); // ["Hello", {y: "World"}]
// 例子2:
const node = {
loc: {
start: {
line: 1,
column: 5
}
}
};
let { loc, loc: { start }, loc: { start: { line } } } = node;
console.log(loc); // {start: {…}} ——————Object {start: Object}
console.log(start); // {line: 1, column: 5} ————Object {line: 1, column: 5}
console.log(line); // 1
// 上面代码有三次解构赋值,分别是对loc、start、line三个属性的解构赋值。
// 注意,最后一次对line属性的解构赋值之中,只有line是变量,loc和start都是模式,不是变量。
var { x = 3 } = { x }
console.log(x); //3
var { message: msg = 'Something went wrong' } = {};
console.log(msg); // "Something went wrong"
// 默认值生效的条件是,对象的属性值严格等于undefined。
// 错误的写法
let x;
{ x } = { x: 1 };// SyntaxError: syntax error
// 上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。
// 只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
{
// 正确的写法
let x;
({ x } = { x: "正确的写法 1" });
console.log(x);
}
({} = [true, false]);
({} = 'abc');
({} = []);
// 上面的表达式虽然毫无意义,但是语法是合法的,可以执行。
let arr = ["aaa", "bbb", "ccc"];
let { 0: first, [arr.length - 1]: last } = arr;
console.log(first); // aaa
console.log(last); // ccc
// 上面代码对数组进行对象解构。
// 数组arr的0键对应的值是1,[arr.length - 1]就是2键,对应的值是3。
对象的结构赋值,核心点是模式匹配,模式决定真正赋值的是谁。
提示:文章内容主要参考阮一峰《ECMAScript 6 入门》,更多详细内容可以去看阮老师的文章,这里做常用内容的讲解
阮一峰>>>《ECMAScript 6 入门》