简介
变量的解构可以应用于:
- 数组
- 字符串
- 对象
- 函数的参数
- 数值和布尔值
null
和undefined
不行,强行解构要报错
const [ a, b ] = [1, 2] const { x, y } = { x: 1, y: 2 } const [ a, b, c, d, e ] = 'hello' const f = ([a, b]) => { console.log(a,b) } let {toString } = 123; s === Number.prototype.toString // true let {toString } = true; s === Boolean.prototype.toString // true let { prop: x } = undefined // 报错:TypeError let { prop: y } = null // 报错:TypeError
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
数值和布尔值转换成对象都存在toString
属性,因此变量s
都能取到值。
由于undefined
和null
无法转为对象,所以对它们进行解构赋值,都会报错。
用法
对于以上五种类型,解构赋值的用法存在一定差异
数组:
- 本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。
- 赋值是按次序排列的
- 可以嵌套赋值
- 如果左边的模式对应的右边没有值,那么赋值
undefined
let [a, [[b], c]] = [1, [[2], 3]]; a // 1 b // 2 c // 3 let [a, ...arr] = [1, 2, 3, 4]; a // 1 arr // [2, 3, 4] let [ , , c] = [1, 2, 3]; c // 3 let [a, , c] = [1, 2, 3]; a // 1 b // undefined c // 3 let [x, y, ...z] = ['a']; x // "a" y // undefined z // []
如果用解构数组的方法解构 不带 Iterator
接口 的数据类型,就会报错。
// 报错 let [foo] = 1; let [foo] = false; let [foo] = NaN; let [foo] = undefined; let [foo] = null; let [foo] = {};
什么是Iterator
接口
遍历器(Iterator
)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator
接口,就可以完成遍历操作。
Iterator
的作用有三个:
- 一·是为各种数据结构,提供一个统一的、简便的访问接口;
- 二·是使得数据结构的成员能够按某种次序排列;
- 三·是 ES6 创造了一种新的遍历命令for...of循环,
Iterator
接口主要供for...of使用。
事实上,只要某种数据结构具有 Iterator
接口,都可以采用数组形式的解构赋值。
比如 Set 结构的数据
let [x, y, z] = new Set(['a', 'b', 'c']) x // "a"
字符串 也有Iterator
接口, 所以字符串的结构方式也是采用数组形式的
const [a, b, c, d, e] = 'hello' a // "h" b // "e" c // "l" d // "l" e // "o"
对象的解构
- 对象的赋值与数组的赋值有所不同。数组赋值是按顺序赋值, 对象赋值按对应属性名赋值,与顺序无关。
- 左边的变量如果在右边没有对应的属性,那么就赋值
undefined
- 在赋值时可以重命名
- 可以嵌套赋值
let { b, a } = { a: "aaa", b: "bbb" } a // "aaa" b // "bbb" let { a, c } = { a: "aaa", b: "bbb" } c // undefined let { a, b: x } = { a: "aaa", b: "bbb" } x // "bbb" b // Uncaught ReferenceError: b is not defined let obj = {a: { b: 'hello' }, c: '33'} let { a: { b }, c } = obj a // Uncaught ReferenceError: a is not defined b // hello c // 33 let { a, a: { b }, c } = obj
对象赋值其实是一种简写
let { b, a } = { a: "aaa", b: "bbb" } a // "aaa" b // "bbb" // 等价于 let { a: a, b: b } = { a: "aaa", b: "bbb" }
根据这个我们可以在对象解构赋值时 重命名
let { a: a1, b: b1 } = { a: "aaa", b: "bbb" }
字符串和数组 都带有length
属性 可以用对象解构形式取出
let arr = [1, 2] let { length } = arr length // 2 let str = 'abc' let { length } = str length // 3
函数参数的解构赋值
函数的参数可以是对象或数组,那么参数就可以使用解构赋值
const f1 = ({ x, y }) => { return x / y } const f2 = ([x, y]) => { return x + y }
解构赋值的默认值
当解构赋值时 左边模式在右边找不到对应的值或 对应的位置是undefined
时,就会赋值undefined
如果解构时预见到可能会出现这种情况是,可以给变量给予默认值。 只有在获取的值严格等于undefined
时才会使用默认值, false, null 不会
let [a, b = 2] = [1, undefined] // a = 1, b = 2 let [a, b = 2] = [1] // a = 1, b = 2 let [a, b, c = 'z'] = 'xy' // a =x, b = y, c = z let { a, b = 2, c = 3 } = {a: 1, b: undefined } // a = 1, b = 2, c = 3 let { a: x = 1 } = {a: undefined } function f({x = 0, y = 0}) { return [x, y] }
如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会执行。
function f() { console.log('aaa') } let [x = f()] = [1] let [x = f()] = [] // 'aaa'
解构赋值的应用
- 交换变量的值
let x = 1 let y = 2 [x, y] = [y, x]
- 从函数返回多个值
函数的返回值本身只能有一个
但是如果返回数组或者对象,获取返回值的时候使用解构赋值 就可以拿到多个变量的值了
// 返回一个数组 function getArr() { return [1, 2, 3] } let [a, b, c] = getArr(); // 返回一个对象 function getObj() { return { a: 1, b: 2 } } let { a, b } = getObj();
- 函数参数的定义 解构赋值可以方便地将一组参数与变量名对应起来。
// 参数是一组有次序的值 function f([x, y, z]) { ... } f([1, 2, 3]); // 参数是一组无次序的值 function f({x, y, z}) { ... } f({z: 3, y: 2, x: 1});
- 提取 JSON 数据
res = { "code" : "200", "msg" : "操作成功!", "data" : [{ "key" : "GBK", "value" : "GBK" }, ] } const { code, msg, data } = res
- 输入模块的指定方法 加载模块时, 有时候只想要这个模块内的部分功能,不想全部加载,就可以使用解构赋值
const { Icon, message } = require("antd") import {Icon, message } from 'antd'