icon
解构

解构

解构(Destructuring)是 ES6 引入的语法,可以从数组或对象中提取值,赋值给变量。

数组解构

  1. 基本用法
const arr = [1, 2, 3];
const [a, b, c] = arr;
console.log(a, b, c); // 1, 2, 3
  1. 跳过元素
const arr = [1, 2, 3, 4, 5];
const [first, , third, , fifth] = arr;
console.log(first, third, fifth); // 1, 3, 5
  1. 默认值
const arr = [1, 2];
const [a, b, c = 3] = arr;
console.log(a, b, c); // 1, 2, 3

const [x, y = 10] = [5];
console.log(x, y); // 5, 10
  1. 剩余元素
const arr = [1, 2, 3, 4, 5];
const [first, second, ...rest] = arr;
console.log(first);  // 1
console.log(second); // 2
console.log(rest);   // [3, 4, 5]
  1. 交换变量
let a = 1;
let b = 2;
[a, b] = [b, a];
console.log(a, b); // 2, 1
  1. 嵌套解构
const arr = [1, [2, 3], 4];
const [a, [b, c], d] = arr;
console.log(a, b, c, d); // 1, 2, 3, 4

对象解构

  1. 基本用法
const obj = { name: 'Alice', age: 25 };
const { name, age } = obj;
console.log(name, age); // 'Alice', 25
  1. 重命名
const obj = { name: 'Alice', age: 25 };
const { name: userName, age: userAge } = obj;
console.log(userName, userAge); // 'Alice', 25
  1. 默认值
const obj = { name: 'Alice' };
const { name, age = 18 } = obj;
console.log(name, age); // 'Alice', 18

const { city = 'Unknown' } = {};
console.log(city); // 'Unknown'
  1. 默认值 + 重命名
const obj = { name: 'Alice' };
const { name: userName, age: userAge = 18 } = obj;
console.log(userName, userAge); // 'Alice', 18
  1. 剩余属性
const obj = { name: 'Alice', age: 25, city: 'NYC' };
const { name, ...rest } = obj;
console.log(name); // 'Alice'
console.log(rest); // { age: 25, city: 'NYC' }
  1. 嵌套解构
const obj = {
  user: {
    name: 'Alice',
    age: 25
  },
  city: 'NYC'
};

const { user: { name, age }, city } = obj;
console.log(name, age, city); // 'Alice', 25, 'NYC'

// 重命名嵌套属性
const { user: { name: userName } } = obj;
console.log(userName); // 'Alice'
  1. 计算属性名
const key = 'name';
const obj = { name: 'Alice', age: 25 };
const { [key]: value } = obj;
console.log(value); // 'Alice'

函数参数解构

  1. 数组参数
function sum([a, b, c]) {
  return a + b + c;
}
console.log(sum([1, 2, 3])); // 6
  1. 对象参数
function greet({ name, age }) {
  return `Hello, ${name}. You are ${age} years old.`;
}
console.log(greet({ name: 'Alice', age: 25 }));
// 'Hello, Alice. You are 25 years old.'

// 带默认值
function createUser({ name, age = 18, city = 'Unknown' }) {
  return { name, age, city };
}
console.log(createUser({ name: 'Alice' }));
// { name: 'Alice', age: 18, city: 'Unknown' }
  1. 默认参数对象
function config({ timeout = 1000, retries = 3 } = {}) {
  return { timeout, retries };
}
console.log(config());           // { timeout: 1000, retries: 3 }
console.log(config({ timeout: 2000 })); // { timeout: 2000, retries: 3 }

实际应用

  1. 函数返回值
function getCoordinates() {
  return [10, 20];
}

const [x, y] = getCoordinates();
console.log(x, y); // 10, 20

function getUser() {
  return { name: 'Alice', age: 25 };
}

const { name, age } = getUser();
console.log(name, age); // 'Alice', 25
  1. 遍历 Map
const map = new Map([
  ['name', 'Alice'],
  ['age', 25]
]);

for (const [key, value] of map) {
  console.log(key, value);
}
// name Alice
// age 25
  1. 处理 API 响应
async function fetchUser() {
  const response = await fetch('/api/user');
  const { data: { user, settings } } = await response.json();
  return { user, settings };
}

// 使用
const { user, settings } = await fetchUser();
  1. 配置对象
function createComponent({
  name,
  props = {},
  children = [],
  ...otherOptions
}) {
  return {
    name,
    props,
    children,
    ...otherOptions
  };
}

const component = createComponent({
  name: 'Button',
  onClick: () => {},
  className: 'btn'
});
  1. 模块导入
// 从模块中解构导入
import { useState, useEffect } from 'react';
import { map, filter, reduce } from 'lodash';

// 重命名导入
import { createUser as create } from './utils';
  1. 忽略不需要的值
const arr = [1, 2, 3, 4, 5];
const [first, , , fourth] = arr;
console.log(first, fourth); // 1, 4

const obj = { a: 1, b: 2, c: 3 };
const { a, c } = obj;
console.log(a, c); // 1, 3
  1. 条件解构
const user = getUser();
const { name, age } = user || {};
console.log(name, age); // 避免 user 为 null/undefined 时报错
  1. 解构赋值
let a, b;
({ a, b } = { a: 1, b: 2 });
console.log(a, b); // 1, 2

// 注意:必须用括号包裹,否则会被解析为代码块

嵌套解构示例

const data = {
  users: [
    { name: 'Alice', age: 25 },
    { name: 'Bob', age: 30 }
  ],
  meta: {
    total: 2,
    page: 1
  }
};

// 解构嵌套数据
const {
  users: [firstUser, secondUser],
  meta: { total }
} = data;

console.log(firstUser);  // { name: 'Alice', age: 25 }
console.log(total);       // 2

// 更深层嵌套
const {
  users: [{ name: firstName }]
} = data;
console.log(firstName); // 'Alice'

注意事项

  1. 解构失败不会报错
const [a] = [];
console.log(a); // undefined

const { b } = {};
console.log(b); // undefined
  1. 解构 null/undefined 会报错
const { a } = null;      // TypeError
const { a } = undefined;  // TypeError

// 使用默认值避免
const { a = 1 } = null || {}; // 安全
  1. 默认值只在值为 undefined 时生效
const { a = 1 } = { a: null };
console.log(a); // null (不是 1)

const { b = 1 } = { b: undefined };
console.log(b); // 1
  1. 解构是浅拷贝
const obj = { nested: { value: 1 } };
const { nested } = obj;
nested.value = 2;
console.log(obj.nested.value); // 2 (被修改了)
  1. 不能解构原始值
// 这些会报错
const [a] = 'hello';     // 字符串会被转换为字符数组
const { a } = 'hello';   // TypeError: Cannot destructure property 'a' of 'hello'

常见模式

  1. 提取和重命名
const response = { status: 200, data: { users: [] } };
const { data: { users: userList } } = response;
console.log(userList); // []
  1. 提供默认值
function process({ input = '', options = {} } = {}) {
  // 安全处理
}
  1. 交换变量
let x = 1, y = 2;
[x, y] = [y, x];
  1. 函数参数简化
// 之前
function createUser(options) {
  const name = options.name;
  const age = options.age || 18;
  // ...
}

// 之后
function createUser({ name, age = 18 }) {
  // ...
}