ES2015-ES2025 新特性完全指南

0 阅读23分钟

ES2015 (ES6) - 基础特性

ES2015 是 JavaScript 历史上最重要的版本更新,引入了现代 JavaScript 的核心概念,彻底改变了 JavaScript 的编程范式。

它奠定了现代前端开发的基础,是从传统 JavaScript 向现代 JavaScript 转变的分水岭。

1. let 和 const

let:块级作用域变量声明,避免变量提升和重复声明。 const:声明常量,赋值后不可更改。

// let 示例
let x = 1;
{
  let x = 2; // 不同的块级作用域
  console.log(x); // 2
}
console.log(x); // 1

// const 示例
const PI = 3.14159;
const obj = { name: 'John' };
obj.name = 'Jane'; // 可以修改对象属性
// obj = {}; // 错误:不能重新赋值

2. 箭头函数 (Arrow Functions)

简洁的函数写法,自动绑定外部 this。

// 基本语法
const add = (a, b) => a + b;

// 多行函数体
const multiply = (a, b) => {
  const result = a * b;
  return result;
};

// this 绑定示例
class Counter {
  constructor() {
    this.count = 0;
  }
  
  start() {
    setInterval(() => {
      this.count++; // this 正确绑定到 Counter 实例
      console.log(this.count);
    }, 1000);
  }
}

3. 模板字符串 (Template Literals)

使用反引号 ``,支持多行和变量插值。

// 基本插值
const name = 'World';
const greeting = `Hello ${name}!`;

// 多行字符串
const html = `
  <div>
    <h1>${title}</h1>
    <p>${content}</p>
  </div>
`;

// 标签模板
function highlight(strings, ...values) {
  return strings.reduce((result, str, i) => 
    result + str + (values[i] ? `<span>${values[i]}</span>` : ''), '');
}
const highlighted = highlight`Hello ${name}!`;

4. 解构赋值 (Destructuring)

快速从数组或对象中提取值。

// 数组解构
const [a, b, ...rest] = [1, 2, 3, 4, 5];
console.log(a, b, rest); // 1, 2, [3, 4, 5]

// 对象解构
const { name, age: userAge, ...otherProps } = { 
  name: 'Tom', 
  age: 18, 
  city: 'New York' 
};
console.log(name, userAge, otherProps); // 'Tom', 18, { city: 'New York' }

// 默认值
const { title = 'Untitled' } = {};
console.log(title); // 'Untitled'

// 嵌套解构
const { user: { name: userName } } = { user: { name: 'John' } };
console.log(userName); // 'John'

5. 默认参数、剩余参数、扩展运算符

// 默认参数
function greet(name = 'Guest') {
  console.log(`Hello, ${name}!`);
}

// 剩余参数
function sum(...numbers) {
  return numbers.reduce((total, n) => total + n, 0);
}

// 扩展运算符
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5];

// for...of
for (const char of 'hello') {
  console.log(char);
}

ES2015 (ES6) - 高级特性

这些高级特性为 JavaScript 带来了面向对象编程、函数式编程和元编程的能力,使 JavaScript 成为一门真正现代化的编程语言。

1. 类和模块 (Classes & Modules)

更接近传统面向对象写法,支持继承和模块化导入导出。

// 类定义
class Person {
  constructor(name) {
    this.name = name;
  }
  
  sayHello() {
    console.log(`Hello, ${this.name}!`);
  }
  
  static create(name) {
    return new Person(name);
  }
}

// 继承
class Employee extends Person {
  constructor(name, role) {
    super(name);
    this.role = role;
  }
  
  sayHello() {
    super.sayHello();
    console.log(`I am a ${this.role}`);
  }
}

// 模块导出
export class User extends Person {}
export const helper = () => {};

// 模块导入
import { User, helper } from './user.js';

2. Promise

统一异步编程接口,支持链式调用。

// 基本用法
const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('done');
  }, 1000);
});

promise
  .then(result => console.log(result))
  .catch(error => console.error(error));

// 链式调用
fetch('api/data')
  .then(response => response.json())
  .then(data => processData(data))
  .catch(error => handleError(error));

// Promise.all
Promise.all([
  fetch('api/users'),
  fetch('api/posts')
])
  .then(([users, posts]) => {
    // 处理所有请求结果
  });

// Promise.race
Promise.race([
  fetch('api/data'),
  new Promise((_, reject) => 
    setTimeout(() => reject(new Error('Timeout')), 5000)
  )
]);

3. 生成器和迭代器 (Generators & Iterators)

生成器函数可暂停和恢复执行,适合异步流程和自定义迭代。

// 基本生成器
function* generator() {
  yield 1;
  yield 2;
  yield 3;
}

for (const value of generator()) {
  console.log(value);
}

// 异步生成器
async function* asyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
}

// 自定义迭代器
const iterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
    yield 3;
  }
};

for (const value of iterable) {
  console.log(value);
}

4. Map/Set/WeakMap/WeakSet

新的集合类型,支持任意类型键和值。

// Map
const map = new Map();
map.set('key', 'value');
map.set(1, 'number');
map.set({}, 'object');

// Set
const set = new Set([1, 2, 3, 3, 4]); // 自动去重
console.log([...set]); // [1, 2, 3, 4]

// WeakMap
const weakMap = new WeakMap();
const obj = {};
weakMap.set(obj, 'value');
// 当 obj 被垃圾回收时,对应的值也会被回收

// WeakSet
const weakSet = new WeakSet();
weakSet.add(obj);
// 当 obj 被垃圾回收时,会自动从 weakSet 中移除

5. Symbol

唯一值的基本类型,常用于对象属性名避免冲突。

// 创建 Symbol
const sym1 = Symbol('description');
const sym2 = Symbol('description');
console.log(sym1 === sym2); // false

// 作为对象属性
const obj = {
  [sym1]: 'value'
};

// 内置 Symbol
class MyArray extends Array {
  static get [Symbol.species]() {
    return Array;
  }
}

// Symbol.iterator
const iterable = {
  *[Symbol.iterator]() {
    yield 1;
    yield 2;
  }
};

6. Proxy & Reflect

元编程能力,拦截对象操作。

// Proxy 示例
const target = { foo: 'bar' };
const handler = {
  get(obj, prop) {
    return prop in obj ? obj[prop] : 'default';
  },
  set(obj, prop, value) {
    if (typeof value === 'string') {
      obj[prop] = value;
      return true;
    }
    return false;
  }
};

const proxy = new Proxy(target, handler);
console.log(proxy.foo); // 'bar'
console.log(proxy.abc); // 'default'

// Reflect 示例
const obj = { x: 1, y: 2 };
Reflect.set(obj, 'z', 3);
console.log(Reflect.get(obj, 'z')); // 3

7. 字符串、数组、对象新方法

// 字符串新方法
'hello'.includes('ell'); // true
'hello'.startsWith('he'); // true
'hello'.endsWith('lo'); // true
'hello'.repeat(3); // 'hellohellohello'

