2. 解构赋值
NOxONE 2/14/2022 ES6
# 0. 引子
从数组和对象中提取值,对变量进行赋值,称为解构(Destructuring)
# 1. Array 解构
# 1.1 正常解构
let [a, b, c] = [1, 2, 3] // a=1,b=2,c=3
# 1.2 花里胡哨解构(看看就行)
let [a, , b] = [1, 2, 3] // a=1,b=2
let [a, b, ...c] = [1] // a=1,b=undefined,c=[]
let [a, [[b, c], d]] = [1, [[2, 3], 4]] // 你猜~
let [a, [b], d] = [1, [2, 3], 4] // a=1,b=2,d=4
// set也可以解构
let [x, y, z] = new Set([1, 2, 3]) // x=1,y=2,z=3
# 1.3 解构允许默认值,若位置无值(undefined
),默认值会替代
let [x, y = 2] = [1] // x=1, y=2
let [x, y = 2] = [1, undefined] // x=1, y=2
let [x = 1] = [undefined] // x=1
// null非undefined
let [x = 1] = [null] // x=null
# 2. Object 解构
# 2.1 属性解构
let { id, name } = { name: '吴彦祖', id: 7 } // id=7,name='NOxONE'(众所周知'NOxONE'==='吴彦祖')
# 2.2 方法解构
const { log } = console
log(7) // 7
let { sin, cos, random, abs } = Math
abs(-7) // 7
// 是不是解锁了新天地?
# 2.3 变量可以与要解构的属性不同名
其实之前的例子里的变量要与解构的属性同名是因为
let { id, name } = { id: 1007, name: 'jack' }
// 等价于
let { id: id, name: name } = { id: 1007, name: 'jack' }
也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量
。真正被赋值的是后者,而非前者
let { id: uid } = { id: 1007 } // uid:1007
# 2.4 花里胡哨解构(看看就行)
let obj = {
p: ['Hello', { y: 'World' }],
}
let {
p,
p: [x, { y }],
} = obj // p:["Hello", {y: "World"}], x='hello',y='world'
let obj = {}
let arr = [](({ id: obj.prop, flag: arr[0] } = { id: 123, flag: true }))
// 加括号强制执行,而无需加let、const
// obj={prop:123}, arr = [true]
// 数组本质上是特殊对象,属性为index
let arr = [1, 2, 3]
let { 0: first, [arr.length - 1]: last } = arr // first=1,last=3
对象的解构赋值可以取到继承的属性
const obj = {}
Object.setPrototypeOf(obj, { id: 107 })
const { id } = obj // id=107
# 2.5 解构默认值
var { x: y = 3 } = {} // y=3
var { x: y = 3 } = { x: 5 } // y=5
var { x = 3 } = { x: undefined } // x=3
var { x = 3 } = { x: null } // x=null
# 3. String 的解构 (看看就行)
解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象
const [a, b, c] = 'xyz' // a='x',b='y',c='z'
// String转对象
String: {
'0': 'x',
'1': 'y',
'2': 'z',
length: 3
}
# 4. Number 和 Boolean 解构 (看看就行)
let { toString: s } = 123
s === Number.prototype.toString // true,实际上是解构原型上的方法
let { toString: s } = true
s === Boolean.prototype.toString // true
# 5. 函数参数的解构
函数调用时传参会发生隐式解构
,
即let [arg1,...,arg2] = [...arguments]
function add([x, y]) {
return x + y
}
add([1, 2]) // 3
// 相当于 let [x,y] = [1,2]
# 5.1 传参隐式解构
;[
[1, 2],
[3, 4],
].map(([a, b]) => a + b) // [3,7]
// 相当于
// 第一次map
let [a, b] = [1, 2]
// 第二次map
let [a, b] = [3, 4]
# 5.2 解构默认值
function f(x, y = 5, z) {
return [x, y, z]
}
f() // [undefined, 5, undefined]
f(1) // [1, 5, undefined]
f(1, ,2) // 报错
f(1, undefined, 2) // [1, 5, 2]
function move({ x = 0, y = 0 } = { x: 9, y: 1 }) {
// {x:9,y:1}表示传参默认值
console.log([x, y])
}
move({ x: 3, y: 8 }) // [3, 8]
move({ x: 3 }) // [3, 0]
move({}) // [0, 0], 相当于 let {x=0,y=0} = {}
move() // [9, 1] , 相当于 let {x=0,y=0} = {x:9,y:1}
# ☆6. 解构的应用场景
# 6.1 变量交换
let x = 1
let y = ((2)[(x, y)] = [y, x])
# 6.2 解构函数返回值
function fn() {
return [1, 2, 3]
}
let [a, b, c] = fn()
function fn() {
return { name: 'jack', id: 107 }
}
let { name: uName, id: uId } = fn() // uName='jack', uId=107
# 6.3 函数参数解构
function fn({ x, y, z }) {
return x + y + z
}
fn({ z: 3, y: 2, x: 1 }) //
# 6.4 提取 JSON 数据
let jsonData = {
id: 1007,
name: 'jack',
data: ['LiNing', 'Anta'],
}
let { id, name, data: brands } = jsonData
# 6.5 函数参数默认值
// 定义默认配置
jQuery.ajax = function (url, { async = true, beforeSend = function () {}, cache = true, id = 12 } = {}) {
//....
}
jQuery.ajax('www.baidu.com', {
async: false,
cache: false,
// 这里只改变两个配置项,其他配置项不传入将取默认值
})
这样就避免了函数体内部类似 let id = config.id || 'default id'
这样的机车语句
# 6.6 遍历 Map 结构
const map = new Map()
map.set('id', 107)
map.set('name', 'jack')
// [['id',107],['name': 'jack']]
// 获取键值对
for (let [key, value] of map) {
console.log(key + ' is ' + value)
}
// 只获取键名
for (let [key] of map) {
// ...
}
// 只获取键值
for (let [, value] of map) {
// ...
}
# 6.7 引入模块的指定方法
const { getId, getUserInfo} = require('user')
import { getId, getUserInfo:myUserInfo } from 'user'