## 一、基礎語法
解構不僅可以用于數組,還可以用于對象。
~~~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
~~~