// 数组新方法
[1, 2, 3].find(x => x > 1); // 2
[1, 2, 3].findIndex(x => x > 1); // 1
Array.from('hello'); // ['h', 'e', 'l', 'l', 'o']
Array.of(1, 2, 3); // [1, 2, 3]

// 对象新方法
Object.assign({}, { a: 1 }, { b: 2 }); // { a: 1, b: 2 }
Object.is(NaN, NaN); // true
Object.setPrototypeOf(obj, proto);

ES2016 (ES7)

ES2016 是一个小版本更新,引入了两个实用的特性。虽然特性不多,但 Array.includes() 成为了日常开发中的常用方法,指数运算符则提供了更简洁的数学运算语法。

1. Array.prototype.includes()

判断数组是否包含某元素,支持 NaN。

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

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

2. 指数运算符 (Exponentiation Operator)

2 ** 3 等价于 Math.pow(2, 3)

const result = 2 ** 3; // 8
const square = 2 ** 2; // 4
const cube = 2 ** 3; // 8

// 与 Math.pow 的区别
console.log(2 ** 3 ** 2); // 512 (右结合)
console.log(Math.pow(2, Math.pow(3, 2))); // 512

ES2017 (ES8)

ES2017 带来了革命性的 async/await 语法,彻底改变了 JavaScript 异步编程的写法,使异步代码看起来像同步代码一样清晰。同时增强了对象操作能力,为现代 JavaScript 开发奠定了重要基础。

1. async/await

基于 Promise 的异步编程语法糖。

// 基本用法
async function fetchData() {
  try {
    const response = await fetch('api/data');
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('Error:', error);
  }
}

// 并行请求
async function fetchMultiple() {
  const [users, posts] = await Promise.all([
    fetch('api/users').then(r => r.json()),
    fetch('api/posts').then(r => r.json())
  ]);
  return { users, posts };
}

// 异步迭代
async function* asyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
}

2. Object.values() 和 Object.entries()

快速获取对象的值数组或键值对数组。

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

// Object.values
console.log(Object.values(obj)); // [1, 2, 3]

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

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

3. 字符串补全(String padding)

字符串补全。

// padStart
'x'.padStart(5, 'a'); // 'aaaax'
'123'.padStart(5, '0'); // '00123'

// padEnd
'x'.padEnd(5, 'a'); // 'xaaaa'
'123'.padEnd(5, '0'); // '12300'

// 实际应用
function formatNumber(num) {
  return num.toString().padStart(2, '0');
}
console.log(formatNumber(5)); // '05'

4. Object.getOwnPropertyDescriptors

获取对象所有属性描述符。

const obj = {
  get name() {
    return 'John';
  }
};

const descriptors = Object.getOwnPropertyDescriptors(obj);
console.log(descriptors.name.get); // [Function: get name]

// 用于克隆对象
const clone = Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);

5. SharedArrayBuffer & Atomics

多线程共享内存和原子操作,适合高性能场景。

// 创建共享内存
const buffer = new SharedArrayBuffer(1024);
const view = new Int32Array(buffer);

// 原子操作
Atomics.store(view, 0, 123);
const value = Atomics.load(view, 0);
Atomics.add(view, 0, 1);

ES2018 (ES9)

ES2018 进一步完善了异步编程能力,引入了异步迭代,同时增强了对象操作和正则表达式功能。Rest/Spread 属性的引入使对象操作更加灵活,成为现代 JavaScript 开发的重要工具。

1. 异步迭代 (Async Iteration)

支持 for await...of 语法,异步遍历。

// 异步生成器
async function* asyncGenerator() {
  yield await Promise.resolve(1);
  yield await Promise.resolve(2);
  yield await Promise.resolve(3);
}

// 异步迭代
(async () => {
  for await (const value of asyncGenerator()) {
    console.log(value);
  }
})();

// 实际应用:读取文件流
async function processFile(file) {
  for await (const chunk of file.stream()) {
    processChunk(chunk);
  }
}

2. Rest/Spread 属性

对象剩余/扩展属性。

// 对象解构
const { x, y, ...rest } = { x: 1, y: 2, a: 3, b: 4 };
console.log(rest); // { a: 3, b: 4 }

// 对象合并
const obj1 = { foo: 'bar', x: 42 };
const obj2 = { foo: 'baz', y: 13 };
const clonedObj = { ...obj1 };
const mergedObj = { ...obj1, ...obj2 };

3. Promise.finally()

无论成功失败都会执行。

fetch('api/data')
  .then(response => response.json())
  .then(data => processData(data))
  .catch(error => handleError(error))
  .finally(() => {
    // 清理工作
    cleanup();
  });

4. 正则增强

命名捕获组、s 修饰符、后行断言等。

// 命名捕获组
const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const result = re.exec('2023-05-01');
console.log(result.groups.year); // '2023'

// s 修饰符(dotAll)
const re2 = /hello.world/s;
console.log(re2.test('hello\nworld')); // true

// 后行断言
const re3 = /(?<=\$)\d+/;
console.log(re3.exec('$123')); // ['123']

ES2019 (ES10)

ES2019 专注于提升开发体验,引入了实用的数组扁平化方法和对象转换工具。这些特性虽然看似简单,但在日常开发中极大地简化了常见操作,提高了代码的可读性和简洁性。

1. Array.prototype.flat() 和 flatMap()

数组扁平化和映射。

// flat
[1, 2, [3, 4]].flat(); // [1, 2, 3, 4]
[1, 2, [3, 4, [5, 6]]].flat(2); // [1, 2, 3, 4, 5, 6]

// flatMap
[1, 2, 3].flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]

// 实际应用
const sentences = ['Hello world', 'How are you'];
const words = sentences.flatMap(s => s.split(' '));

2. Object.fromEntries()

键值对数组转对象。

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

// 实际应用:URL 参数解析
const params = new URLSearchParams('name=John&age=30');
const paramsObj = Object.fromEntries(params);

3. String.trimStart/trimEnd

去除字符串首尾空白。

// trimStart
'  hello '.trimStart(); // 'hello '

// trimEnd
'  hello '.trimEnd(); // '  hello'

// 实际应用
function formatName(name) {
  return name.trimStart().trimEnd();
}

4. 可选 catch 绑定

catch 可以省略 error 参数。

try {
  // 可能抛出错误的代码
} catch {
  // 不需要使用 error 参数
  console.log('An error occurred');
}

ES2020 (ES11)

ES2020 是近年来最具影响力的版本之一,可选链和空值合并操作符彻底改变了 JavaScript 中处理不确定数据的方式,大幅减少了防御性编程代码。BigInt 和动态 import 则为特定场景提供了强大的新能力。

1. 可选链操作符 (Optional Chaining)

安全访问多层嵌套属性。

// 对象属性访问
const value = obj?.prop?.nested?.value;

// 数组元素访问
const first = arr?.[0];

// 函数调用
const result = obj.method?.();

// 实际应用
function getCity(user) {
  return user?.address?.city ?? 'Unknown';
}

2. 空值合并操作符 (Nullish Coalescing)

只在 null 或 undefined 时使用默认值。

