JavaScript历代版本新特性
# 前言
JavaScript 诞生于1995年,由 Brendan Eich 在 Netscape 公司仅用10天时间创建。从最初简单的网页脚本语言,发展到今天成为全栈开发的主力语言之一。
JavaScript 的标准化工作由 ECMA International 的 TC39 技术委员会负责,标准名称为 ECMAScript(ES)。从2015年 ES6 发布开始,JavaScript 进入了快速迭代期,每年发布一个新版本,语言特性不断丰富和完善。
本文系统梳理了 JavaScript/ECMAScript 各个版本的核心特性和发展历程。对于每个版本,我们会重点介绍那些影响深远的特性和重要的语法改进。
阅读建议:
- 标记为 粗体 的特性通常是该版本最重要的改进
- ES6(ES2015)是一个里程碑版本,建议重点关注
- 代码示例可以帮助你快速理解新特性的用法
# JavaScript版本发布流程
JavaScript 由 TC39(ECMA International 的第39号技术委员会)管理,通过社区驱动的方式制定标准,采用提案驱动的发布模型(Proposal-Based Release Model)。
# 关键特点
- 自 ES2015 起,每年发布一个新版本(通常在6月)
- 版本命名采用年份(如 ES2015、ES2016、ES2017……)
- 开发基于提案(Proposal)系统
# 全流程步骤
# 1. 提案提交(Stage 0: Strawperson)
- 任何 TC39 成员或贡献者可以提交想法
- 只需在 TC39 会议上展示即可进入 Stage 0
- 此阶段的提案可能会被完全改变或废弃
# 2. 提案阶段(Stage 1: Proposal)
- 明确问题和解决方案
- 提供示例和高层API描述
- 识别潜在的实现挑战
# 3. 草案阶段(Stage 2: Draft)
- 提供精确的语法和语义描述
- 预期该特性最终会被纳入标准
- 可能会有实验性的实现
# 4. 候选阶段(Stage 3: Candidate)
- 规范文本完成,等待实现和用户反馈
- 至少需要两个符合规范的实现
- 只有在实现过程中发现关键问题才会修改
# 5. 完成阶段(Stage 4: Finished)
- 通过 Test262 验收测试
- 至少两个通过测试的实现
- 编辑签字确认
- 将在下一个年度版本中发布
# 6. 正式发布
- 每年6月发布新版本
- 只包含已达到 Stage 4 的提案
- 版本以年份命名(如 ES2024)
# 7. 后续更新
- 规范错误修正随时进行
- 不影响已发布版本的稳定性
# 治理模型
- 代表组织:各大浏览器厂商(Google、Mozilla、Apple、Microsoft)、科技公司(Meta、Netflix)、学术机构等
- 治理模型:共识驱动(需要委员会达成共识)
# ES1(1997)
1997年6月发布,是 JavaScript 的第一个正式标准版本。
# 核心特性
- 基础语法:变量声明、数据类型、运算符
- 控制结构:
if/else、for、while、switch - 函数:函数声明、函数表达式
- 对象:基于原型的对象系统
- 数组:基本数组操作
- 字符串:字符串处理方法
# ES2(1998)
1998年6月发布,主要是编辑性修改以符合 ISO/IEC 16262 国际标准。
# 主要改进
- 规范文本的格式化和编辑修正
- 与 ISO/IEC 16262 标准保持一致
# ES3(1999)
1999年12月发布,是 JavaScript 成熟的重要版本。
# 核心特性
- 正则表达式:内置正则表达式支持
- 异常处理:
try/catch/finally语句 - 更好的字符串处理:
substring、concat、match、replace、split等方法 - 更多数组方法:
push、pop、shift、unshift、splice等 - 格式化输出:
toFixed、toExponential、toPrecision
示例:
// 正则表达式
var pattern = /hello/i;
var text = "Hello World";
console.log(pattern.test(text)); // true
// 异常处理
try {
throw new Error("自定义错误");
} catch (e) {
console.log(e.message);
} finally {
console.log("总是执行");
}
// 数组方法
var arr = [1, 2, 3];
arr.push(4);
console.log(arr); // [1, 2, 3, 4]
# ES4(废弃)
ES4 计划引入大量新特性,包括类、模块、类型注解等,但由于提案过于激进,最终被废弃。部分特性后来在 ES6 中实现。
# ES5(2009)
2009年12月发布,是 ES3 之后的首个重大更新,间隔了10年。
# 革命性特性
严格模式(Strict Mode):
"use strict"启用更严格的语法检查"use strict"; x = 3.14; // 报错:未声明变量JSON 支持:原生
JSON.parse()和JSON.stringify()var obj = {name: "张三", age: 25}; var json = JSON.stringify(obj); var parsed = JSON.parse(json);
# 对象增强
访问器属性:
Object.defineProperty()、Object.defineProperties()var person = {}; Object.defineProperty(person, "name", { get: function() { return this._name; }, set: function(value) { this._name = value.toUpperCase(); } });对象方法:
Object.create():基于原型创建对象Object.keys():获取对象的键Object.seal():密封对象Object.freeze():冻结对象Object.preventExtensions():防止扩展
# 数组增强
数组迭代方法:
var arr = [1, 2, 3, 4, 5]; // forEach arr.forEach(function(item) { console.log(item); }); // map var doubled = arr.map(function(item) { return item * 2; }); // filter var evens = arr.filter(function(item) { return item % 2 === 0; }); // reduce var sum = arr.reduce(function(acc, item) { return acc + item; }, 0); // some 和 every var hasEven = arr.some(function(item) { return item % 2 === 0; }); var allPositive = arr.every(function(item) { return item > 0; });数组方法:
Array.isArray()、indexOf()、lastIndexOf()
# 其他改进
Function.prototype.bind():绑定函数的this值var module = { x: 42, getX: function() { return this.x; } }; var boundGetX = module.getX.bind(module); console.log(boundGetX()); // 42String.prototype.trim():去除字符串首尾空白
# ES5.1(2011)
2011年6月发布,是 ES5 的维护版本。
# 主要改进
- 修正规范中的歧义和错误
- 与 ISO/IEC 16262:2011 保持一致
# ES6 / ES2015(2015)
2015年6月发布,是 JavaScript 历史上最重要的版本,引入了大量现代化特性。
# 革命性特性
# 1. let 和 const
- 块级作用域:解决
var的变量提升问题// var 的问题 for (var i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 100); } // 输出:3 3 3 // let 解决 for (let i = 0; i < 3; i++) { setTimeout(function() { console.log(i); }, 100); } // 输出:0 1 2 // const 常量 const PI = 3.14159; // PI = 3; // 报错
# 2. 箭头函数
- 简洁语法:更简洁的函数表达式
- 词法 this:不绑定自己的
this// 传统函数 var add = function(a, b) { return a + b; }; // 箭头函数 const add = (a, b) => a + b; // this 绑定 function Timer() { this.seconds = 0; setInterval(() => { this.seconds++; // this 指向 Timer 实例 }, 1000); }
# 3. 类(Class)
- 语法糖:更清晰的面向对象编程
class Person { constructor(name, age) { this.name = name; this.age = age; } sayHello() { console.log(`你好,我是${this.name}`); } static species() { return "智人"; } } class Student extends Person { constructor(name, age, grade) { super(name, age); this.grade = grade; } study() { console.log(`${this.name}正在学习`); } }
# 4. 模块系统
- ES6 模块:原生模块支持
// math.js export const PI = 3.14159; export function add(a, b) { return a + b; } export default class Calculator { // ... } // main.js import Calculator, { PI, add } from './math.js'; import * as math from './math.js';
# 5. 模板字符串
- 字符串插值:更方便的字符串拼接
const name = "张三"; const age = 25; // 传统方式 var msg = "我是" + name + ",今年" + age + "岁"; // 模板字符串 const msg = `我是${name},今年${age}岁`; // 多行字符串 const html = ` <div> <h1>${name}</h1> <p>年龄:${age}</p> </div> `;
# 6. 解构赋值
- 便捷提取:从数组或对象中提取值
// 数组解构 const [a, b, c] = [1, 2, 3]; const [first, ...rest] = [1, 2, 3, 4, 5]; // 对象解构 const {name, age} = {name: "张三", age: 25}; const {name: userName, age: userAge} = {name: "张三", age: 25}; // 函数参数解构 function greet({name, age}) { console.log(`${name}今年${age}岁`); } greet({name: "张三", age: 25});
# 7. 默认参数、剩余参数、展开运算符
// 默认参数
function greet(name = "访客") {
console.log(`你好,${name}`);
}
// 剩余参数
function sum(...numbers) {
return numbers.reduce((acc, num) => acc + num, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
// 展开运算符
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 4, 5, 6];
const obj1 = {a: 1, b: 2};
const obj2 = {...obj1, c: 3};
# 8. Promise
- 异步编程:更优雅的异步处理
// 创建 Promise const promise = new Promise((resolve, reject) => { setTimeout(() => { resolve("成功"); // reject(new Error("失败")); }, 1000); }); // 使用 Promise promise .then(result => console.log(result)) .catch(error => console.error(error)) .finally(() => console.log("完成")); // Promise 链式调用 fetch('/api/user') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error));
# 9. Symbol
- 唯一标识符:创建唯一的属性键
const sym1 = Symbol('描述'); const sym2 = Symbol('描述'); console.log(sym1 === sym2); // false // 作为对象属性 const obj = { [Symbol('id')]: 123 };
# 10. 迭代器和生成器
// 迭代器
const obj = {
data: [1, 2, 3],
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return {value: this.data[index++], done: false};
}
return {done: true};
}
};
}
};
// 生成器
function* fibonacci() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
const fib = fibonacci();
console.log(fib.next().value); // 1
console.log(fib.next().value); // 1
console.log(fib.next().value); // 2
# 数据结构
Set:值的集合,值唯一
const set = new Set([1, 2, 3, 3, 4]); console.log(set.size); // 4 set.add(5); set.has(3); // true set.delete(2);Map:键值对集合,键可以是任意类型
const map = new Map(); map.set('name', '张三'); map.set(123, '数字键'); map.get('name'); // "张三" map.size; // 2WeakSet 和 WeakMap:弱引用版本,用于防止内存泄漏
# 其他重要特性
Proxy 和 Reflect:元编程支持
const handler = { get(target, prop) { console.log(`访问属性: ${prop}`); return target[prop]; } }; const proxy = new Proxy({name: "张三"}, handler); console.log(proxy.name); // 访问属性: name \n 张三二进制和八进制字面量:
0b1010、0o755Number 扩展:
Number.isNaN()、Number.isFinite()、Number.isInteger()Math 扩展:
Math.trunc()、Math.sign()、Math.cbrt()等Array 扩展:
Array.from()、Array.of()、find()、findIndex()、fill()、copyWithin()Object 扩展:
Object.assign()、Object.is()String 扩展:
startsWith()、endsWith()、includes()、repeat()
# ES2016(ES7)
2016年6月发布,包含2个新特性。
# 核心特性
数组 includes 方法:检查数组是否包含某个值
const arr = [1, 2, 3, NaN]; arr.includes(2); // true arr.includes(NaN); // true(indexOf 无法识别 NaN)指数运算符:
**运算符console.log(2 ** 3); // 8 console.log(Math.pow(2, 3)); // 8(旧方法)
# ES2017(ES8)
2017年6月发布,引入了异步编程的重大改进。
# 革命性特性
- async/await:基于 Promise 的异步语法糖
// Promise 方式 function fetchData() { return fetch('/api/data') .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error(error)); } // async/await 方式 async function fetchData() { try { const response = await fetch('/api/data'); const data = await response.json(); console.log(data); } catch (error) { console.error(error); } } // 并行执行 async function parallel() { const [result1, result2] = await Promise.all([ fetch('/api/1'), fetch('/api/2') ]); }
# 对象增强
Object.values():返回对象的值数组
Object.entries():返回对象的键值对数组
const obj = {name: "张三", age: 25}; Object.values(obj); // ["张三", 25] Object.entries(obj); // [["name", "张三"], ["age", 25]] // 遍历对象 for (let [key, value] of Object.entries(obj)) { console.log(`${key}: ${value}`); }Object.getOwnPropertyDescriptors():获取对象所有属性描述符
# 字符串增强
- 字符串填充:
padStart()和padEnd()'5'.padStart(3, '0'); // "005" 'abc'.padEnd(5, '*'); // "abc**"
# 其他特性
函数参数尾逗号:允许函数参数列表和调用时的尾逗号
function foo( a, b, c, ) { // ... }共享内存和原子操作:
SharedArrayBuffer和Atomics
# ES2018(ES9)
2018年6月发布,进一步完善异步和对象操作。
# 核心特性
异步迭代:
for await...ofasync function* asyncGenerator() { yield await Promise.resolve(1); yield await Promise.resolve(2); yield await Promise.resolve(3); } (async () => { for await (const num of asyncGenerator()) { console.log(num); } })();Promise.finally():无论成功或失败都执行
fetch('/api/data') .then(response => response.json()) .catch(error => console.error(error)) .finally(() => console.log('请求完成'));
# 对象增强
- 对象展开运算符:对象的剩余/展开属性
const {a, b, ...rest} = {a: 1, b: 2, c: 3, d: 4}; console.log(rest); // {c: 3, d: 4} const obj = {a: 1, b: 2}; const newObj = {...obj, c: 3}; // {a: 1, b: 2, c: 3}
# 正则表达式增强
命名捕获组:
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; const match = pattern.exec('2024-01-15'); console.log(match.groups.year); // "2024"反向断言:
(?<=...)和(?<!...)dotAll 模式:
s标志让.匹配换行符Unicode 属性转义:
\p{...}和\P{...}
# ES2019(ES10)
2019年6月发布,带来了多个实用特性。
# 核心特性
Array.flat() 和 Array.flatMap():数组扁平化
const arr = [1, 2, [3, 4, [5, 6]]]; arr.flat(); // [1, 2, 3, 4, [5, 6]] arr.flat(2); // [1, 2, 3, 4, 5, 6] arr.flat(Infinity); // 完全扁平化 const arr2 = [1, 2, 3]; arr2.flatMap(x => [x, x * 2]); // [1, 2, 2, 4, 3, 6]Object.fromEntries():将键值对列表转换为对象
const entries = [['name', '张三'], ['age', 25]]; const obj = Object.fromEntries(entries); // {name: "张三", age: 25} // 对象转换 const obj2 = {a: 1, b: 2, c: 3}; const filtered = Object.fromEntries( Object.entries(obj2).filter(([key, value]) => value > 1) );String.trimStart() 和 String.trimEnd():去除首尾空白
' hello '.trimStart(); // "hello " ' hello '.trimEnd(); // " hello"
# 其他特性
可选的 catch 绑定:catch 可以省略参数
try { // ... } catch { console.log('发生错误'); }Symbol.description:获取 Symbol 的描述
const sym = Symbol('描述'); console.log(sym.description); // "描述"Function.toString() 改进:返回精确的源代码文本
JSON 超集:允许 U+2028 和 U+2029 字符
# ES2020(ES11)
2020年6月发布,引入了多个重要特性。
# 核心特性
可选链操作符(Optional Chaining):
?.const user = { name: '张三', address: { city: '北京' } }; // 传统方式 const city = user && user.address && user.address.city; // 可选链 const city = user?.address?.city; const zipCode = user?.address?.zipCode; // undefined // 函数调用 obj.method?.(); // 数组访问 arr?.[0];空值合并运算符(Nullish Coalescing):
??// || 的问题 const count = 0; const result = count || 10; // 10(不符合预期) // ?? 只判断 null 和 undefined const result = count ?? 10; // 0 const result = null ?? 10; // 10 const result = undefined ?? 10; // 10BigInt:任意精度整数
const bigInt = 9007199254740991n; const alsoHuge = BigInt(9007199254740991); const result = bigInt + 1n; // 9007199254740992n // 不能与 Number 混用 // bigInt + 1; // 报错Promise.allSettled():等待所有 Promise 完成(无论成功或失败)
const promises = [ Promise.resolve(1), Promise.reject('错误'), Promise.resolve(3) ]; Promise.allSettled(promises).then(results => { results.forEach(result => { if (result.status === 'fulfilled') { console.log('成功:', result.value); } else { console.log('失败:', result.reason); } }); });
# 模块增强
动态 import():运行时动态加载模块
// 条件加载 if (condition) { import('./module.js').then(module => { module.doSomething(); }); } // async/await async function loadModule() { const module = await import('./module.js'); module.doSomething(); }import.meta:模块元数据
console.log(import.meta.url); // 模块的 URL
# 其他特性
globalThis:统一的全局对象
// 浏览器: window // Node.js: global // Web Workers: self // 统一访问 globalThis.setTimeout(...);String.matchAll():返回所有匹配的迭代器
const str = 'test1test2test3'; const regex = /test(\d)/g; for (const match of str.matchAll(regex)) { console.log(match[0], match[1]); }for-in 顺序标准化:规范化 for-in 的遍历顺序
# ES2021(ES12)
2021年6月发布,带来了多个实用的新特性。
# 核心特性
逻辑赋值运算符:
&&=、||=、??=// 逻辑或赋值 let x = 0; x ||= 10; // x = x || 10 console.log(x); // 10 // 逻辑与赋值 let y = 5; y &&= 10; // y = y && 10 console.log(y); // 10 // 空值赋值 let z = null; z ??= 10; // z = z ?? 10 console.log(z); // 10数字分隔符:提高数字可读性
const billion = 1_000_000_000; const bytes = 0xFF_FF_FF_FF; const pi = 3.14_15_92_65;String.replaceAll():替换所有匹配项
const str = 'hello world hello'; // 传统方式 str.replace(/hello/g, 'hi'); // "hi world hi" // replaceAll str.replaceAll('hello', 'hi'); // "hi world hi"Promise.any():任意一个 Promise 成功即返回
const promises = [ Promise.reject('错误1'), Promise.resolve('成功'), Promise.reject('错误2') ]; Promise.any(promises) .then(result => console.log(result)) // "成功" .catch(error => console.error(error)); // 如果全部失败,返回 AggregateError
# 其他特性
WeakRef:弱引用对象
const obj = {name: '张三'}; const weakRef = new WeakRef(obj); // 获取引用 const deref = weakRef.deref(); if (deref) { console.log(deref.name); }FinalizationRegistry:对象被垃圾回收时的回调
逻辑赋值运算符的短路特性
# ES2022(ES13)
2022年6月发布,进一步完善了类和模块系统。
# 核心特性
类字段声明:直接在类中声明字段
class Person { name = '张三'; // 公共字段 #age = 25; // 私有字段 getAge() { return this.#age; } } const p = new Person(); console.log(p.name); // "张三" // console.log(p.#age); // 报错:私有字段 console.log(p.getAge()); // 25私有方法和访问器:
class Counter { #count = 0; #increment() { this.#count++; } get #privateCount() { return this.#count; } increase() { this.#increment(); return this.#privateCount; } }静态类字段和方法:
class MathUtils { static PI = 3.14159; static #secret = 'private'; static area(radius) { return this.PI * radius * radius; } static #privateMethod() { return this.#secret; } } console.log(MathUtils.PI); // 3.14159 console.log(MathUtils.area(5)); // 78.53975类静态初始化块:
class Database { static connection; static { // 静态初始化块 this.connection = createConnection(); } }
# 其他特性
顶层 await:模块顶层可以直接使用 await
// module.js const data = await fetch('/api/data'); export default data;Array.at():支持负索引的数组访问
const arr = [1, 2, 3, 4, 5]; arr.at(-1); // 5 arr.at(-2); // 4 arr.at(0); // 1Object.hasOwn():更安全的属性检查
const obj = {name: '张三'}; // 传统方式(可能有问题) obj.hasOwnProperty('name'); // true // 新方式 Object.hasOwn(obj, 'name'); // trueError.cause:错误链
try { // ... } catch (error) { throw new Error('上层错误', {cause: error}); }正则表达式 d 标志:匹配索引
# ES2023(ES14)
2023年6月发布,带来了数组操作的重要改进。
# 核心特性
Array.findLast() 和 Array.findLastIndex():从后向前查找
const arr = [1, 2, 3, 4, 5]; arr.findLast(x => x > 2); // 5 arr.findLastIndex(x => x > 2); // 4Array.toReversed()、toSorted()、toSpliced():不可变数组方法
const arr = [3, 1, 2]; // 传统方式(会修改原数组) arr.sort(); // [1, 2, 3] // 新方式(返回新数组) const sorted = arr.toSorted(); // [1, 2, 3] console.log(arr); // [3, 1, 2](原数组不变) const reversed = arr.toReversed(); // [2, 1, 3] const spliced = arr.toSpliced(1, 1, 10); // [3, 10, 2]Array.with():不可变的索引替换
const arr = [1, 2, 3]; const newArr = arr.with(1, 10); // [1, 10, 3] console.log(arr); // [1, 2, 3](原数组不变)
# 其他特性
WeakMap 支持 Symbol 作为键:
const weakMap = new WeakMap(); const sym = Symbol('key'); const obj = {}; weakMap.set(sym, obj);#! Shebang 语法:支持 Unix Shebang
#!/usr/bin/env node console.log('Hello');
# ES2024(ES15)
2024年6月发布,包含多个实用的新特性。
# 核心特性
Promise.withResolvers():更方便地创建 Promise
// 传统方式 let resolve, reject; const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); // 新方式 const {promise, resolve, reject} = Promise.withResolvers(); // 使用场景 class Queue { #items = []; #resolvers = []; async dequeue() { if (this.#items.length > 0) { return this.#items.shift(); } const {promise, resolve} = Promise.withResolvers(); this.#resolvers.push(resolve); return promise; } enqueue(item) { if (this.#resolvers.length > 0) { const resolve = this.#resolvers.shift(); resolve(item); } else { this.#items.push(item); } } }Object.groupBy() 和 Map.groupBy():数组分组
const people = [ {name: '张三', age: 25}, {name: '李四', age: 30}, {name: '王五', age: 25} ]; // 按年龄分组(返回对象) const grouped = Object.groupBy(people, person => person.age); // { // 25: [{name: '张三', age: 25}, {name: '王五', age: 25}], // 30: [{name: '李四', age: 30}] // } // 按年龄分组(返回 Map) const groupedMap = Map.groupBy(people, person => person.age);正则表达式 v 标志:Unicode 集合符号和属性
// v 标志支持更强大的 Unicode 匹配 const regex = /[\p{Script=Han}&&\p{Radical=亻}]/v;
# 其他特性
ArrayBuffer 转移:
const buffer = new ArrayBuffer(8); const newBuffer = buffer.transfer(16); // 转移并调整大小Atomics.waitAsync():异步等待共享内存
# ES2025(ES16)
2025年6月发布,包含8个重要的新特性。
# 核心特性
# 1. 迭代器辅助方法(Iterator Helpers)
为迭代器提供链式操作方法,使其使用更加便捷。
// 创建生成器
function* numberGenerator() {
yield 1;
yield 2;
yield 3;
yield 4;
yield 5;
}
// map() - 转换每个值
const doubled = numberGenerator().map(x => x * 2);
console.log([...doubled]); // [2, 4, 6, 8, 10]
// filter() - 过滤元素
const evens = numberGenerator().filter(x => x % 2 === 0);
console.log([...evens]); // [2, 4]
// take() - 取前 N 个
const first3 = numberGenerator().take(3);
console.log([...first3]); // [1, 2, 3]
// drop() - 跳过前 N 个
const after2 = numberGenerator().drop(2);
console.log([...after2]); // [3, 4, 5]
// flatMap() - 扁平化映射
const flattened = numberGenerator().flatMap(x => [x, x * 10]);
console.log([...flattened]); // [1, 10, 2, 20, 3, 30, 4, 40, 5, 50]
// reduce() - 累积计算
const sum = numberGenerator().reduce((acc, x) => acc + x, 0);
console.log(sum); // 15
// 链式调用
const arr = ['a', '', 'b', '', 'c', '', 'd', '', 'e'];
const result = arr.values()
.filter(x => x.length > 0)
.drop(1)
.take(3)
.map(x => `=${x}=`)
.toArray();
console.log(result); // ['=b=', '=c=', '=d=']
// 其他方法
numberGenerator().forEach(x => console.log(x)); // 遍历
numberGenerator().some(x => x % 2 === 0); // true - 是否存在偶数
numberGenerator().every(x => x > 0); // true - 是否全部为正数
numberGenerator().find(x => x > 3); // 4 - 查找第一个匹配
// Iterator.from() - 从可迭代对象创建
const iter = Iterator.from([1, 2, 3]);
console.log([...iter.map(x => x * 2)]); // [2, 4, 6]
# 2. Set 新方法
新增一系列集合操作方法。
const setA = new Set(['a', 'b', 'c']);
const setB = new Set(['b', 'c', 'd']);
// union() - 并集
setA.union(setB); // Set(['a', 'b', 'c', 'd'])
// intersection() - 交集
setA.intersection(setB); // Set(['b', 'c'])
// difference() - 差集
setA.difference(setB); // Set(['a'])
// symmetricDifference() - 对称差(存在于A或B,但不同时存在)
setA.symmetricDifference(setB); // Set(['a', 'd'])
// isSubsetOf() - 判断是否为子集
new Set(['a', 'b']).isSubsetOf(new Set(['a', 'b', 'c'])); // true
// isSupersetOf() - 判断是否为超集
new Set(['a', 'b', 'c']).isSupersetOf(new Set(['a', 'b'])); // true
// isDisjointFrom() - 判断是否不相交
new Set(['a', 'b']).isDisjointFrom(new Set(['c', 'd'])); // true
# 3. Promise.try()
统一处理同步和异步代码的错误。
// 传统方式的问题
function compute() {
try {
const value = syncFuncMightThrow(); // 可能抛出同步错误
return asyncFunc(value); // 返回 Promise
} catch (error) {
return Promise.reject(error);
}
}
// 使用 Promise.try()
function compute() {
return Promise.try(() => {
const value = syncFuncMightThrow();
return asyncFunc(value);
});
}
// 实际应用
Promise.try(() => {
return riskyOperation();
})
.then(result => console.log('成功:', result))
.catch(error => console.error('错误:', error));
// 优势:统一了同步和异步错误处理
async function processData(data) {
return Promise.try(() => {
// 这里可能是同步代码,也可能是异步代码
if (!data) throw new Error('数据为空');
return fetch(`/api/${data}`);
})
.then(response => response.json())
.catch(error => {
console.error('处理失败:', error);
throw error;
});
}
# 4. RegExp.escape()
转义正则表达式中的特殊字符。
// 问题场景
const userInput = '[hello]';
// new RegExp(userInput); // 错误:[] 是特殊字符
// 使用 RegExp.escape()
const escaped = RegExp.escape(userInput); // '\[hello\]'
const regex = new RegExp(escaped);
// 实际应用:移除未引用的文本
function removeUnquotedText(str, text) {
const regExp = new RegExp(
`(?<!")${RegExp.escape(text)}(?!")`,
'gu'
);
return str.replaceAll(regExp, '•');
}
removeUnquotedText('"yes" and yes and "yes"', 'yes');
// '"yes" and • and "yes"'
// 搜索包含特殊字符的字符串
const searchTerm = 'a+b*c?';
const pattern = new RegExp(RegExp.escape(searchTerm));
pattern.test('a+b*c?'); // true
pattern.test('aabbbbc'); // false
# 5. 导入属性(Import Attributes)
支持导入 JSON 等非 JavaScript 资源。
// 静态导入 JSON
import config from './config.json' with { type: 'json' };
console.log(config.apiUrl);
// 动态导入 JSON
const configData = await import(
'./config.json',
{ with: { type: 'json' } }
);
// 导入 CSS(将来可能支持)
import styles from './styles.css' with { type: 'css' };
// 实际应用
// config.json
{
"apiUrl": "https://api.example.com",
"timeout": 5000
}
// app.js
import settings from './config.json' with { type: 'json' };
async function fetchData() {
const response = await fetch(settings.apiUrl, {
signal: AbortSignal.timeout(settings.timeout)
});
return response.json();
}
# 6. 正则表达式模式修饰符
在正则表达式内部使用修饰符。
// 内联标志 - 对部分表达式应用修饰符
const regex = /^x(?i:hello)x$/;
regex.test('xHELLOx'); // true
regex.test('xhellox'); // true
regex.test('XhelloX'); // false(开头和结尾的 x 仍然区分大小写)
// 实际应用:部分不区分大小写
const pattern = /^(?i:mr|mrs|ms)\.\s+[A-Z][a-z]+$/;
pattern.test('Mr. Smith'); // true
pattern.test('mrs. Johnson'); // true
pattern.test('MS. Williams'); // true
// 禁用修饰符
const regex2 = /(?-i:HELLO)/i; // 整体不区分大小写,但 HELLO 部分区分大小写
# 7. 重复命名捕获组
允许在不同分支中使用相同的组名。
// ES2024 之前,捕获组名必须唯一
// const RE_OLD = /(?<year>\d{4})-\d{2}|(?<year>\d{4})\/\d{2}/; // 错误
// ES2025 允许在不同分支中重复
const RE = /(?<year>\d{4})-(?<month>\d{2})|(?<year>\d{4})\/(?<month>\d{2})/v;
RE.exec('2024-01').groups; // { year: '2024', month: '01' }
RE.exec('2024/12').groups; // { year: '2024', month: '12' }
// 实际应用:匹配不同格式
const datePattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})|(?<month>\d{2})\/(?<day>\d{2})\/(?<year>\d{4})/v;
datePattern.exec('2024-01-15').groups;
// { year: '2024', month: '01', day: '15' }
datePattern.exec('01/15/2024').groups;
// { year: '2024', month: '01', day: '15' }
// 字符类匹配
const RE2 = /(?<chars>a+)|(?<chars>b+)/v;
RE2.exec('aaa').groups; // { chars: 'aaa' }
RE2.exec('bb').groups; // { chars: 'bb' }
# 8. Float16Array(16位浮点数)
支持半精度浮点数,适用于 WebGPU 和机器学习。
// 创建 Float16Array
const arr = new Float16Array([1.5, 2.5, 3.5, 4.5]);
// 属性
arr.BYTES_PER_ELEMENT; // 2(每个元素占2字节)
arr.length; // 4
arr.byteLength; // 8
// Math.f16round() - 转换为最接近的 16 位浮点数
Math.f16round(2.60); // 2.599609375
Math.f16round(2.50); // 2.5
Math.f16round(2.49); // 2.490234375
// DataView 支持
const buffer = new ArrayBuffer(8);
const view = new DataView(buffer);
view.setFloat16(0, 3.14);
view.getFloat16(0); // 3.140625
// 实际应用:节省内存
// 32位浮点数数组
const float32 = new Float32Array([1.1, 2.2, 3.3]); // 12 字节
// 16位浮点数数组(精度略低但节省空间)
const float16 = new Float16Array([1.1, 2.2, 3.3]); // 6 字节
// WebGPU 使用场景
const vertices = new Float16Array([
// x, y, z 坐标
0.0, 0.5, 0.0,
-0.5, -0.5, 0.0,
0.5, -0.5, 0.0
]);
# 正则表达式 v 标志增强
v 标志是 u(unicode)标志的升级版,支持更强大的 Unicode 匹配。
// 匹配 emoji
const emojiPattern = /\p{RGI_Emoji}/v;
emojiPattern.test('Hello 😀'); // true
// 字符类运算
// 并集、交集、差集
const pattern = /[\p{Script=Greek}&&\p{Letter}]/v;
// 字符串属性
const stringPattern = /\p{Emoji_Keycap_Sequence}/v;
stringPattern.test('1️⃣'); // true
# 总结
JavaScript 从简单的脚本语言发展到今天的全栈开发语言,经历了巨大的变化:
- ES3(1999):奠定基础,引入正则和异常处理
- ES5(2009):严格模式、JSON 支持、数组方法
- ES6(2015):里程碑版本,引入 class、模块、Promise、箭头函数等
- ES2016-ES2025:每年一个版本,持续改进和完善
重点关注的版本:
- ES6(ES2015):必须掌握,现代 JavaScript 的基础
- ES2017:async/await 改变异步编程
- ES2020:可选链和空值合并极大提升开发体验
- ES2022:私有字段和方法使类更加完善
- ES2025:迭代器辅助方法、Set 集合操作、Promise.try() 等实用特性
# 参考资料
- ECMAScript 规范 (opens new window)
- TC39 提案流程 (opens new window)
- MDN JavaScript 文档 (opens new window)
- Can I Use (opens new window):浏览器兼容性查询
祝你变得更强!