变量的解构赋值
简介
变量的解构可以应用于:
- 数组
- 字符串
- 对象
- 函数的参数
- 数值和布尔值
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'
复制代码