// 基本用法
const value = null ?? 'default';
const count = 0 ?? 42; // 0

// 与 || 的区别
const value1 = 0 || 42; // 42
const value2 = 0 ?? 42; // 0

// 实际应用
function greet(name) {
  return `Hello, ${name ?? 'Guest'}!`;
}

3. BigInt

支持任意精度整数。

// 创建 BigInt
const bigInt = 9007199254740991n;
const bigInt2 = BigInt(9007199254740991);

// 运算
const sum = bigInt + 1n;
const product = bigInt * 2n;

// 实际应用:大数计算
function calculateFactorial(n) {
  let result = 1n;
  for (let i = 2n; i <= n; i++) {
    result *= i;
  }
  return result;
}

4. Promise.allSettled()

所有 Promise 完成后返回每个结果。

// 基本用法
Promise.allSettled([
  Promise.resolve(1),
  Promise.reject('error'),
  Promise.resolve(3)
]).then(results => {
  console.log(results);
  // [
  //   { status: 'fulfilled', value: 1 },
  //   { status: 'rejected', reason: 'error' },
  //   { status: 'fulfilled', value: 3 }
  // ]
});

// 实际应用:批量请求
async function fetchAll(urls) {
  const results = await Promise.allSettled(
    urls.map(url => fetch(url))
  );
  return results.map(result => 
    result.status === 'fulfilled' ? result.value : null
  );
}

5. globalThis

统一全局对象。

// 浏览器环境
console.log(globalThis === window); // true

// Node.js 环境
console.log(globalThis === global); // true

// 实际应用
function getGlobal() {
  return globalThis;
}

6. 动态 import

按需异步加载模块。

// 基本用法
const module = await import('./module.js');

// 条件导入
if (condition) {
  const { default: Component } = await import('./Component.js');
}

// 实际应用:路由懒加载
const routes = [
  {
    path: '/about',
    component: () => import('./About.js')
  }
];

ES2021 (ES12)

ES2021 继续完善语言的实用性,replaceAll() 解决了长期存在的字符串替换痛点,逻辑赋值运算符简化了常见的赋值模式,Promise.any() 丰富了异步编程的选择。

1. String.prototype.replaceAll()

全部替换字符串。

// 基本用法
'hello world'.replaceAll('o', '0'); // 'hell0 w0rld'

// 与 replace 的区别
'hello world'.replace(/o/g, '0'); // 需要正则
'hello world'.replaceAll('o', '0'); // 直接使用字符串

// 实际应用
function sanitizeHTML(str) {
  return str.replaceAll('<', '&lt;').replaceAll('>', '&gt;');
}

2. Promise.any()

只要有一个 Promise 成功就返回。

// 基本用法
Promise.any([
  Promise.reject('error1'),
  Promise.resolve('success'),
  Promise.reject('error2')
]).then(result => {
  console.log(result); // 'success'
});

// 实际应用:多源数据获取
async function fetchFromAnySource(urls) {
  try {
    const result = await Promise.any(
      urls.map(url => fetch(url).then(r => r.json()))
    );
    return result;
  } catch (error) {
    console.error('All requests failed');
  }
}

3. 逻辑赋值运算符 (Logical Assignment)

简化赋值逻辑。

// 基本用法
let x = 1;
x ||= 2; // x = x || 2
x &&= 3; // x = x && 3
x ??= 4; // x = x ?? 4

// 实际应用
function updateConfig(config) {
  config.timeout ??= 1000;
  config.retries ||= 3;
  return config;
}

4. WeakRef & FinalizationRegistry

弱引用和终结器,适合缓存等场景。

// WeakRef
const cache = new Map();
function getCachedData(key) {
  let ref = cache.get(key);
  if (ref) {
    const value = ref.deref();
    if (value) return value;
  }
  const value = computeExpensiveValue();
  cache.set(key, new WeakRef(value));
  return value;
}

// FinalizationRegistry
const registry = new FinalizationRegistry(heldValue => {
  console.log(`Cleaning up: ${heldValue}`);
});

registry.register(target, 'some value');

ES2022 (ES13)

ES2022 显著增强了类的功能,引入了私有字段和静态字段,使 JavaScript 的面向对象编程更加完善。

顶层 await 简化了模块的异步初始化,这些特性让 JavaScript 在大型应用开发中更加成熟。

1. Class 字段声明 (Class Fields)

类字段和私有字段。

class Person {
  // 公共字段
  name = 'John';
  
  // 私有字段
  #privateField = 'private';
  
  // 静态字段
  static count = 0;
  
  // 私有静态字段
  static #privateStaticField = 'private static';
  
  constructor() {
    Person.count++;
  }
  
  getPrivateField() {
    return this.#privateField;
  }
}

2. Top-level await

模块顶层直接使用 await

// 基本用法
const response = await fetch('api/data');
const data = await response.json();

// 实际应用:模块初始化
const config = await loadConfig();
export const api = createAPI(config);

3. Object.hasOwn()

判断对象自身属性。

// 基本用法
const obj = { prop: 'value' };
console.log(Object.hasOwn(obj, 'prop')); // true
console.log(Object.hasOwn(obj, 'toString')); // false

// 与 hasOwnProperty 的区别
const obj2 = Object.create(null);
obj2.prop = 'value';
console.log(obj2.hasOwnProperty('prop')); // 错误
console.log(Object.hasOwn(obj2, 'prop')); // true

4. Error cause

错误链路。

// 基本用法
try {
  throw new Error('fail', { cause: 'reason' });
} catch (e) {
  console.log(e.cause); // 'reason'
}

// 实际应用:错误传播
async function fetchData() {
  try {
    const response = await fetch('api/data');
    if (!response.ok) {
      throw new Error('HTTP error', { 
        cause: { status: response.status }
      });
    }
    return response.json();
  } catch (error) {
    throw new Error('Failed to fetch data', { cause: error });
  }
}

ES2023 (ES14)

ES2023 专注于填补功能空白,findLast/findLastIndex 补全了数组查找方法,WeakMap/WeakSet 对 Symbol 的支持增强了元编程能力。虽然特性不多,但都是实用的增强。

1. Array.prototype.findLast / findLastIndex

从数组末尾查找满足条件的元素或索引。

// 基本用法
const arr = [1, 2, 3, 4, 5];
arr.findLast(x => x % 2 === 0); // 4
arr.findLastIndex(x => x % 2 === 0); // 3

// 实际应用:查找最后一个匹配项
const logs = [
  { id: 1, status: 'success' },
  { id: 2, status: 'error' },
  { id: 3, status: 'success' }
];
const lastSuccess = logs.findLast(log => log.status === 'success');

2. Array.prototype.toSorted / toReversed / toSpliced

不可变数组操作方法。

  • 原有数组方法会修改原数组,不符合函数式编程理念
  • 需要手动复制数组再操作,代码冗长
  • 缺乏标准的不可变数组操作方法
const original = [3, 1, 4, 1, 5];

// 不可变排序
const sorted = original.toSorted();
console.log(original); // [3, 1, 4, 1, 5] (未改变)
console.log(sorted);   // [1, 1, 3, 4, 5]

