Destructuring

解构(destructuring)以 patterns 的方式从 objects 和 arrays 中提取数据。解构赋值

pattern = value

如果 value 是原始类型将转为 object(ToObject )。当 value是 undefined,null 时,抛出 TypeError 异常。

const { length } = 'abc' // length = 3
const { foo } = undefined // TypeError: Cannot match against 'undefined' or 'null'.

undefined,null 不像 strings 可以包装为对象,没有数据可以提取。

解构赋值跟一般赋值没有什么不同,不局限于给变量赋值,也可以给对象属性,数组元素等赋值。

const obj = {}
[obj.prop] = []

Object pattern

Object pattern { prop1: var1, prop2: var2 },如果变量和属性同名,可以简写为 { prop1, prop2 }

const obj = { first: 'Ivan', last: 'Yan' }
const { first, last } = obj
// first = "Ivan"; last = "Yan"

由于 {} 视为语句块,注意

{ a, b } = obj   // SyntaxError
({ a, b }) = obj // SyntaxError
({ a, b } = obj) // ok
const { a, b } = obj // ok

在 Node.js 模块中常常只提取需要的值

const { sum, mean } = '_'

object pattern 支持计算属性,可以提取 symbol keys

const { [Symbol.iterator]: func } = []
typeof func // 'function'

Array pattern

Array pattern [var1, var2], 赋值表达式 [var1, var2] = iterable

const [x] = [1, 2, 3]
// x = 1

可以省略跳过一些元素

const [, y] = 'abc'
// y = 'b'

剩余操作符 rest operator ...

const [x, ...y] = 'abc'
// x = 'a'; y = ['b', 'c']

剩余操作符的操作数可以是 array pattern

const [x, ...[y, z]] = 'abc'
// x = 'a'; y = 'b'; z = 'c'

Nested pattern

嵌套 pattern 可以将深层数据提取出来,不过相对复杂一些,容易出错

const obj = {
  a: [{ foo: 123, bar: 'abc' }]
}
const { a: [{ foo }] } = obj // foo = 123

默认值

pattern 可以指定默认值。当 pattern 没有匹配时将使用默认值。

// object pattern
const { a = 3, b } = {} // a = 3; b = undefined

// array pattern
const [x = 3, y] = [] // x = 3; y = undefined

当 pattern 匹配 undefined,也将使用默认值

const [x = 3] = [undefined] // x = 3
const { a = 3 } = { a: undefined } // a = 3

默认值可以是表达式,只在需要时计算

function log(x) { console.log(x); return 0 }
const [a = log('hello')] = [] // a = 0
// 'hello'
const [b = log('hello')] = [3] // b = 3

默认值可以引用 pattern 当中的变量,注意变量声明先后顺序

var [x = 3, y = x] = [] // x = 3; y = 3
var [x = y, y = 3] = [] // ReferenceError: y is not defined

默认值可以是 pattern

const [{ prop: x } = { prop: 3 }] = [] // x = ?
  1. { prop: x } 匹配 undefined, 于是使用默认值 { prop: 3 }
  2. 接着解构 ({ prop: x } = { prop: 3 }),结果 x = 3

empty pattern

ESLint no-empty-pattern

空 pattern 不创建变量

var [] = 'abc'

它们多半是误写

var { a: {} } = {}
var { a = {} } = {}

应用

交换值

let x = 1, y = 2; // 注意分号
[x, y] = [y, x]
console.log(x, y)

因为 array pattern 以 [ 开始,在省略分号时要小心。

exec()

const [, year, month, day] = /^(\d{4})-(\d{2})-(\d{2})$/
  .exec('2017-01-31') || []
console.log(year, month, day) // 2017 01 31

参考