概念
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
认识:
let [a, b] = [1, 2] a // 1 b // 2复制代码
图解:
条件:
-
等号两边结构一致;
let [{a, b}, c] = { a: 1, b: 2, c: 3} // Uncaught TypeError: {(intermediate value)(intermediate value)(intermediate value)} is not iterable复制代码
-
定义与赋值同时完成。
let [a, b][a, b] = [1, 2] // Uncaught SyntaxError: Missing initializer in destructuring declaration复制代码
下面我们将分别介绍数组、对象、函数参数、字符串、数值和布尔值的解构赋值。
数组
-
嵌套使用;
let [a, [[b], c]] = [1, [[2], 3]]a // 1b // 2c // 3复制代码
-
解构失败,输出undefined;
let [a, b, c] = [1, 2]a // 1b // 2c // undefined复制代码
-
不完全解构;
let [a, b] = [1, 2, 3]a // 1b // 2复制代码
-
需具备Iterator接口;
let [a] = 'hello'a // "h"let [a, b] = new Set([1, 2]);a // 1b // 2let [a] = true // Uncaught ReferenceError: a is not defined复制代码
-
默认值。
只有当一个数组成员严格等于undefined,默认值才会生效。
let [a = 1, b = 2, c = 3] = [undefined, null, false] a // 1b // nullc // false复制代码
如果默认值是一个表达式,那么这个表达式是惰性求值的。
function f() { console.log('test')}let [a = f()] = [1]a // 1复制代码
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [a = 1, b = a] = [];a // 1b // 1let [a = 1, b = a] = [2]a // 2b // 2复制代码
对象
-
变量必须与属性同名,才能取到正确的值,且无需关注次序;
let {a, b, c} = { b: 2, a: 1, cc: 3}a // 1b // 2c // undefined复制代码
-
嵌套使用;
let obj = { p: [ 'Hello', { b: 'World' } ]}let { p: [a, { b }] } = obj // 这时p是模式,不是变量,因此不会被赋值。a // Hellob // World复制代码
如果解构模式是嵌套的对象,而且子对象所在的父属性不存在,那么将会报错。
let { a: {a1}, b: {b1}} = { a: { a1: 1}} // Uncaught TypeError: Cannot destructure property `b1` of 'undefined' or 'null'复制代码
对象的解构赋值可以取到继承的属性。
let obj1 = {}let obj2 = { a: 1 }Object.setPrototypeOf(obj1, obj2)let { a } = obj1a // 1复制代码
-
解构失败,输出undefined,同数组;
let {a, b} = { a: 1}a // 1b // undefined复制代码
-
不完全解构,同数组;
let {a} = { a: 1, b: 2}a // 1复制代码
-
变量名与属性名不一致;
let { a: test } = { a: 1 }test // 1复制代码
-
默认值,同数组。
函数参数
[[1, 2], [3, 4]].map(([a, b]) => a + b) // [3, 7] [[1, 2], [3, 4]].map(([a, b, c = 100]) => a + b + c) // [103, 107]复制代码
字符串
字符串被转换成了一个类似数组的对象。
let [a, b] = 'hello' a // "h" b // "e" let { length : l} = 'hello' l // 5复制代码
数值 & 布尔值
解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。
let { toString: s} = 123; s === Number.prototype.toString // true let { toString: s} = true; s === Boolean.prototype.toString // true复制代码
用途
-
交换值;
let a = 1let b = 2[a, b] = [b, a]a // 2b // 1复制代码
-
函数返回多个值;
function test () { return [1, 2]}let [a, b] = test()a // 1b // 2复制代码
-
函数参数的定义;
function test ([a, b]) { return a + b}test([1, 2]) // 3复制代码
-
提取
JSON
数据;let json = { a: 1, b: 2}let {a, b} = jsona // 1b // 2复制代码
-
函数参数的默认值;
function test (obj = {a: 1, b: 2}) { return obj.a + obj.b}test() // 3test({ a: 100, b: 100}) // 200复制代码
-
遍历
Map
结构;let map = new Map([ ['a', 1], ['b', 2]])for (let [key, value] of map) { console.log(`${key} : ${value}`) // a : 1 b : 2}复制代码
-
输入模块的指定方法。
import {Text, View} from "react-native"复制代码
参考
小结
本文主要介绍了数组、对象、函数参数、字符串、数值和布尔值的解构赋值,其中,数组和对象在日常开发中使用超级频繁,掌握好二者的解构赋值会大大减少容错代码,提高开发效率。函数参数就是使用解构赋值的好地方。
需特别注意:
- 数组解构赋值需具备
Iterator
接口; - 对象解构赋值需特别注意变量名与属性名;
- 解构失败,输出undefined;
- 默认值在===
undefined
时才会生效。
感谢阅读,如有问题,欢迎指正。
最后祝大家五四青年节快乐,吃好喝好玩好!