// 自定义排序
const people = [
  { name: 'Alice', age: 30 },
  { name: 'Bob', age: 25 },
  { name: 'Charlie', age: 35 }
];
const sortedByAge = people.toSorted((a, b) => a.age - b.age);

// 不可变反转
const reversed = original.toReversed();
console.log(reversed); // [5, 1, 4, 1, 3]

// 不可变拼接
const spliced = original.toSpliced(1, 2, 'a', 'b');
console.log(spliced); // [3, 'a', 'b', 1, 5]

// 组合使用
const data = [10, 5, 8, 3, 1];
const processed = data
  .toSorted((a, b) => b - a)  // 降序排序
  .toSpliced(0, 2)            // 移除前两个元素
  .toReversed();              // 反转
console.log(processed); // [3, 8]
console.log(data);      // [10, 5, 8, 3, 1] (原数组未变)

// 实际应用:状态管理
class TodoList {
  constructor(items = []) {
    this.items = items;
  }
  
  addItem(item) {
    return new TodoList(this.items.toSpliced(this.items.length, 0, item));
  }
  
  removeItem(index) {
    return new TodoList(this.items.toSpliced(index, 1));
  }
  
  sortByPriority() {
    return new TodoList(this.items.toSorted((a, b) => a.priority - b.priority));
  }
  
  reverse() {
    return new TodoList(this.items.toReversed());
  }
}

// 使用示例
const todos = new TodoList([
  { id: 1, text: 'Learn JavaScript', priority: 2 },
  { id: 2, text: 'Build app', priority: 1 },
  { id: 3, text: 'Deploy', priority: 3 }
]);

const sortedTodos = todos.sortByPriority();
const reversedTodos = sortedTodos.reverse();

2. WeakMap 和 WeakSet 支持 Symbol 键

// 基本用法
const weakMap = new WeakMap();
const symbol = Symbol('key');
weakMap.set(symbol, 'value');

// 实际应用:私有数据存储
const privateData = new WeakMap();
class MyClass {
  constructor() {
    privateData.set(this, {
      secret: 'value'
    });
  }
  
  getSecret() {
    return privateData.get(this).secret;
  }
}

4. Hashbang 支持

允许脚本以 #! 开头。

#!/usr/bin/env node
// 现在可以直接运行脚本
console.log('Hello, world!');

ES2024 (ES15)

ES2024 带来了多个重要的实用特性,Object.groupBy() 简化了数据分组操作,Promise.withResolvers() 提供了更灵活的 Promise 创建方式,RegExp v 标志增强了正则表达式能力,这些特性进一步提升了 JavaScript 的开发效率。

1. ArrayBuffer 和 SharedArrayBuffer 增强

支持可调整大小的 ArrayBuffer 和 SharedArrayBuffer,以及传输功能。

// 可调整大小的 ArrayBuffer
const buffer = new ArrayBuffer(8, { maxByteLength: 16 });
console.log(buffer.resizable); // true
console.log(buffer.maxByteLength); // 16

// 调整大小
buffer.resize(12);
console.log(buffer.byteLength); // 12

// 传输 ArrayBuffer
const newBuffer = buffer.transfer(20);
console.log(newBuffer.byteLength); // 20
console.log(buffer.detached); // true

// SharedArrayBuffer 也支持类似功能
const sharedBuffer = new SharedArrayBuffer(8, { maxByteLength: 16 });
sharedBuffer.grow(12); // 只能增长,不能缩小

2. Promise.withResolvers()

提供便捷的方式创建 Promise 及其 resolve/reject 函数。

// 基本用法
const { promise, resolve, reject } = Promise.withResolvers();

// 异步操作
setTimeout(() => {
  resolve('Success!');
}, 1000);

// 实际应用:创建可控制的 Promise
class AsyncQueue {
  constructor() {
    this.queue = [];
    this.processing = false;
  }
  
  add(task) {
    const { promise, resolve, reject } = Promise.withResolvers();
    this.queue.push({ task, resolve, reject });
    this.process();
    return promise;
  }
  
  async process() {
    if (this.processing) return;
    this.processing = true;
    
    while (this.queue.length > 0) {
      const { task, resolve, reject } = this.queue.shift();
      try {
        const result = await task();
        resolve(result);
      } catch (error) {
        reject(error);
      }
    }
    
    this.processing = false;
  }
}

3. Object.groupBy() 和 Map.groupBy()

根据回调函数结果对数据进行分组。

// Object.groupBy
const users = [
  { name: 'Alice', age: 25, department: 'Engineering' },
  { name: 'Bob', age: 30, department: 'Marketing' },
  { name: 'Charlie', age: 35, department: 'Engineering' }
];

const byDepartment = Object.groupBy(users, user => user.department);
// {
//   Engineering: [{ name: 'Alice', ... }, { name: 'Charlie', ... }],
//   Marketing: [{ name: 'Bob', ... }]
// }

// Map.groupBy
const ageGroups = Map.groupBy(users, user => {
  if (user.age < 30) return 'young';
  if (user.age < 40) return 'middle';
  return 'senior';
});
// Map {
//   'young' => [{ name: 'Alice', ... }],
//   'middle' => [{ name: 'Bob', ... }, { name: 'Charlie', ... }]
// }

// 实际应用:数据分析
function analyzeData(data) {
  const statusGroups = Object.groupBy(data, item => item.status);
  const summary = Object.entries(statusGroups).map(([status, items]) => ({
    status,
    count: items.length,
    total: items.reduce((sum, item) => sum + item.value, 0)
  }));
  return summary;
}

4. RegExp v 标志

增强正则表达式,支持集合表示法和字符串属性。

// 基本用法
const regex = /[\p{Script=Latin}&&[^\p{ASCII}]]/v;
console.log(regex.test('café')); // true

// 集合操作
const emojiRegex = /[\p{Emoji}--\p{ASCII}]/v;
console.log(emojiRegex.test('😀')); // true
console.log(emojiRegex.test('A')); // false

// 字符串字面量
const stringSetRegex = /["hello"|"world"]/v;
console.log(stringSetRegex.test('hello')); // true

// 实际应用:复杂字符匹配
function validateUsername(username) {
  // 允许字母、数字,但排除某些特殊字符
  const validChars = /^[\p{L}\p{N}--[\p{Emoji}\p{Symbol}]]+$/v;
  return validChars.test(username);
}

5. Atomics.waitAsync()

异步等待共享内存变化。

// 基本用法
const sharedBuffer = new SharedArrayBuffer(4);
const view = new Int32Array(sharedBuffer);

// 异步等待
const result = Atomics.waitAsync(view, 0, 0);
if (result.async) {
  result.value.then(() => {
    console.log('Value changed!');
  });
}

// 在另一个线程中
Atomics.store(view, 0, 1);
Atomics.notify(view, 0, 1);

// 实际应用:多线程协调
class SharedCounter {
  constructor() {
    this.buffer = new SharedArrayBuffer(4);
    this.view = new Int32Array(this.buffer);
  }
  
