# [Destructuring](https://babeljs.cn/docs/plugins/transform-es2015-destructuring)
在 ES6 中可以使用,支持解構操作。
可以使用 `babel-plugin-transform-es2015-destructuring` 進行語法轉換。
```
npm install --save-dev babel-plugin-transform-es2015-destructuring
```
## .babelrc 配置
```json
{
"plugins": ["transform-es2015-destructuring"]
}
```
## 使用
### 數組解構
數組解構的格式如下:
```
[ variable1, variable2, ..., variableN ] = array;
```
in
```js
let arr = ['aa', 'bb', 'cc']
var [first, second, third] = someArray;
console.log(first, second, third) // 'aa', 'bb', 'cc'
```
out
```js
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var arr = ['aa', 'bb', 'cc'];
var _someArray = someArray,
_someArray2 = _slicedToArray(_someArray, 3),
first = _someArray2[0],
second = _someArray2[1],
third = _someArray2[2];
console.log(first, second, third);
```
#### 多維數組解構
in
```js
var [foo, [[bar], baz]] = [1, [[2], 3]];
```
out
```js
var foo = 1,
bar = 2,
baz = 3;
```
#### 元素留空解構
可以使用留空跳過被解構數組中的某些元素。
in
```js
var [,,third] = ["foo", "bar", "baz"];
```
out
```js
var _ref = ["foo", "bar", "baz"],
third = _ref[2];
```
#### 不定參數解構
in
```js
var [head, ...tail] = [1, 2, 3, 4];
```
out
```js
var head = 1,
tail = [2, 3, 4];
```
#### 越界解構
當訪問空數組或越界訪問數組時,對其解構與對其索引的行為一致,最終得到的結果都是:undefined。
in
```js
var [missing] = [];
console.log(missing); // undefined
```
out
```js
var _ref = [],
missing = _ref[0];
console.log(missing); // undefined
```
### 迭代器解構
數組解構賦值的模式同樣適用于任意迭代器。
in
```js
function* fibs() {
var a = 0;
var b = 1;
while (true) {
yield a;
[a, b] = [b, a + b];
}
}
var [first, second, third, fourth, fifth, sixth] = fibs();
console.log(sixth);
```
out
```js
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var _marked = /*#__PURE__*/regeneratorRuntime.mark(fibs);
function fibs() {
var a, b, _ref;
return regeneratorRuntime.wrap(function fibs$(_context) {
while (1) {
switch (_context.prev = _context.next) {
case 0:
a = 0;
b = 1;
case 2:
if (!true) {
_context.next = 10;
break;
}
_context.next = 5;
return a;
case 5:
_ref = [b, a + b];
a = _ref[0];
b = _ref[1];
_context.next = 2;
break;
case 10:
case "end":
return _context.stop();
}
}
}, _marked, this);
}
var _fibs = fibs(),
_fibs2 = _slicedToArray(_fibs, 6),
first = _fibs2[0],
second = _fibs2[1],
third = _fibs2[2],
fourth = _fibs2[3],
fifth = _fibs2[4],
sixth = _fibs2[5];
console.log(sixth);
```
### 對象解構
通過解構對象,你可以把它的每個屬性與不同的變量綁定,首先指定被綁定的屬性,然后緊跟一個要解構的變量。
in
```js
var robotA = { name: "Bender", age: 18 };
var robotB = { name: "Flexo", age: 20 };
var { name: nameA, age: ageA } = robotA;
var { name: nameB, age: ageB } = robotB;
console.log(nameA, ageA); // "Bender", 18
console.log(nameB, ageB); // "Flexo", 20
```
out
```js
var robotA = { name: "Bender", age: 18 };
var robotB = { name: "Flexo", age: 20 };
var nameA = robotA.name,
ageA = robotA.age;
var nameB = robotB.name,
ageB = robotB.age;
console.log(nameA, ageA); // "Bender", 18
console.log(nameB, ageB); // "Flexo", 20
```
#### 對象解構的簡寫
當屬性名與變量名一致時,可以通過一種實用的句法簡寫:
in
```js
var { foo, bar } = { foo: "lorem", bar: "ipsum" };
console.log(foo); // "lorem"
console.log(bar); // "ipsum"
```
out
```js
var _foo$bar = { foo: "lorem", bar: "ipsum" },
foo = _foo$bar.foo,
bar = _foo$bar.bar;
console.log(foo); // "lorem"
console.log(bar); // "ipsum"
```
#### 嵌套解構
in
```js
var complicatedObj = {
arrayProp: [
"Zapp",
{ second: "Brannigan" }
]
};
var { arrayProp: [first, { second }] } = complicatedObj;
console.log(first); // "Zapp"
console.log(second); // "Brannigan"
```
out
```js
"use strict";
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();
var complicatedObj = {
arrayProp: ["Zapp", { second: "Brannigan" }]
};
var _complicatedObj$array = _slicedToArray(complicatedObj.arrayProp, 2),
first = _complicatedObj$array[0],
second = _complicatedObj$array[1].second;
console.log(first); // "Zapp"
console.log(second); // "Brannigan"
```
### 解構的默認值
in
```js
var [missing = true] = [];
console.log(missing); // true
var { message: msg = "Something went wrong" } = {};
console.log(msg); // "Something went wrong"
var { x = 3 } = {};
console.log(x); // 3
```
out
```js
var _ref = [],
_ref$ = _ref[0],
missing = _ref$ === undefined ? true : _ref$;
console.log(missing); // true
var _ref2 = {},
_ref2$message = _ref2.message,
msg = _ref2$message === undefined ? "Something went wrong" : _ref2$message;
console.log(msg); // "Something went wrong"
var _ref3 = {},
_ref3$x = _ref3.x,
x = _ref3$x === undefined ? 3 : _ref3$x;
console.log(x); // 3
```
## 注意事項
>[danger] 請注意,當你解構對象并賦值給變量時,如果你已經聲明或不打算聲明這些變量(亦即賦值語句前沒有let、const或var關鍵字),你應該注意這樣一個潛在的語法錯誤:
---
```js
{ blowUp } = { blowUp: 10 };
// Syntax error 語法錯誤
```
為什么會出錯?這是因為JavaScript語法通知解析引擎將任何以{開始的語句解析為一個塊語句(例如,{console}是一個合法塊語句)。解決方案是將整個表達式用一對小括號包裹:
```js
({ safe } = {});
// No errors 沒有語法錯誤
```
>[danger] 當你嘗試解構null或undefined時,你會得到一個類型錯誤:
---
```js
var {blowUp} = null;
// TypeError: null has no properties(null沒有屬性)
```
>[warning] 但是,可以解構其它原始類型,例如:布爾值、數值、字符串,但這將得到undefined:
---
```js
var {wtf} = NaN;
console.log(wtf);
// undefined
```
你可能對此感到意外,但經過進一步審查你就會發現,原因其實非常簡單。當使用對象賦值模式時,被解構的值需要被強制轉換為對象。大多數類型都可以被轉換為對象,但null和undefined卻無法進行轉換。當使用數組賦值模式時,被解構的值一定要包含一個迭代器。
# 參考資料
[深入淺出ES6(六):解構 Destructuring](http://www.infoq.com/cn/articles/es6-in-depth-destructuring/)