解构不仅可以用于数组,还可以用于对象。
一、变量名与属性名相同时:
let {b,a,c} = {a:1,b:2,c:3}; //次序不同,不影响解构赋值
console.log(a,b,c) //1 2 3
let {a,b,c} = {arr:1,b:2,c:3}; //变量名与属性名不相同
console.log(a,b,c) //undefined 2 3
注意点:对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值
二、变量名与属性名不同时(指的是左侧部分):
如果变量名与属性名不一致,必须写成下面这样。
let { first: f, last: l } = { first: 'hello', last: 'world' };
console.log(f); // 'hello'
console.log(l); // 'world'
这实际上说明,对象的解构赋值是下面形式的简写
var { foo: foo, bar: bar } = { foo: "aaa", bar: "bbb" };
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
var { foo: baz } = { foo: "aaa", bar: "bbb" };
baz // "aaa"
foo // error: foo is not defined
上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
注意,采用这种写法时,变量的声明和赋值是一体的。对于let和const来说,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错。
let foo;
let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"
let baz;
let {bar: baz} = {bar: 1}; // SyntaxError: Duplicate declaration "baz"
上面代码中,解构赋值的变量都会重新声明,所以报错了。不过,因为var命令允许重新声明,所以这个错误只会在使用let和const命令时出现。如果没有第二个let命令,上面的代码就不会报错。
let foo;
({foo} = {foo: 1}); // 成功
let baz;
({bar: baz} = {bar: 1}); // 成功
上面代码中,let命令下面一行的圆括号是必须的,否则会报错。因为解析器会将起首的大括号,理解成一个代码块,而不是赋值语句。
三、嵌套结构的对象
var obj = {
arr:[
111,
{
brr:222
}
]
}
let {arr:[x,{brr}]} = {arr:[111,{brr:222}]}
console.log(x,brr) //111 222
四、默认值
let { a = true } = {}
console.log(a); //true
let { a = true } = { a: false }
console.log(a); //false
var {x, y = 5} = {x: 1};
x // 1
y // 5
var {x:y = 3} = {};
y // 3
var {x:y = 3} = {x: 5};
y // 5
默认值生效的条件是,对象的属性值严格等于undefined(左侧默认值优先级高);打印左侧默认值
默认值不生效的条件是,对象的属性值严格不等于undefined(左侧默认值优先级低);打印右侧值
var {x = 3} = {x: undefined}; //生效的情况
x // 3
var {x = 3} = {x: null}; //不生效的情况
x // null
总结:如果右侧对象的值是undefined那么取左侧的默认值;如果不是undefined则取右侧的值。
五、解构失败
let {a,b} = undefined
console.log(a) //报错
let {a,b} = null
console.log(a) //报错
let {a,b} = 1
console.log(a) //undefiend
let {a,b} = "1"
console.log(a) //undefiend
let {a,b} = true
console.log(a) //undefiend
网友评论