JavaScript ES6+新特性完全指南

JavaScript教程 作者: 编辑团队 发布于: 2026-07-01 阅读约 15 分钟

概述

ES6(ECMAScript 2015)是JavaScript历史上最重要的一次更新,后续的ES7-ES14(ES2016-ES2023)继续引入了大量新特性。掌握这些现代JavaScript特性是成为一名高效前端开发者的必备条件。

本文将系统介绍最实用的ES6+特性,包括语法变化、新的数据结构、异步编程模式和现代代码组织方式。

let 和 const — 块级作用域

ES6引入了 letconst 两个新的变量声明方式,取代 var 的大部分使用场景。

// var 的问题:函数作用域,存在变量提升
var x = 10;
if (true) {
  var x = 20; // 覆盖了外部的 x
}
console.log(x); // 20

// let:块级作用域
let y = 10;
if (true) {
  let y = 20; // 块级作用域内的新变量
}
console.log(y); // 10

// const:块级作用域 + 不可重新赋值
const z = 10;
// z = 20; // TypeError!

// const 对象/数组仍可修改属性
const user = { name: '张三' };
user.name = '李四'; // 可以修改
// user = {}; // TypeError! 不能重新赋值
最佳实践:默认使用 const,只在需要重新赋值时使用 let,不再使用 var

箭头函数

箭头函数提供了更简洁的函数语法,并且自动绑定外层的 this

// 传统函数
function add(a, b) {
  return a + b;
}

// 箭头函数
const add = (a, b) => a + b;

// 单参数可省略括号
const double = x => x * 2;

// 多行箭头函数
const processUser = (user) => {
  const name = user.name.toUpperCase();
  const age = user.age + 1;
  return { name, age };
};

// 箭头函数最大的优势:this 绑定
class Timer {
  constructor() {
    this.seconds = 0;
  }

  start() {
    // 箭头函数继承外层 this
    setInterval(() => {
      this.seconds++;
      console.log(this.seconds);
    }, 1000);
  }
}

// 数组方法中的箭头函数
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(n => n * 2);
const evens = numbers.filter(n => n % 2 === 0);
const sum = numbers.reduce((acc, n) => acc + n, 0);

模板字符串

