# [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/)