## 一、基础语法
解构不仅可以用于数组,还可以用于对象。
~~~javascript
let {foo, bar} = {foo: 'aaa', bar: 'bbb'}; // foo = "aaa", bar = "bbb"
~~~
对象的解构与数组有一个重要的不同。
* 数组的元素是按次序排列的,变量的取值由它的位置决定;
* 对象的属性没有次序,变量必须与属性同名,才能取到正确的值。
~~~javascript
let {bar, foo} = {foo: 'aaa', bar: 'bbb'}; // foo = "aaa", bar = "bbb"
let {baz} = {foo: 'aaa', bar: 'bbb'}; // baz = undefined
~~~
对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量。
~~~javascript
let {log, sin, cos} = Math;
const {log} = console;
log('hello') // hello
~~~
上面代码中,将`Math`对象的对数、正弦、余弦三个方法,赋值到对应的变量上,将`console.log`赋值到`log`变量。
如果变量名与属性名不一致,必须写成下面这样。
~~~javascript
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"
~~~
这实际上说明,对象的解构赋值是下面形式的简写。
~~~javascript
let {foo: foo, bar: bar} = {foo: 'aaa', bar: 'bbb'};
~~~
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。
## 二、默认值
对象的解构也可以指定默认值。
~~~javascript
let {x = 3} = {}; // x = 3
let {x, y = 5} = {x: 1}; // x = 1, y = 5
let {x: y = 3} = {}; // y = 3
let {x: y = 3} = {x: 5}; // y = 5
let {message: msg = "hello" } = {}; // msg = "hello"
~~~
默认值生效的条件是,对象的属性值严格等于`undefined`。
~~~javascript
var {x = 3} = {x: undefined}; // x = 3
var {x = 3} = {x: null}; // x = null
~~~
上面代码中,属性`x`等于`null`,因为`null`与`undefined`不严格相等,所以是个有效的赋值,导致默认值`3`不会生效。
## 三、注意点
* 如果要将一个已经声明的变量用于解构赋值,必须处理一下。
~~~javascript
let x;
{x} = {x: 1}; // SyntaxError: syntax error
~~~
上面代码的写法会报错,因为 JavaScript 引擎会将`{x}`理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
~~~javascript
let x;
({x} = {x: 1});
~~~
* 由于数组本质是特殊的对象,因此可以对数组进行对象属性的解构。
~~~javascript
let arr = [1, 2, 3];
let {0 : first, [arr.length - 1] : last} = arr; // first = 1, last = 3
~~~