概念
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 // 1 b // 2 c // 3 复制代码
-
解构失败,输出undefined;
let [a, b, c] = [1, 2] a // 1 b // 2 c // undefined 复制代码
-
不完全解构;
let [a, b] = [1, 2, 3] a // 1 b // 2 复制代码
-
需具备Iterator接口;
let [a] = 'hello' a // "h" let [a, b] = new Set([1, 2]); a // 1 b // 2 let [a] = true // Uncaught ReferenceError: a is not defined 复制代码
-
默认值。
只有当一个数组成员严格等于undefined,默认值才会生效。
let [a = 1, b = 2, c = 3] = [undefined, null, false] a // 1 b // null c // false 复制代码
如果默认值是一个表达式,那么这个表达式是惰性求值的。
function f() { console.log('test') } let [a = f()] = [1] a // 1 复制代码
默认值可以引用解构赋值的其他变量,但该变量必须已经声明。
let [a = 1, b = a] = []; a // 1 b // 1 let [a = 1, b = a] = [2] a // 2 b // 2 复制代码
对象
-
变量必须与属性同名,才能取到正确的值,且无需关注次序;
let {a, b, c} = {b: 2, a: 1, cc: 3} a // 1 b // 2 c // undefined 复制代码
-
嵌套使用;
let obj = { p: [ 'Hello', { b: 'World' } ] } let { p: [a, { b }] } = obj // 这时p是模式,不是变量,因此不会被赋值。 a // Hello b // 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 } = obj1 a // 1 复制代码
-
解构失败,输出undefined,同数组;
let {a, b} = {a: 1} a // 1 b // 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 = 1 let b = 2 [a, b] = [b, a] a // 2 b // 1 复制代码
-
函数返回多个值;
function test () { return [1, 2] } let [a, b] = test() a // 1 b // 2 复制代码
-
函数参数的定义;
function test ([a, b]) { return a + b } test([1, 2]) // 3 复制代码
-
提取
JSON
数据;let json = { a: 1, b: 2 } let {a, b} = json a // 1 b // 2 复制代码
-
函数参数的默认值;
function test (obj = {a: 1, b: 2}) { return obj.a + obj.b } test() // 3 test({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
时才会生效。
感谢阅读,如有问题,欢迎指正。
最后祝大家五四青年节快乐,吃好喝好玩好!