解构赋值是 ES6 引入的重要特性之一,允许我们从数组或对象中提取数据,并将其赋值给变量。它不仅提高了代码的可读性,还增强了数据处理的灵活性。
// 从数组中提取前两个元素
const [first, second] = [1, 2, 3];
console.log(first); // 输出: 1
console.log(second); // 输出: 2
跳过某些元素:
// 忽略前两个元素,仅提取第三个
const [, , third] = [1, 2, 3];
console.log(third); // 输出: 3
// 定义一个对象
const person = {
name: '张三',
age: 25
};
// 解构时为属性起新名字
const { name: userName, age: userAge } = person;
console.log(userName); // 输出: '张三'
console.log(userAge); // 输出: 25
当被解构的值为 undefined
时,默认值会被使用。
// 数组默认值
const [x = 1, y = 2] = [undefined, null];
console.log(x); // 输出: 1
console.log(y); // 输出: null(因为 null 不等于 undefined)
// 对象默认值
const { title = '默认标题', count = 0 } = {};
console.log(title); // 输出: '默认标题'
console.log(count); // 输出: 0
适用于复杂嵌套结构的对象或数组。
const user = {
id: 1,
info: {
name: '李四',
address: {
city: '北京'
}
}
};
// 多层嵌套解构
const { info: { name, address: { city } } } = user;
console.log(name); // 输出: '李四'
console.log(city); // 输出: '北京'
可以获取剩余的数组项或对象属性。
// 数组结合扩展运算符
const [head, ...tail] = [1, 2, 3, 4];
console.log(head); // 输出: 1
console.log(tail); // 输出: [2, 3, 4]
// 对象结合扩展运算符
const { id, ...rest } = { id: 1, name: '李四', age: 35 };
console.log(id); // 输出: 1
console.log(rest); // 输出: { name: '李四', age: 35 }
使函数接口更清晰,便于传参。
// 对象参数解构
function user({ name, age = 35 }) {
console.log(`${name}今年${age}岁`);
}
user({ name: '李四' }); // 输出: "李四今年35岁"
// 数组参数解构
function sum([a, b] = [0, 0]) {
return a + b;
}
console.log(sum([1, 3])); // 输出: 4
使用方括号 [expression]
动态指定要解构的属性名。
const key = 'name';
const { [key]: value } = { name: '李四' };
console.log(value); // 输出: '李四'
无需中间变量即可交换两个变量的值。
let a = 1, b = 2;
[a, b] = [b, a];
console.log(a); // 输出: 2
console.log(b); // 输出: 1
在一行内完成多个解构操作。
const obj = { a: 1, b: 2 };
const arr = [3, 4];
const { a, b } = obj, [c, d] = arr;
console.log(a, b, c, d); // 输出: 1 2 3 4
处理正则表达式返回的结果数组时非常方便。
const [, year, month, day] = /(\d{4})-(\d{2})-(\d{2})/.exec('2025-02-26');
console.log(year, month, day); // 输出: 2025 02 26
只导入需要的部分,提高模块可读性。
// 只导入需要的方法
import { useState, useEffect } from 'react';
// 解构同时重命名
import { useState as useStsteHook } from 'react';
结合空值合并运算符(??
)避免 null/undefined
报错。
const data = null;
const { value = 'default' } = data ?? {}; // 如果 data 为 null,则用空对象替代
console.log(value); // 输出: 'default'
防止对 null
或 undefined
进行解构导致报错。
const safeObj = maybeNull || {};
const { value } = safeObj; // 即使 maybeNull 为 null,也不会报错
字符串被视为字符数组,可以像数组一样解构。
const [a, b] = 'ES6';
console.log(a, b); // 输出: E S
只有在值为 undefined
时才使用默认值。
const { status = 'pending' } = { status: null }; // 不会使用默认值
console.log(status); // 输出: null
const { status = 'pending' } = { status: undefined }; // 使用默认值
console.log(status); // 输出: 'pending'
遍历 Map 时可直接解构键值对。
const map = new Map([['react', 18], ['vue', 3]]);
for (const [lib, version] of map) {
console.log(`${lib}@${version}`);
}
// 输出:
// react@18
// vue@3
解构来自生成器的数据流。
function* dataStream() {
yield [1, { val: '2025' }];
}
const [[index, { val }]] = dataStream();
console.log(index); // 输出: 1
console.log(val); // 输出: '2025'
解析异步请求返回的 JSON 数据。
const {
headers: { 'x-2025-version': apiVersion },
body: { results: [firstItem] }
} = await fetch('/2025-api').then(r => r.json());
console.log(apiVersion);
console.log(firstItem);
从类型数组中提取原始字节数据。
const buffer = new Uint8Array([72, 101]);
const [firstByte, secondByte] = buffer;
console.log(String.fromCharCode(firstByte, secondByte)); // 输出: 'He'
通过可选链和异常捕获确保安全访问深层属性。
// 可选链保护
const {
user?.profile: {
email = '[email protected]'
} = {}
} = serverResponse ?? {};
// 异常捕获模式
try {
const { data } = JSON.parse(apiResponse);
} catch {
const { data } = { data: 'Fallback 2025 Data' };
}
函数柯里化中结合解构,实现灵活的参数传递。
const createRequest = ({ headers }) => ({ body }) =>
fetch('/api', { headers, body });
// 使用示例:
const requestWithHeaders = createRequest({ headers: { token: 'abc' } });
requestWithHeaders({ body: JSON.stringify({ query: 'test' }) });
结合函数式编程风格,简化数据转换流程。
const parseUser = ([, { name, age }]) => ({
name,
birthYear: 2025 - age
});
parseUser(['header', { name: 'Bob', age: 30 }]);
// 输出: { name: 'Bob', birthYear: 1995 }
利用 Proxy 实现响应式或拦截行为。
const reactiveObj = new Proxy({ x: 10 }, {
get(target, prop) {
return target[prop] * 2; // 每次访问都乘以 2
}
});
const { x } = reactiveObj;
console.log(x); // 输出: 20
封装一个安全访问嵌套属性的工具函数。
const safeGet = (obj, path) => {
try {
return Function(
'o',
`return o?.${path.join('?.')}`
)(obj);
} catch {
const [firstKey] = path;
return { [firstKey]: null };
}
};
// 示例使用:
const result = safeGet({ user: { profile: { name: 'Alice' } } }, ['user', 'profile', 'name']);
console.log(result); // 输出: 'Alice'
类型 |
场景 |
特点 |
数组解构 |
提取元素、跳过元素、变量交换 |
简洁直观 |
对象解构 |
属性提取、重命名、默认值 |
更具语义 |
嵌套解构 |
处理复杂结构 |
提升可读性 |
扩展运算符 |
获取剩余部分 |
灵活控制数据 |
函数参数解构 |
简化接口设计 |
提高函数复用性 |
动态解构 |
计算属性名 |
支持动态逻辑 |
安全解构 |
防止错误 |
提高健壮性 |