解构赋值是 ES6 中最实用的特性之一,它允许从数组或对象中提取值,按照对应位置或属性名赋值给变量。
🎯 为什么需要解构#
传统方式从对象中取值:
const user = { name: '张三', age: 25, city: '北京' }
// ES5 写法var name = user.namevar age = user.agevar city = user.city
// ES6 解构const { name, age, city } = user代码简洁了很多,而且意图更清晰。
数组解构#
基本语法#
按位置匹配:
const [a, b, c] = [1, 2, 3]console.log(a) // 1console.log(b) // 2console.log(c) // 3跳过元素#
用逗号跳过不需要的元素:
const [first, , third] = [1, 2, 3]console.log(first) // 1console.log(third) // 3
// 只取第一个和最后一个const arr = [1, 2, 3, 4, 5]const [head, , , , tail] = arrconsole.log(head, tail) // 1 5剩余元素#
用 ... 收集剩余元素:
const [first, ...rest] = [1, 2, 3, 4]console.log(first) // 1console.log(rest) // [2, 3, 4]
// 实用场景:分离头部和尾部const [head, ...tail] = ['a', 'b', 'c']console.log(head) // 'a'console.log(tail) // ['b', 'c']🔶 剩余元素必须是最后一个:
// const [...rest, last] = [1, 2, 3]; // SyntaxError默认值#
解构失败时使用默认值:
const [a, b, c = 3] = [1, 2]console.log(c) // 3
const [x = 1, y = 2] = [undefined, null]console.log(x) // 1(undefined 触发默认值)console.log(y) // null(null 不触发默认值)默认值可以是表达式,惰性求值:
function getValue() { console.log('计算默认值') return 100}
const [a = getValue()] = [1]// 不会打印,因为 a 有值
const [b = getValue()] = []// 打印 '计算默认值'交换变量#
不需要临时变量:
let x = 1let y = 2
;[x, y] = [y, x]console.log(x, y) // 2 1
// 三个变量轮换let a = 1, b = 2, c = 3;[a, b, c] = [c, a, b]console.log(a, b, c) // 3 1 2对象解构#
基本语法#
按属性名匹配:
const { name, age } = { name: '张三', age: 25 }console.log(name) // '张三'console.log(age) // 25顺序无关:
const { age, name } = { name: '张三', age: 25 }console.log(name) // '张三'console.log(age) // 25重命名变量#
属性名和变量名可以不同:
const { name: username, age: userAge } = { name: '张三', age: 25 }console.log(username) // '张三'console.log(userAge) // 25// console.log(name); // ReferenceError语法是 { 属性名: 变量名 }(注意:属性名在前,变量名在后):
// 从 API 响应中提取并重命名const response = { data: { id: 1, user_name: '张三' },}
const { data: { id, user_name: userName },} = responseconsole.log(id) // 1console.log(userName) // '张三'默认值#
const { name, age = 18 } = { name: '张三' }console.log(age) // 18
// 重命名 + 默认值const { name: username = '匿名', role = 'user' } = {}console.log(username) // '匿名'console.log(role) // 'user'剩余属性#
const { a, ...rest } = { a: 1, b: 2, c: 3 }console.log(a) // 1console.log(rest) // { b: 2, c: 3 }
// 实用场景:排除某些属性const user = { id: 1, name: '张三', password: '123456' }const { password, ...safeUser } = userconsole.log(safeUser) // { id: 1, name: '张三' }解构的实际应用#
函数参数解构#
// 传统写法function createUser(options) { const name = options.name const age = options.age || 18 const role = options.role || 'user' // ...}
// 解构写法function createUser({ name, age = 18, role = 'user' }) { console.log(name, age, role)}
createUser({ name: '张三' }) // 张三 18 user函数返回值解构#
function getPosition() { return { x: 100, y: 200 }}
const { x, y } = getPosition()console.log(x, y) // 100 200
// 数组返回值function getRange() { return [0, 100]}
const [min, max] = getRange()console.log(min, max) // 0 100模块导入#
// 解构导入import { useState, useEffect } from 'react'
// 等价于import React from 'react'const { useState, useEffect } = React遍历 Map#
const map = new Map([ ['name', '张三'], ['age', 25],])
for (const [key, value] of map) { console.log(`${key}: ${value}`)}// name: 张三// age: 25处理 JSON 数据#
const response = { status: 200, data: { users: [ { id: 1, name: '张三' }, { id: 2, name: '李四' }, ], total: 2, },}
const { data: { users, total },} = responseconsole.log(users) // [{ id: 1, name: '张三' }, ...]console.log(total) // 2常见陷阱#
🔶 已声明变量的对象解构#
let name, age
// 错误写法 // { name, age } = { name: '张三', age: 25 }; // SyntaxError
// 正确写法:用括号包裹;({ name, age } = { name: '张三', age: 25 })因为 { 开头会被解析为代码块,需要括号告诉解析器这是表达式。
🔶 解构 null 和 undefined#
// const { name } = null; // TypeError// const { name } = undefined; // TypeError
// 安全写法const { name } = null || {}console.log(name) // undefined🔶 字符串解构#
字符串可以被当作数组解构:
const [a, b, c] = 'hello'console.log(a, b, c) // h e l
// 也可以解构 length 属性const { length } = 'hello'console.log(length) // 5🔶 数字和布尔值#
数字和布尔值会先转为对象:
const { toString: fn } = 123console.log(fn === Number.prototype.toString) // true
const { valueOf } = trueconsole.log(valueOf === Boolean.prototype.valueOf) // true小结#
| 类型 | 语法 | 匹配方式 |
|---|---|---|
| 数组解构 | [a, b] = arr | 按位置 |
| 对象解构 | { a, b } = obj | 按属性名 |
| 重命名 | { a: newA } = obj | 属性名:变量名 |
| 默认值 | { a = 1 } = obj | undefined 时生效 |
| 剩余元素 | { a, ...rest } = obj | 收集剩余部分 |
解构让代码更简洁、意图更清晰,是日常开发中使用频率最高的 ES6 特性之一。