普通视图

发现新文章,点击刷新页面。
昨天 — 2025年6月8日首页

ES6~ES13 新特性

作者 梨子同志
2025年6月8日 11:01

一、ES6 (ES2015) 重要新特性

1. 模板字符串 (Template Literals)

  • 使用反引号(``)定义字符串
  • 支持多行字符串和插值表达式
// 基本用法
const name = 'Alice';
const greeting = `Hello, ${name}!`; // "Hello, Alice!"

// 多行字符串
const multiLine = `
  This is 
  a multi-line
  string
`;

// 标签模板
function tag(strings, ...values) {
  console.log(strings); // ["Hello ", "!"]
  console.log(values);  // ["Alice"]
  return strings[0] + values[0].toUpperCase() + strings[1];
}
const result = tag`Hello ${name}!`; // "Hello ALICE!"

2. 箭头函数 (Arrow Functions)

  • 更简洁的函数语法
  • 自动绑定词法作用域的 this
// 基本语法
const add = (a, b) => a + b;

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

// 无参数需要括号
const sayHi = () => console.log('Hi');

// 返回对象需要用括号包裹
const makePerson = (name, age) => ({ name, age });

// this 绑定示例
const counter = {
  count: 0,
  increment: function() {
    setInterval(() => {
      this.count++; // 正确绑定this
      console.log(this.count);
    }, 1000);
  }
};

3. 函数参数增强

默认参数 (Default Parameters)

function greet(name = 'Guest', greeting = 'Hello') {
  return `${greeting}, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"

剩余参数 (Rest Parameters)

function sum(...numbers) {
  return numbers.reduce((total, num) => total + num, 0);
}
console.log(sum(1, 2, 3)); // 6

4. 解构赋值 (Destructuring Assignment)

对象解构

const person = { name: 'John', age: 30, city: 'New York' };
const { name, age } = person;
console.log(name, age); // "John" 30

// 别名
const { name: personName } = person;
console.log(personName); // "John"

// 默认值
const { country = 'USA' } = person;
console.log(country); // "USA"

数组解构

const numbers = [1, 2, 3];
const [first, second] = numbers;
console.log(first, second); // 1 2

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

// 剩余元素
const [head, ...tail] = numbers;
console.log(tail); // [2, 3]

5. 对象字面量增强

属性简写

const name = 'Alice';
const age = 25;
const person = { name, age }; // { name: 'Alice', age: 25 }

方法简写

const obj = {
  // 传统写法
  sayHello: function() {},
  
  // 简写写法
  sayHi() {},
  
  // 箭头函数
  sayBye: () => {}
};

计算属性名

const propKey = 'name';
const obj = {
  [propKey]: 'John',
  [`get${propKey}`]() {
    return this[propKey];
  }
};
console.log(obj.getName()); // "John"

二、ES2016 (ES7) 新特性

1. 数组 includes() 方法

const arr = [1, 2, 3];
console.log(arr.includes(2)); // true
console.log(arr.includes(4)); // false

// 与indexOf的区别
console.log([NaN].includes(NaN)); // true
console.log([NaN].indexOf(NaN) !== -1); // false

2. 指数运算符 (**)

console.log(2 ** 3); // 8
console.log(Math.pow(2, 3)); // 8

// 与Math.pow()的区别
console.log((-2) ** 3); // -8
console.log(Math.pow(-2, 3)); // -8

三、ES2017 (ES8) 新特性

1. async/await

async function fetchData() {
  try {
    const response = await fetch('https://api.example.com/data');
    const data = await response.json();
    console.log(data);
  } catch (error) {
    console.error('Error:', error);
  }
}

2. Object.values() / Object.entries()

const obj = { a: 1, b: 2, c: 3 };

console.log(Object.values(obj)); // [1, 2, 3]
console.log(Object.entries(obj)); // [["a", 1], ["b", 2], ["c", 3]]

// 与for...in的区别
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key}: ${value}`);
}