  async waitForValue(expectedValue) {
    const result = Atomics.waitAsync(this.view, 0, expectedValue);
    if (result.async) {
      await result.value;
    }
    return Atomics.load(this.view, 0);
  }
  
  increment() {
    Atomics.add(this.view, 0, 1);
    Atomics.notify(this.view, 0, 1);
  }
}

6. String.prototype.isWellFormed() 和 toWellFormed()

检查和确保字符串包含格式良好的 Unicode。

// 检查字符串是否格式良好
const wellFormed = 'Hello 👋';
const malformed = 'Hello \uD83D'; // 孤立的高代理项

console.log(wellFormed.isWellFormed()); // true
console.log(malformed.isWellFormed()); // false

// 修复格式错误的字符串
console.log(malformed.toWellFormed()); // 'Hello �'

// 实际应用:安全的字符串处理
function safeStringOperation(str) {
  if (!str.isWellFormed()) {
    console.warn('String contains malformed Unicode, fixing...');
    str = str.toWellFormed();
  }
  return str.toUpperCase();
}

// 用于 API 响应处理
function processApiResponse(response) {
  if (typeof response === 'string' && !response.isWellFormed()) {
    response = response.toWellFormed();
  }
  return JSON.parse(response);
}

ES2025 (ES16)

ES2025 引入了期待已久的 Iterator Helpers,为 JavaScript 带来了类似函数式编程语言的数据处理能力。Set 方法扩展完善了集合操作,Promise.try() 统一了同步异步处理,这些特性将显著改善数据处理和函数式编程的体验。

1. Iterator Helpers

为迭代器提供丰富的辅助方法,类似于数组方法。

// 基本用法
function* numbers() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
}

// 链式调用
const result = numbers()
  .filter(x => x % 2 === 0)
  .map(x => x * 2)
  .take(2)
  .toArray();
console.log(result); // [4, 8]

// 更多方法
const iterator = numbers();
iterator.drop(2).next().value; // 3
iterator.forEach(x => console.log(x));
iterator.some(x => x > 3); // true
iterator.every(x => x > 0); // true
iterator.find(x => x > 2); // 3
iterator.reduce((acc, x) => acc + x, 0); // 15

// 实际应用:数据流处理
function* fetchData() {
  for (let i = 1; i <= 100; i++) {
    yield fetch(`/api/data/${i}`).then(r => r.json());
  }
}

// 处理前10个有效数据
const validData = fetchData()
  .filter(async data => (await data).valid)
  .take(10)
  .toArray();

2. Set 方法扩展

为 Set 添加数学集合操作方法。

// 基本集合操作
const setA = new Set([1, 2, 3, 4]);
const setB = new Set([3, 4, 5, 6]);

// 并集
const union = setA.union(setB);
console.log([...union]); // [1, 2, 3, 4, 5, 6]

// 交集
const intersection = setA.intersection(setB);
console.log([...intersection]); // [3, 4]

// 差集
const difference = setA.difference(setB);
console.log([...difference]); // [1, 2]

// 对称差集
const symmetricDifference = setA.symmetricDifference(setB);
console.log([...symmetricDifference]); // [1, 2, 5, 6]

// 子集检查
console.log(new Set([1, 2]).isSubsetOf(setA)); // true
console.log(setA.isSupersetOf(new Set([1, 2]))); // true
console.log(setA.isDisjointFrom(new Set([7, 8]))); // true

// 实际应用:权限管理
class PermissionManager {
  constructor() {
    this.userPermissions = new Map();
    this.rolePermissions = new Map();
  }
  
  getUserEffectivePermissions(userId) {
    const userPerms = this.userPermissions.get(userId) || new Set();
    const rolePerms = this.getUserRolePermissions(userId);
    return userPerms.union(rolePerms);
  }
  
  hasConflictingPermissions(userId, requiredPerms) {
    const effectivePerms = this.getUserEffectivePermissions(userId);
    return !requiredPerms.isSubsetOf(effectivePerms);
  }
}

3. Promise.try()

安全地执行可能同步或异步的函数。

// 基本用法
const result = await Promise.try(() => {
  // 可能是同步或异步的函数
  return Math.random() > 0.5 ? 'sync' : Promise.resolve('async');
});

// 错误处理
const safeResult = await Promise.try(() => {
  if (Math.random() > 0.5) {
    throw new Error('Something went wrong');
  }
  return 'success';
}).catch(error => {
  console.error('Caught error:', error.message);
  return 'fallback';
});

// 实际应用:统一异步处理
class DataProcessor {
  async processData(processor, data) {
    return Promise.try(() => processor(data))
      .then(result => this.validateResult(result))
      .catch(error => this.handleError(error));
  }
  
  validateResult(result) {
    if (!result || typeof result !== 'object') {
      throw new Error('Invalid result format');
    }
    return result;
  }
  
  handleError(error) {
    console.error('Processing failed:', error);
    return { error: error.message, success: false };
  }
}

4. RegExp.escape()

安全地转义字符串用于正则表达式。

// 基本用法
const userInput = 'Hello (world) [test]';
const escaped = RegExp.escape(userInput);
console.log(escaped); // 'Hello \\(world\\) \\[test\\]'

// 创建安全的正则表达式
const regex = new RegExp(RegExp.escape(userInput));
console.log(regex.test('Hello (world) [test]')); // true

// 实际应用:搜索功能
class SearchEngine {
  search(text, query) {
    const escapedQuery = RegExp.escape(query);
    const regex = new RegExp(escapedQuery, 'gi');
    return text.match(regex) || [];
  }
  
  highlight(text, query) {
    const escapedQuery = RegExp.escape(query);
    const regex = new RegExp(`(${escapedQuery})`, 'gi');
    return text.replace(regex, '<mark>$1</mark>');
  }
  
  fuzzySearch(text, query) {
    const escapedQuery = RegExp.escape(query);
    const fuzzyPattern = escapedQuery.split('').join('.*?');
    const regex = new RegExp(fuzzyPattern, 'i');
    return regex.test(text);
  }
}

5. Float16Array 支持

添加半精度浮点数类型数组支持。

// 创建 Float16Array
const float16Array = new Float16Array(4);
float16Array[0] = 1.5;
float16Array[1] = 2.25;
float16Array[2] = 3.75;
float16Array[3] = 4.125;

console.log(float16Array); // Float16Array [1.5, 2.25, 3.75, 4.125]

// Math.f16round 方法
const rounded = Math.f16round(1.23456789);
console.log(rounded); // 1.234375 (半精度精度)

// DataView 支持
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
view.setFloat16(0, 1.5);
view.setFloat16(2, 2.5);
console.log(view.getFloat16(0)); // 1.5
console.log(view.getFloat16(2)); // 2.5

// 实际应用:图形处理
class ImageProcessor {
  constructor(width, height) {
    this.width = width;
    this.height = height;
    // 使用半精度浮点数节省内存
    this.pixels = new Float16Array(width * height * 4); // RGBA
  }
  
