javascript

ES6 解构赋值与扩展运算符

By AI-Writer 12 min read

ES6 引入的解构赋值(Destructuring Assignment)和扩展运算符(Spread Operator)是 JavaScript 中最常用、最能提升代码可读性的语法特性。它们让从对象或数组中提取数据、合并集合变得异常简洁。

数组解构

数组解构允许你按照位置从数组中提取元素。

基本语法

javascript
const colors = ['red', 'green', 'blue'];

// 传统方式
const r = colors[0];
const g = colors[1];
const b = colors[2];

// 解构赋值
const [r, g, b] = colors;
console.log(r, g, b); // 'red' 'green' 'blue'

跳过元素与默认值

javascript
const numbers = [1, 2, 3, 4, 5];

// 跳过前两个元素
const [, , third] = numbers;
console.log(third); // 3

// 提供默认值(当解构值为 undefined 时生效)
const [a = 10, b = 20, c = 30] = [1, undefined];
console.log(a, b, c); // 1 20 30

嵌套数组解构

javascript
const matrix = [[1, 2], [3, 4]];
const [[a, b], [c, d]] = matrix;
console.log(a, b, c, d); // 1 2 3 4

对象解构

对象解构按照属性名匹配提取值,而非位置。

基本语法

javascript
const user = { name: 'Alice', age: 28, city: 'Beijing' };

// 属性名必须与对象键匹配
const { name, age } = user;
console.log(name, age); // 'Alice' 28

// 解构为不同变量名
const { name: userName, age: userAge } = user;
console.log(userName, userAge); // 'Alice' 28

默认值与嵌套解构

javascript
const config = {
  host: 'localhost',
  port: 3000,
  db: { type: 'mysql', pool: { min: 2, max: 10 } }
};

// 默认值 + 嵌套解构
const {
  host,
  port,
  timeout = 5000,           // 默认值
  db: {
    type,
    pool: { min, max }      // 深层解构
  }
} = config;

console.log(timeout); // 5000(原对象无此属性)
console.log(min, max); // 2 10

函数参数中的解构

解构在函数参数中尤为实用,避免了频繁访问 options.xxx

javascript
// 传统写法
function createUser(options) {
  const name = options.name;
  const role = options.role || 'user';
  // ...
}

// 解构写法
function createUser({ name, role = 'user', age = 18 }) {
  console.log(`创建用户: ${name}, 角色: ${role}, 年龄: ${age}`);
}

createUser({ name: 'Bob' });
// 创建用户: Bob, 角色: user, 年龄: 18

Rest 参数

Rest 参数...rest)用于收集剩余的元素,只能出现在解构模式的末尾。

数组 Rest

javascript
const [first, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest);  // [2, 3, 4, 5]

对象 Rest(ES2018)

javascript
const person = { id: 1, name: 'Alice', age: 28, city: 'Beijing' };

// 提取 id,其余属性归入 info
const { id, ...info } = person;
console.log(id);   // 1
console.log(info); // { name: 'Alice', age: 28, city: 'Beijing' }

Rest 参数是浅拷贝——它复制的是引用,而非深层克隆。

展开运算符

展开运算符(...)是 rest 的逆操作:将可迭代对象或对象字面量展开为独立元素。

数组展开

javascript
const arr1 = [1, 2];
const arr2 = [3, 4];

// 合并数组
const merged = [...arr1, ...arr2, 5];
console.log(merged); // [1, 2, 3, 4, 5]

// 复制数组(浅拷贝)
const copy = [...arr1];
copy.push(99);
console.log(arr1); // [1, 2] —— 原数组不受影响

// 将类数组或可迭代对象转为数组
const str = 'hello';
const chars = [...str];
console.log(chars); // ['h', 'e', 'l', 'l', 'o']

对象展开(ES2018)

javascript
const defaults = { theme: 'dark', lang: 'en' };
const overrides = { lang: 'zh', fontSize: 16 };

// 合并对象,后面的属性覆盖前面的
const settings = { ...defaults, ...overrides };
console.log(settings);
// { theme: 'dark', lang: 'zh', fontSize: 16 }

// 对象浅拷贝
const clone = { ...settings };

对象展开是浅拷贝:嵌套对象仍然共享引用。

在函数调用中的应用

展开运算符可以将数组元素作为独立参数传递:

javascript
const nums = [3, 1, 4, 1, 5];

// 传统:Math.max.apply(null, nums)
const max = Math.max(...nums);
console.log(max); // 5

// 与 new 配合使用(ES2015+)
const dateParts = [2026, 3, 26];
const d = new Date(...dateParts);
console.log(d); // 2026-04-26(注意:月份从 0 开始)

解构与展开的经典组合模式

1. 状态更新(不可变更新)

javascript
const state = { user: { name: 'Alice' }, count: 0 };

// React/Redux 风格的状态更新
const newState = {
  ...state,
  user: { ...state.user, name: 'Bob' },
  count: state.count + 1
};

2. 从数组中提取头和尾

javascript
const queue = ['a', 'b', 'c', 'd'];
const [head, ...tail] = queue;

console.log(head); // 'a'
console.log(tail); // ['b', 'c', 'd']

3. 多重返回值模拟

javascript
function parseUrl(url) {
  const match = url.match(/^(https?):\/\/([^\/]+)(\/.*)?$/);
  if (!match) return null;
  const [, protocol, host, path = '/'] = match;
  return { protocol, host, path };
}

const { protocol, host } = parseUrl('https://example.com/api');

常见陷阱

解构 null 与 undefined

nullundefined 进行解构会抛出 TypeError,空对象解构则安全无影响:

javascript
const {} = {};       // OK,只是没有绑定任何变量
const {} = null;     // TypeError!
const {} = undefined; // TypeError!

默认值仅在 undefined 时生效

javascript
const { a = 1 } = { a: null };
console.log(a); // null,不是 1

const { b = 1 } = { b: undefined };
console.log(b); // 1

展开运算符是浅拷贝

javascript
const obj = { nested: { value: 1 } };
const clone = { ...obj };

clone.nested.value = 2;
console.log(obj.nested.value); // 2 —— 嵌套对象被共享!

小结

特性用途示例
数组解构按位置提取const [a, b] = arr
对象解构按属性名提取const { x } = obj
重命名解构到不同变量const { x: y } = obj
默认值处理缺失值const { x = 1 } = obj
Rest收集剩余const [a, ...rest] = arr
展开分散元素[...arr1, ...arr2]

解构赋值和展开运算符是现代 JavaScript 代码的基石,掌握它们能让你写出更声明式、更简洁的代码。

#javascript #es6 #解构赋值 #扩展运算符

评论

A

Written by

AI-Writer

Related Articles

javascript
#10

Proxy、Reflect 与 Symbol

深入探索 JavaScript 元编程三大利器——Proxy 拦截器、Reflect API 与 Symbol 类型,掌握可劫持的语言行为与自定义迭代协议。

Read More
javascript
#11

数组内置方法综合运用

深入掌握 forEach、map、filter、reduce、find、sort 等数组方法的组合技巧,避开常见性能陷阱,写出更高效的函数式代码。

Read More