3. 字符串填充方法

console.log('5'.padStart(2, '0')); // "05"
console.log('12'.padStart(2, '0')); // "12"
console.log('abc'.padEnd(5, '*')); // "abc**"

4. 函数参数列表尾逗号

function foo(
  param1,
  param2, // 允许尾逗号
) {
  // ...
}

四、ES2018 (ES9) 新特性

1. 对象扩展运算符

const obj1 = { a: 1, b: 2 };
const obj2 = { ...obj1, c: 3 }; // { a: 1, b: 2, c: 3 }

// 覆盖属性
const obj3 = { ...obj1, a: 3 }; // { a: 3, b: 2 }

// 浅拷贝
const obj4 = { ...obj1 };
console.log(obj4 === obj1); // false

2. Promise.finally()

fetch('https://api.example.com/data')
  .then(response => response.json())
  .then(data => console.log(data))
  .catch(error => console.error(error))
  .finally(() => console.log('Request completed'));

3. 正则表达式增强

命名捕获组

const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const match = re.exec('2023-05-15');
console.log(match.groups.year); // "2023"

dotAll 模式 (s 标志)

const re = /foo.bar/s;
console.log(re.test('foo\nbar')); // true

后行断言

console.log(/(?<=\$)\d+/.exec('$100')[0]); // "100" (匹配$后的数字)
console.log(/(?<!\$)\d+/.exec('€100')[0]); // "100" (匹配前面不是$的数字)

五、ES2019 (ES10) 新特性

1. Array.flat() / Array.flatMap()

const arr = [1, [2, [3]]];
console.log(arr.flat()); // [1, 2, [3]]
console.log(arr.flat(2)); // [1, 2, 3]

const sentences = ["Hello world", "Goodbye universe"];
const words = sentences.flatMap(sentence => sentence.split(' '));
console.log(words); // ["Hello", "world", "Goodbye", "universe"]

2. Object.fromEntries()

const entries = [['name', 'John'], ['age', 30]];
const obj = Object.fromEntries(entries);
console.log(obj); // { name: "John", age: 30 }

// 与Object.entries()配合使用
const newObj = Object.fromEntries(
  Object.entries(obj).map(([key, value]) => [key, String(value)])
);

3. String.trimStart() / String.trimEnd()

const str = '   hello   ';
console.log(str.trimStart()); // "hello   "
console.log(str.trimEnd());   // "   hello"

4. 可选的 catch 绑定

try {
  // ...
} catch { // 不需要指定error参数
  console.log('An error occurred');
}

六、ES2020 (ES11) 新特性

1. 可选链操作符 (?.)

const user = { profile: { name: 'John' } };

// 传统写法
const name = user && user.profile && user.profile.name;

// 可选链写法
const name = user?.profile?.name;

// 函数调用
user.sayHi?.(); // 如果sayHi存在则调用

// 数组访问
const firstItem = arr?.[0];

2. 空值合并运算符 (??)

const value = null ?? 'default'; // "default"
const value2 = 0 ?? 'default';   // 0 (与||不同)

// 与||的区别
console.log(0 || 'default'); // "default"
console.log('' || 'default'); // "default"
console.log(false || 'default'); // "default"

3. 动态导入 (Dynamic Import)

// 按需加载模块
button.addEventListener('click', async () => {
  const module = await import('./module.js');
  module.doSomething();
});

4. BigInt

const bigNum = 9007199254740991n; // 字面量加n
const anotherBigNum = BigInt("9007199254740991");

console.log(bigNum + anotherBigNum); // 18014398509481982n

// 不能与Number混合运算
console.log(bigNum + 1); // TypeError

七、ES2021 (ES12) 新特性

1. 逻辑赋值运算符

// 逻辑或赋值
let a = false;
a ||= true; // a = a || true

// 逻辑与赋值
let b = true;
b &&= false; // b = b && false