模板字符串使用反引号(`` ` ``),支持多行文本和变量插值。

const name = '张三';
const age = 25;

// 变量插值
const greeting = `你好,${name}!你今年 ${age} 岁。`;

// 多行字符串
const html = `
  <div class="user-card">
    <h2>${name}</h2>
    <p>年龄:${age}</p>
    <p>明年你 ${age + 1} 岁</p>
  </div>
`;

// 标签模板字符串
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => {
    const value = values[i - 1] ? `<mark>${values[i - 1]}</mark>` : '';
    return result + str + value;
  }, '');
}

const name2 = 'JavaScript';
const result = highlight`Hello ${name2}, welcome!`;
// "Hello <mark>JavaScript</mark>, welcome!"

解构赋值

解构赋值让你可以从数组或对象中快速提取值到变量中。

数组解构

// 基本解构
const [a, b, c] = [1, 2, 3];
// a=1, b=2, c=3

// 跳过元素
const [first, , third] = [1, 2, 3];
// first=1, third=3

// 剩余元素
const [head, ...tail] = [1, 2, 3, 4];
// head=1, tail=[2, 3, 4]

// 默认值
const [x = 0, y = 0] = [5];
// x=5, y=0

// 交换变量
let m = 1, n = 2;
[m, n] = [n, m]; // m=2, n=1

对象解构

// 基本解构
const user = { name: '张三', age: 25, city: '北京' };
const { name, age } = user;
// name='张三', age=25

// 重命名
const { name: userName, age: userAge } = user;

// 默认值
const { name, gender = '未知' } = user;
// gender='未知'

// 嵌套解构
const data = {
  result: {
    users: [{ name: '张三' }]
  }
};
const { result: { users: [firstUser] } } = data;

// 函数参数解构
function createUser({ name, age, role = 'user' }) {
  return { name, age, role };
}
createUser({ name: '张三', age: 25 });

展开运算符和剩余参数

// 展开数组
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5]; // [1, 2, 3, 4, 5]

// 展开对象
const user = { name: '张三', age: 25 };
const updatedUser = { ...user, age: 26, city: '北京' };

// 浅拷贝
const copy = [...arr1];
const objCopy = { ...user };

// 剩余参数
function sum(...numbers) {
  return numbers.reduce((acc, n) => acc + n, 0);
}
sum(1, 2, 3, 4); // 10

// 解构 + 剩余
const [first, ...rest] = [1, 2, 3, 4];
// first=1, rest=[2, 3, 4]

const { id, ...userData } = { id: 1, name: '张三', age: 25 };
// id=1, userData={ name: '张三', age: 25 }

Promise 和 async/await

异步编程是JavaScript的核心概念,ES6的Promise和后续的async/await极大改善了异步代码的可读性。

// Promise 基础
function fetchUser(id) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (id > 0) {
        resolve({ id, name: '张三' });
      } else {
        reject(new Error('无效ID'));
      }
    }, 1000);
  });
}

// Promise 链
fetchUser(1)
  .then(user => fetchUserPosts(user.id))
  .then(posts => console.log(posts))
  .catch(error => console.error(error))
  .finally(() => console.log('完成'));

// async/await — 更优雅的写法
async function loadUserData(id) {
  try {
    const user = await fetchUser(id);
    const posts = await fetchUserPosts(user.id);
    return { user, posts };
  } catch (error) {
    console.error('加载失败:', error);
    throw error;
  }
}

// 并行执行多个异步操作
async function loadDashboard() {
  const [user, posts, notifications] = await Promise.all([
    fetchUser(1),
    fetchUserPosts(1),
    fetchNotifications(1)
  ]);
  return { user, posts, notifications };
}

// Promise.allSettled — 不管成功失败都返回
const results = await Promise.allSettled([
  fetchUser(1),
  fetchUserPosts(1),
]);
// results: [{ status: 'fulfilled', value: ... }, { status: 'rejected', reason: ... }]

ES Module 模块系统

// math.js — 导出
export const PI = 3.14159;
export function add(a, b) { return a + b; }
export default class Calculator { /* ... */ }

// app.js — 导入
import Calculator, { PI, add } from './math.js';
import * as math from './math.js';

// 动态导入(按需加载)
async function loadChart() {
  const { Chart } = await import('./chart.js');
  return new Chart();
}

// 导出重命名
export { add as sum } from './math.js';

可选链和空值合并

// 可选链 ?. — 安全访问嵌套属性
const user = {
  profile: {
    address: {
      city: '北京'
    }
  }
};

// 传统方式
const city1 = user && user.profile && user.profile.address && user.profile.address.city;

// 可选链
const city2 = user?.profile?.address?.city; // '北京'
const zip = user?.profile?.address?.zip;     // undefined(不报错)

// 可选链调用方法
const result = user?.getName?.();

// 可选链访问数组
const first = user?.tags?.[0];

// 空值合并 ?? — 仅在 null/undefined 时使用默认值
const name = null ?? '默认名';     // '默认名'
const name2 = '' ?? '默认名';      // ''(空字符串不是null/undefined)
const name3 = 0 ?? '默认名';       // 0(0不是null/undefined)

// 对比 || 运算符
const name4 = '' || '默认名';      // '默认名'(空字符串是 falsy)
const name5 = 0 || '默认名';       // '默认名'(0是 falsy)

Map 和 Set

// Map — 键值对集合,键可以是任意类型
const map = new Map();
map.set('name', '张三');
map.set(42, '数字键');
map.set(true, '布尔键');

map.get('name');  // '张三'
map.has(42);      // true
map.size;         // 3
map.delete(true);

// 遍历
for (const [key, value] of map) {
  console.log(key, value);
}

// Set — 唯一值集合
const set = new Set([1, 2, 3, 2, 1]);
set.size;  // 3
set.has(2); // true

// 去重
const arr = [1, 1, 2, 3, 3, 4];
const unique = [...new Set(arr)]; // [1, 2, 3, 4]

// 集合运算
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
const union = new Set([...a, ...b]);          // 并集
const intersection = new Set([...a].filter(x => b.has(x))); // 交集
const difference = new Set([...a].filter(x => !b.has(x)));  // 差集

其他实用特性

Object.entries / Object.keys / Object.values

const user = { name: '张三', age: 25, city: '北京' };
Object.keys(user);    // ['name', 'age', 'city']
Object.values(user);  // ['张三', 25, '北京']
Object.entries(user); // [['name', '张三'], ['age', 25], ['city', '北京']]

// 转换为 Map
const map = new Map(Object.entries(user));

Array 方法增强

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

// find / findIndex
const found = numbers.find(n => n > 3);      // 4
const index = numbers.findIndex(n => n > 3); // 3

// includes
numbers.includes(3); // true

// flat / flatMap
const nested = [[1, 2], [3, [4, 5]]];
nested.flat();     // [1, 2, 3, [4, 5]]
nested.flat(Infinity); // [1, 2, 3, 4, 5]

const sentences = ['Hello World', 'Good Morning'];
sentences.flatMap(s => s.split(' '));
// ['Hello', 'World', 'Good', 'Morning']

对象合并

// Object.assign(浅合并)
const target = { a: 1, b: 2 };
Object.assign(target, { b: 3, c: 4 });
// target: { a: 1, b: 3, c: 4 }

// 展开运算符(推荐)
const merged = { ...target, b: 3, c: 4 };

// structuredClone(深拷贝)
const original = { nested: { value: 1 } };
const deepCopy = structuredClone(original);

总结:现代JavaScript最佳实践

  1. 使用 const 优先,let 次之,避免 var
  2. 使用箭头函数进行回调,传统函数用于方法定义
  3. 使用模板字符串替代字符串拼接
  4. 使用解构赋值简化数据提取
  5. 使用 async/await 替代 Promise 链
  6. 使用 ES Module 组织代码
  7. 使用可选链 ?. 和空值合并 ??
  8. 使用 Map/Set 替代普通对象作为集合
  9. 使用 ...rest/spread 简化参数和展开操作