  setPixel(x, y, r, g, b, a = 1.0) {
    const index = (y * this.width + x) * 4;
    this.pixels[index] = Math.f16round(r);
    this.pixels[index + 1] = Math.f16round(g);
    this.pixels[index + 2] = Math.f16round(b);
    this.pixels[index + 3] = Math.f16round(a);
  }
  
  getPixel(x, y) {
    const index = (y * this.width + x) * 4;
    return {
      r: this.pixels[index],
      g: this.pixels[index + 1],
      b: this.pixels[index + 2],
      a: this.pixels[index + 3]
    };
  }
}

6. JSON 模块导入

支持直接导入 JSON 文件作为模块。

// 导入 JSON 文件
import config from './config.json' with { type: 'json' };
import data from './data.json' with { type: 'json' };

// 使用导入的数据
console.log(config.apiUrl);
console.log(data.users);

// 动态导入
const settings = await import('./settings.json', {
  with: { type: 'json' }
});

// 实际应用:配置管理
class ConfigManager {
  async loadConfig(environment) {
    const configPath = `./config/${environment}.json`;
    const config = await import(configPath, {
      with: { type: 'json' }
    });
    return config.default;
  }
  
  async loadLocalization(locale) {
    const localizationPath = `./i18n/${locale}.json`;
    try {
      const messages = await import(localizationPath, {
        with: { type: 'json' }
      });
      return messages.default;
    } catch (error) {
      // 回退到默认语言
      const fallback = await import('./i18n/en.json', {
        with: { type: 'json' }
      });
      return fallback.default;
    }
  }
}

7. 正则表达式修饰符

支持在正则表达式内部启用和禁用修饰符。

// 内联修饰符
const regex1 = /(?i)hello/; // 等价于 /hello/i
const regex2 = /(?-i:WORLD)/i; // 在大小写不敏感模式中,WORLD 部分大小写敏感

// 组合使用
const regex3 = /(?i)hello(?-i: WORLD)/;
console.log(regex3.test('Hello WORLD')); // true
console.log(regex3.test('Hello world')); // false

// 多行模式切换
const regex4 = /^(?m)start.*?(?-m)end$/;

// 实际应用:复杂文本解析
class TextParser {
  parseDocument(text) {
    // 标题:大小写不敏感
    // 内容:大小写敏感
    const headerRegex = /(?i)^#\s+(.+)$(?-i)/gm;
    const headers = [...text.matchAll(headerRegex)];
    
    return headers.map(match => ({
      title: match[1],
      level: match[0].indexOf('#') + 1
    }));
  }
  
  extractCodeBlocks(text) {
    // 在多行模式中匹配代码块
    const codeRegex = /(?s)```(?i)(\w+)?(?-i)\n(.*?)\n```/g;
    const blocks = [...text.matchAll(codeRegex)];
    
    return blocks.map(match => ({
      language: match[1] || 'text',
      code: match[2]
    }));
  }
}

草案特性合集 (Draft Features Collection)

1. 装饰器(Decorators,Stage 3)

为类和类成员添加元编程注解和行为扩展。当前状态:Stage 3,预计2025年进入Stage 4

草案提出原因或目的:

  • 缺乏标准化的元编程机制
  • 需要复杂的代码来实现横切关注点(如日志、验证、缓存)
  • 框架间装饰器语法不统一
// 类装饰器
@sealed
class Example {
  // 方法装饰器
  @readonly
  @logged
  method() {
    return 'Hello World';
  }
  
  // 属性装饰器
  @validate
  name = '';
  
  // 访问器装饰器
  @cached
  get computedValue() {
    return this.expensiveCalculation();
  }
}

// 装饰器实现
function sealed(constructor) {
  Object.seal(constructor);
  Object.seal(constructor.prototype);
  return constructor;
}

function readonly(target, context) {
  if (context.kind === 'method') {
    return function(...args) {
      const result = target.call(this, ...args);
      Object.freeze(result);
      return result;
    };
  }
}

function logged(target, context) {
  return function(...args) {
    console.log(`Calling ${context.name} with args:`, args);
    const result = target.call(this, ...args);
    console.log(`${context.name} returned:`, result);
    return result;
  };
}

function validate(target, context) {
  return {
    get() {
      return target.get.call(this);
    },
    set(value) {
      if (typeof value !== 'string') {
        throw new Error(`${context.name} must be a string`);
      }
      return target.set.call(this, value);
    },
    init(value) {
      if (typeof value !== 'string') {
        throw new Error(`${context.name} must be a string`);
      }
      return value;
    }
  };
}

// 实际应用:API 控制器
class UserController {
  @authenticated
  @rateLimit(100) // 每分钟100次请求
  @validate({ schema: userSchema })
  async createUser(userData) {
    return await this.userService.create(userData);
  }
  
  @cached(300) // 缓存5分钟
  @authorized('admin')
  async getUsers() {
    return await this.userService.findAll();
  }
}

2. Symbol.metadata(Stage 3)

为类和对象提供元数据存储。当前状态:Stage 3,与装饰器提案密切相关

草案提出原因或目的:

  • 缺乏标准的元数据存储机制
  • 框架需要自定义元数据系统
  • 反射和元编程支持不足

注意:该特性与装饰器提案紧密结合,语法可能随装饰器提案变化

// 基本用法(配合装饰器)
function metadata(data) {
  return function(target, context) {
    // 在装饰器中设置元数据
    if (!target[Symbol.metadata]) {
      target[Symbol.metadata] = {};
    }
    Object.assign(target[Symbol.metadata], data);
    return target;
  };
}

@metadata({ version: '1.0', author: 'developer' })
class MyClass {
  @metadata({ required: true, type: 'string' })
  property = 'value';
  
  @metadata({ deprecated: true, since: '2.0' })
  oldMethod() {
    return 'legacy';
  }
  
  @metadata({ async: true, timeout: 5000 })
  async newMethod() {
    return 'modern';
  }
}

// 访问元数据
const classMetadata = MyClass[Symbol.metadata];
console.log(classMetadata); // { version: '1.0', author: 'developer' }

// 实际应用:API 文档生成
class ApiDocGenerator {
  static generateDocs(targetClass) {
    const metadata = targetClass[Symbol.metadata] || {};
    const docs = {
      className: targetClass.name,
      ...metadata,
      methods: [],
      properties: []
    };
    
    // 遍历类的方法和属性
    const prototype = targetClass.prototype;
    const propertyNames = Object.getOwnPropertyNames(prototype);
    
    propertyNames.forEach(name => {
      if (name !== 'constructor') {
        const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
        if (descriptor && typeof descriptor.value === 'function') {
          const methodMetadata = descriptor.value[Symbol.metadata] || {};
          docs.methods.push({
            name,
            ...methodMetadata
          });
        }
      }
    });
    
    return docs;
  }
}

// 使用示例
@metadata({ 
  description: 'User management service',
  version: '2.1.0',
  tags: ['user', 'auth']
})
class UserService {
  @metadata({ 
    description: 'Create a new user',
    parameters: [{ name: 'userData', type: 'object', required: true }],
    returns: { type: 'Promise<User>', description: 'Created user object' }
  })
  async createUser(userData) {
    // 创建用户逻辑
    return { id: 1, ...userData };
  }
  