// 空值合并赋值
let c = null;
c ??= 'default'; // c = c ?? 'default'

2. String.replaceAll()

const str = 'hello world';
console.log(str.replaceAll('l', 'x')); // "hexxo worxd"

// 之前需要正则表达式
console.log(str.replace(/l/g, 'x')); // "hexxo worxd"

3. Promise.any()

const promises = [
  Promise.reject('Error 1'),
  Promise.resolve('Success 1'),
  Promise.reject('Error 2')
];

Promise.any(promises)
  .then(result => console.log(result)) // "Success 1"
  .catch(errors => console.log(errors));

4. 数字分隔符

const billion = 1_000_000_000; // 更易读
console.log(billion === 1000000000); // true

八、ES2022 (ES13) 新特性

1. 类字段声明

class Counter {
  count = 0; // 实例字段
  
  increment = () => { // 箭头函数方法
    this.count++;
  };
  
  static version = '1.0'; // 静态字段
}

2. 私有字段和方法

class Person {
  #name; // 私有字段
  
  constructor(name) {
    this.#name = name;
  }
  
  #privateMethod() { // 私有方法
    return `Hello, ${this.#name}`;
  }
  
  greet() {
    console.log(this.#privateMethod());
  }
}

const person = new Person('John');
person.greet(); // "Hello, John"
// person.#name; // SyntaxError

3. 静态初始化块

class Translator {
  static translations = {
    yes: 'ja',
    no: 'nein'
  };
  
  static englishWords = [];
  static germanWords = [];
  
  static { // 静态初始化块
    for (const [english, german] of Object.entries(this.translations)) {
      this.englishWords.push(english);
      this.germanWords.push(german);
    }
  }
}

4. 顶层 await

// 在模块顶层使用await
const data = await fetchData();
console.log(data);

// 之前需要包装在async函数中
(async () => {
  const data = await fetchData();
  console.log(data);
})();

九、ES2023 (ES14) 新特性

1. Array.findLast() / Array.findLastIndex()

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

console.log(numbers.findLast(n => n > 2)); // 3 (最后一个满足条件的元素)
console.log(numbers.findLastIndex(n => n > 2)); // 4 (索引)

2. Hashbang 语法标准化

#!/usr/bin/env node
// 现在ES标准正式支持Shebang语法
console.log('Hello from CLI tool');

3. WeakMap 支持 Symbol 键

const weakMap = new WeakMap();
const key = Symbol('privateData');
const obj = {};

weakMap.set(key, 'secret');
weakMap.set(obj, 'other secret');

console.log(weakMap.get(key)); // "secret"
console.log(weakMap.get(obj)); // "other secret"

十、总结与应用建议

1. 版本特性快速参考

版本 重要特性
ES6 类、模块、箭头函数、模板字符串、解构、Promise、let/const
ES2016 includes()、指数运算符
ES2017 async/await、Object.values/entries、字符串填充
ES2018 对象扩展运算符、Promise.finally、正则增强
ES2019 Array.flat/flatMap、Object.fromEntries、trimStart/End
ES2020 可选链、空值合并、动态导入、BigInt
ES2021 逻辑赋值、replaceAll、Promise.any、数字分隔符
ES2022 类字段、私有方法、静态块、顶层await
ES2023 Array.findLast、Hashbang、WeakMap Symbol键

2. 现代JavaScript开发建议

  1. 优先使用新语法:如箭头函数、模板字符串、解构赋值等
  2. 渐进式采用:根据项目环境逐步引入新特性
  3. 关注兼容性:使用Babel等工具确保代码兼容性
  4. 代码可读性:合理使用新特性提升代码可读性而非炫技
  5. 团队一致性:制定团队编码规范统一新特性的使用方式

3. 学习资源推荐

  1. 官方文档ECMAScript规范
  2. 兼容性查询Can I use
  3. 实践教程现代JavaScript教程
  4. 新特性演示ES6+示例
❌
❌