  @metadata({ 
    description: 'Get user by ID',
    parameters: [{ name: 'id', type: 'number', required: true }],
    returns: { type: 'Promise<User|null>', description: 'User object or null' },
    cache: { ttl: 300 }
  })
  async getUserById(id) {
    // 获取用户逻辑
    return { id, name: 'John Doe' };
  }
  
  @metadata({ 
    description: 'Delete user',
    deprecated: true,
    since: '2.0.0',
    alternative: 'softDeleteUser'
  })
  async deleteUser(id) {
    // 删除用户逻辑
  }
}

// 生成 API 文档
const apiDocs = ApiDocGenerator.generateDocs(UserService);
console.log(JSON.stringify(apiDocs, null, 2));

// 运行时元数据检查
class ValidationService {
  static validate(instance, methodName, args) {
    const method = instance.constructor.prototype[methodName];
    const metadata = method[Symbol.metadata];
    
    if (metadata && metadata.parameters) {
      metadata.parameters.forEach((param, index) => {
        if (param.required && args[index] === undefined) {
          throw new Error(`Parameter '${param.name}' is required`);
        }
        
        if (param.type && typeof args[index] !== param.type) {
          throw new Error(`Parameter '${param.name}' must be of type ${param.type}`);
        }
      });
    }
    
    if (metadata && metadata.deprecated) {
      console.warn(`Method '${methodName}' is deprecated since ${metadata.since}`);
      if (metadata.alternative) {
        console.warn(`Use '${metadata.alternative}' instead`);
      }
    }
  }
}

提案状态说明:

  • 目前处于 Stage 3,接近最终确定
  • 与装饰器提案紧密结合,共同进退
  • 为反射和元编程提供标准化支持
  • 预计与装饰器一同在2025年进入 Stage 4

3. 管道操作符(Pipeline Operator,Stage 2)

提供函数式编程风格的数据流处理。当前状态:Stage 2,语法仍在讨论中

草案提出原因或目的:

  • 深度嵌套的函数调用难以阅读和维护
  • 缺乏清晰的数据流表达方式
  • 临时变量污染作用域

当前提案有两种语法选择:

Hack-style 管道(|>)

// 传统写法
const result = Math.round(Math.abs(Math.sqrt(16)));

// 管道操作符写法
const result = 16
  |> Math.sqrt(%)
  |> Math.abs(%)
  |> Math.round(%);

// 复杂数据处理
const processData = data => data
  |> %.filter(item => item.active)
  |> %.map(item => ({ ...item, processed: true }))
  |> %.sort((a, b) => a.priority - b.priority);

// 异步管道
const fetchUserData = userId => userId
  |> await fetchUser(%)
  |> await fetchUserPosts(%)
  |> await enrichWithMetadata(%);

F#-style 管道(|>)

// F# 风格(每个阶段必须是单参数函数)
const result = 16
  |> Math.sqrt
  |> Math.abs
  |> Math.round;

// 需要适配器函数处理多参数
const processUser = user => user
  |> validateUser
  |> u => updateDatabase(u, { timestamp: Date.now() })
  |> u => sendNotification(u, 'updated');

// 实际应用:数据转换管道
const transformApiResponse = response => response
  |> JSON.parse
  |> data => data.results
  |> results => results.filter(item => item.status === 'active')
  |> items => items.map(normalizeItem)
  |> items => items.sort(byPriority);

提案状态说明:

  • 目前 TC39 委员会在两种语法间犹豫
  • Hack-style 更灵活但语法复杂
  • F#-style 更简洁但限制较多
  • 预计2025年确定最终语法方案

4. 部分应用(Partial Application,Stage 1)

允许用 ? 占位符预先填充部分参数,返回新函数。当前状态:Stage 1,提案被重新设计

草案提出原因或目的:

  • 手动创建柯里化函数繁琐
  • 缺乏标准的部分应用语法
  • 函数组合和复用困难

注意:该提案目前处于重新设计阶段,语法可能发生变化

// 基本用法(当前提案语法)
const add = (a, b, c) => a + b + c;
const addFive = add(5, ?, ?);
const addFiveAndThree = add(5, 3, ?);

console.log(addFive(2, 3)); // 10
console.log(addFiveAndThree(1)); // 9

// 复杂参数模式
const processData = (config, data, options, callback) => {
  // 数据处理逻辑
};

// 预设配置和选项
const processWithDefaults = processData(defaultConfig, ?, defaultOptions, ?);

// 使用
processWithDefaults(userData, handleResult);
processWithDefaults(apiData, logResult);

// 实际应用:API 调用
const apiCall = (method, url, headers, body) => {
  return fetch(url, { method, headers, body });
};

// 预设 API 配置
const postToAPI = apiCall('POST', ?, authHeaders, ?);
const getFromAPI = apiCall('GET', ?, authHeaders, null);

// 使用
const createUser = postToAPI('/users', JSON.stringify(userData));
const fetchUsers = getFromAPI('/users');

// 事件处理应用
const handleEvent = (element, eventType, handler, options) => {
  element.addEventListener(eventType, handler, options);
};

// 预设元素和选项
const addClickHandler = handleEvent(button, 'click', ?, { once: true });
const addHoverHandler = handleEvent(?, 'mouseenter', ?, false);

// 使用
addClickHandler(submitForm);
addHoverHandler(tooltip, showTooltip);

提案状态说明:

  • 原 Stage 2 提案因复杂性问题被降级
  • 目前在重新设计更简洁的语法
  • 与管道操作符提案存在语法冲突需要解决
  • 预计2025-2026年重新进入 Stage 2

5. 模式匹配(Pattern Matching,Stage 1)

类似于 switch,但支持结构化匹配和解构。当前状态:Stage 1,语法设计中

草案提出原因或目的:

  • switch 语句功能有限,不支持复杂匹配
  • 缺乏结构化数据的优雅处理方式
  • 条件逻辑复杂时代码冗长

注意:语法仍在设计阶段,以下为提案中的语法示例

// 基本模式匹配(提案语法)
const result = match (value) {
  when 0 -> 'zero',
  when 1 -> 'one',
  when Number if (value > 1) -> 'big number',
  when String -> 'text',
  when _ -> 'unknown'
};

// 对象解构匹配
const handleResponse = match (response) {
  when { status: 200, data } -> data,
  when { status: 404 } -> null,
  when { status, error } if (status >= 400) -> throw new Error(error),
  when _ -> response
};

// 数组模式匹配
const processArray = match (arr) {
  when [] -> 'empty',
  when [x] -> `single: ${x}`,
  when [x, y] -> `pair: ${x}, ${y}`,
  when [head, ...tail] -> `head: ${head}, tail: ${tail.length}`,
  when _ -> 'other'
};

// 复杂嵌套匹配
const handleApiResult = match (result) {
  when { success: true, data: { user: { name, age } } } if (age >= 18) -> 
    `Adult user: ${name}`,
  when { success: true, data: { user: { name } } } -> 
    `Minor user: ${name}`,
  when { success: false, error: { code: 404 } } -> 
    'User not found',
  when { success: false, error: { code, message } } -> 
    `Error ${code}: ${message}`,
  when _ -> 'Unknown response format'
};

// 类型匹配(假设有类型系统)
const processValue = match (value) {
  when String if (value.length > 10) -> 'long string',
  when String -> 'short string',
  when Number if (value % 2 === 0) -> 'even number',
  when Number -> 'odd number',
  when Boolean -> 'boolean value',
  when Array -> `array with ${value.length} items`,
  when Object -> 'object',
  when null -> 'null value',
  when undefined -> 'undefined value',
  when _ -> 'unknown type'
};

// 实际应用:状态机
const handleState = (state, action) => match ([state, action]) {
  when ['idle', { type: 'START' }] -> 'loading',
  when ['loading', { type: 'SUCCESS', data }] -> { state: 'success', data },
  when ['loading', { type: 'ERROR', error }] -> { state: 'error', error },
  when ['success', { type: 'RESET' }] -> 'idle',
  when ['error', { type: 'RETRY' }] -> 'loading',
  when [currentState, _] -> currentState // 保持当前状态
};

提案状态说明:

  • 2018年5月进入 Stage 1
  • 语法设计仍在讨论中,存在多个竞争方案
  • 需要解决与现有 switch 语句的兼容性
  • 性能优化和编译器支持是关键挑战
  • 预计2026年后才可能进入 Stage 2

6. 类型注解(Type Annotations,Stage 1)

为 JS 代码添加类型注解,未来可用于类型检查和 IDE 智能提示。当前状态:Stage 1,语法规范制定中

草案提出原因或目的:

  • JavaScript 缺乏原生类型系统
  • 运行时错误难以在开发阶段发现
  • IDE 智能提示和重构支持有限
  • TypeScript 需要编译步骤

注意:这是一个仅语法提案,不包含运行时类型检查

// 函数类型注解(提案语法)
function add(a: number, b: number): number {
  return a + b;
}

// 变量类型注解
let name: string = 'John';
let age: number = 30;
let isActive: boolean = true;
let items: Array<string> = ['a', 'b', 'c'];

// 对象类型注解
interface User {
  id: number;
  name: string;
  email?: string;
  roles: string[];
}

const user: User = {
  id: 1,
  name: 'Alice',
  roles: ['admin']
};

// 类型别名
type Status = 'pending' | 'approved' | 'rejected';
type EventHandler = (event: Event) => void;

// 泛型函数
function identity<T>(arg: T): T {
  return arg;
}

function map<T, U>(array: T[], fn: (item: T) => U): U[] {
  return array.map(fn);
}

// 类的类型注解
class ApiClient {
  private baseUrl: string;
  
  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;
  }
  
  async get<T>(endpoint: string): Promise<T> {
    const response = await fetch(`${this.baseUrl}${endpoint}`);
    return response.json();
  }
  
  async post<T, U>(endpoint: string, data: T): Promise<U> {
    const response = await fetch(`${this.baseUrl}${endpoint}`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    });
    return response.json();
  }
}

// 复杂类型组合
interface ApiResponse<T> {
  success: boolean;
  data?: T;
  error?: {
    code: number;
    message: string;
  };
}

type UserCreateRequest = {
  name: string;
  email: string;
  password: string;
};

type UserResponse = ApiResponse<User>;

// 实际应用示例
class UserService {
  private client: ApiClient;
  
  constructor(client: ApiClient) {
    this.client = client;
  }
  
  async createUser(userData: UserCreateRequest): Promise<UserResponse> {
    return this.client.post<UserCreateRequest, UserResponse>('/users', userData);
  }
  
  async getUser(id: number): Promise<UserResponse> {
    return this.client.get<UserResponse>(`/users/${id}`);
  }
  
  async updateUser(id: number, updates: Partial<User>): Promise<UserResponse> {
    return this.client.post<Partial<User>, UserResponse>(`/users/${id}`, updates);
  }
}

提案状态说明:

  • 这是一个"仅语法"提案,类型注解在运行时会被忽略
  • 目标是让工具(如 TypeScript、Flow)能够直接处理 JS 文件
  • 不包含运行时类型检查,保持 JS 的动态特性
  • 语法设计需要与 TypeScript 保持兼容
  • 预计2025-2026年进入 Stage 2

7. Array.prototype.groupBy(已移至 Object.groupBy,ES2024)

根据回调结果分组数组元素。当前状态:已在 ES2024 中作为 Object.groupBy 实现

草案提出原因或目的:

  • 手动分组数组元素代码冗长
  • 缺乏标准的数组分组方法
  • 需要使用 reduce 等复杂操作

注意:原 Array.prototype.groupBy 提案被重新设计为 Object.groupBy

const people = [
  { name: 'Alice', age: 25, department: 'Engineering' },
  { name: 'Bob', age: 30, department: 'Marketing' },
  { name: 'Charlie', age: 35, department: 'Engineering' },
  { name: 'Diana', age: 28, department: 'Marketing' }
];

// 使用 Object.groupBy(ES2024)
const byDepartment = Object.groupBy(people, person => person.department);
// {
//   Engineering: [{ name: 'Alice', ... }, { name: 'Charlie', ... }],
//   Marketing: [{ name: 'Bob', ... }, { name: 'Diana', ... }]
// }

// 按年龄段分组
const byAgeGroup = Object.groupBy(people, person => {
  if (person.age < 30) return 'young';
  return 'senior';
});
// {
//   young: [{ name: 'Alice', ... }, { name: 'Diana', ... }],
//   senior: [{ name: 'Bob', ... }, { name: 'Charlie', ... }]
// }

// 使用 Map.groupBy 处理非字符串键
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
const byParity = Map.groupBy(numbers, n => n % 2 === 0);
// Map {
//   false => [1, 3, 5, 7, 9],
//   true => [2, 4, 6, 8, 10]
// }

// 复杂分组逻辑
const transactions = [
  { id: 1, amount: 100, type: 'credit', date: '2024-01-15' },
  { id: 2, amount: 50, type: 'debit', date: '2024-01-15' },
  { id: 3, amount: 200, type: 'credit', date: '2024-01-16' },
  { id: 4, amount: 75, type: 'debit', date: '2024-01-16' }
];

// 按日期和类型分组
const byDateAndType = Object.groupBy(transactions, t => `${t.date}-${t.type}`);
// {
//   '2024-01-15-credit': [{ id: 1, ... }],
//   '2024-01-15-debit': [{ id: 2, ... }],
//   '2024-01-16-credit': [{ id: 3, ... }],
//   '2024-01-16-debit': [{ id: 4, ... }]
// }

提案演进历史:

  • 最初作为 Array.prototype.groupBy 提案
  • 因原型污染和性能考虑,改为静态方法
  • ES2024 中实现为 Object.groupBy 和 Map.groupBy
  • 解决了数组分组的标准化需求

本文档专注于 ES2015-ES2025 各版本的核心特性介绍,为 JavaScript 开发者提供系统性的学习参考。