ECMAScript 2025 正式發(fā)布,一大波超實(shí)用特性來襲!
6 月 26 日,ECMA 國際正式批準(zhǔn) ECMAScript 2025(第 16 版)語言規(guī)范。作為 JavaScript 演化的又一次關(guān)鍵節(jié)點(diǎn),ES2025 引入了八項(xiàng)語言級新特性,本文將詳細(xì)解析這些特性!
圖片
Promise.try()
新增的 Promise.try()
方法可用于統(tǒng)一封裝同步返回值或拋錯的函數(shù)。相比以往常見的 Promise.resolve().then(fn)
或 new Promise(resolve => resolve(fn()))
,Promise.try(fn)
更簡潔高效。
舉個例子:
function mightThrow() {
if (Math.random() > 0.5) throw new Error("Oops");
return "Success";
}
Promise.try(mightThrow)
.then(console.log)
.catch(console.error);
使用場景:
- 適用于封裝第三方同步 API,使其具備統(tǒng)一的異步處理能力;
- 避免使用
Promise.resolve().then(fn)
引入的微任務(wù)延遲; - 可立即拋出同步異常,提高錯誤可見性與調(diào)試效率。
瀏覽器支持情況:
圖片
新的 Set 方法
ES2025 為 Set 實(shí)例新增七個方法,支持集合論基礎(chǔ)運(yùn)算與集合關(guān)系判斷:
- 集合運(yùn)算方法(返回新 Set):
A.intersection(B)
:交集
A.union(B)
:并集
A.difference(B)
:差集
A.symmetricDifference(B)
:對稱差集
- 集合關(guān)系方法(返回布爾值):
A.isSubsetOf(B)
:是否為子集
A.isSupersetOf(B)
:是否為超集
A.isDisjointFrom(B)
:是否無交集
舉個例子:
const A = new Set([1, 2, 3]);
const B = new Set([3, 4, 5]);
console.log(A.union(B)); // Set {1,2,3,4,5}
.log(A.intersection(B)); // Set {3}
console.log(A.difference(B)); // Set {1,2}
console.log(A.symmetricDifference(B)); // Set {1,2,4,5}
console.log(A.isSubsetOf(B)); // false
console.log(A.isSupersetOf(B)); // false
console.log(A.isDisjointFrom(B)); // false
瀏覽器支持情況:
圖片
導(dǎo)入屬性與 JSON 模塊
ES2025 增加了導(dǎo)入屬性,允許在 import
語句中指定附加信息,以指定如何加載模塊。主要用于引入非 JavaScript 資源(如 JSON 文件或 CSS 模塊)。例如,通過 with { type: 'json' }
屬性可將 JSON 文件作為模塊導(dǎo)入,否則瀏覽器默認(rèn)只加載 JS 模塊。
靜態(tài)導(dǎo)入時,可在路徑后加上 with
選項(xiàng);動態(tài)導(dǎo)入時,將其放在第二個參數(shù)的 with
字段中,舉個例子:
// 靜態(tài)導(dǎo)入 JSON 模塊
import config from './config.json' with { type: 'json' };
// 動態(tài)導(dǎo)入 JSON 模塊
const config = await import('./config.json', {
with: { type: 'json' }
});
使用場景:常用于直接導(dǎo)入配置文件、數(shù)據(jù)文件或其他資源,簡化代碼。例如,用于加載本地配置數(shù)據(jù)、國際化文件等,而無需顯式發(fā)起 fetch
請求。相比手動請求后再處理,導(dǎo)入屬性方式語法更簡潔,且可直接像引用 JS 模塊一樣使用 JSON 數(shù)據(jù)。
瀏覽器支持情況:
圖片
同步迭代器輔助函數(shù)
ES2025 為所有同步迭代器(即實(shí)現(xiàn)了迭代器協(xié)議的對象)添加了一系列輔助方法,用于鏈?zhǔn)教幚砜傻鷮ο蟮臄?shù)據(jù)。
.map(fn)
、.filter(fn)
、.flatMap(fn)
.some(fn)
、.every(fn)
、.find(fn)
.reduce(fn, init)
、.forEach(fn)
.drop(n)
、.take(n)
、.toArray()
例如,對數(shù)組使用 values()
生成迭代器后,可以鏈?zhǔn)秸{(diào)用:
const arr = ['a', '', 'b', '', 'c', '', 'd'];
const result = arr.values() // 創(chuàng)建迭代器
.filter(x => x) // 過濾出非空字符串
.map(x => x.toUpperCase()) // 轉(zhuǎn)為大寫
.toArray(); // 轉(zhuǎn)回?cái)?shù)組
console.log(result); // ['A','B','C','D']
以下列舉常用迭代器方法:
iterator.filter(fn)
:返回一個新的迭代器,只包含通過fn
條件的元素。iterator.map(fn)
、iterator.flatMap(fn)
:對每個元素應(yīng)用映射函數(shù),返回新迭代器。iterator.some(fn)
、iterator.every(fn)
:測試是否有元素滿足條件,返回布爾值。iterator.find(fn)
、iterator.reduce(fn)
:返回第一個滿足條件的元素或規(guī)約后的值。iterator.forEach(fn)
:對每個元素執(zhí)行函數(shù),無返回值。iterator.drop(n)
:返回一個迭代器,跳過前n
個元素。iterator.take(n)
:返回一個迭代器,只包含前n
個元素。iterator.toArray()
:將剩余元素收集為數(shù)組并返回。
使用場景:
- 惰性求值:只有在請求下一個值時才計(jì)算,適合處理大型或無限可迭代數(shù)據(jù)(如生成器、流數(shù)據(jù)等),可避免創(chuàng)建多個中間數(shù)組。
- 用于非數(shù)組可迭代對象(如
Set
、Map
、字符串等):使用迭代器方法可以逐步對數(shù)據(jù)進(jìn)行過濾和轉(zhuǎn)換,內(nèi)存效率更高,邏輯更加流暢。例如,處理文件行流、網(wǎng)絡(luò)流或流式數(shù)據(jù)時尤為方便。
瀏覽器支持情況:
圖片
RegExp.escape()
ES2025 新增加的RegExp.escape(str)
方法可以將字符串中的正則元字符(如 *
, .
, ?
, +
, (
, )
等)轉(zhuǎn)義,使其可以安全地嵌入正則表達(dá)式中。
舉個例子:
const raw = "(foo)*+?";
const escaped = RegExp.escape(raw);
console.log(escaped);
// 輸出 "\\(foo\\)\\*\\+\\?"
使用場景:
- 動態(tài)生成正則表達(dá)式時避免語法錯誤;
- 防止正則注入漏洞;
- 替代手動維護(hù)的轉(zhuǎn)義函數(shù)。
瀏覽器支持情況:
圖片
正則表達(dá)式內(nèi)聯(lián)標(biāo)志
ES2025 允許在正則表達(dá)式內(nèi)部使用內(nèi)聯(lián)語法 (?flags:...)
或 (?flags1-flags2:...)
以局部開啟或關(guān)閉某些標(biāo)志位(如 i
, m
, s
)。
例如,正則 /^x(?i:HELLO)x$/
的含義是在整個表達(dá)式外部沒有 i
標(biāo)志,而只對子串 HELLO
應(yīng)用忽略大小寫。
/^x(?i:HELLO)x$/.test('xHELLOx'); // true (HELLO 匹配不區(qū)分大小寫)
/^x(?i:HELLO)x$/.test('xhellox'); // true
/^x(?i:HELLO)x$/.test('XhelloX'); // false (外圍的 x 匹配區(qū)分大小寫)
使用場景:
- 在復(fù)合表達(dá)式中局部應(yīng)用大小寫不敏感匹配;
- 避免正則拆分與多輪匹配邏輯。
重復(fù)命名捕獲組
ES2025 允許在正則表達(dá)式的不同分支(由 |
分隔)中使用相同的命名捕獲組名稱。此前同名捕獲組會導(dǎo)致語法錯誤,但在 ES2025 中,只要這些同名組不可能同時匹配(即位于不同分支),就可以重用名字。這樣便于對形式不同但結(jié)構(gòu)類似的文本進(jìn)行統(tǒng)一處理。
例如,正則 /^((?<x>a)|(?<x>b))$/
既允許匹配字符 'a'
又匹配 'b'
,無論哪種匹配,都使用同名組 x
。匹配 'a'
時,groups.x
值為 'a'
;匹配 'b'
時,groups.x
值為 'b'
const re = /^((?<x>a)|(?<x>b))$/;
console.log(re.exec('a').groups); // { x: 'a' }
console.log(re.exec('b').groups); // { x: 'b' }
同樣地,解析日期字符串可以寫成 /(?<year>\d{4})-\d{2}|\d{2}-(?<year>\d{4})/
,它既匹配“YYYY-MM”也匹配“MM-YYYY”,而捕獲的年、月都儲存在同名 year
、month
組中。
使用場景:重復(fù)命名捕獲組方便處理結(jié)構(gòu)相似的多種格式,例如解析多種日期格式、鍵值對格式等場合。它使得匹配同一邏輯的不同模式可復(fù)用同一段處理代碼,從而避免冗余。例如,在同時支持“年-月”和“月/年”格式的正則中,統(tǒng)一使用 year
、month
組即可簡化后續(xù)處理。
瀏覽器支持情況:
圖片
支持 16 位浮點(diǎn)數(shù)
ES2025 提供對 16 位浮點(diǎn)數(shù)的原生支持:
Float16Array
:16 位浮點(diǎn)的 TypedArray 類型;DataView.prototype.getFloat16()
/setFloat16()
:讀取/寫入半精度浮點(diǎn);Math.f16round(number)
:將雙精度數(shù)值舍入為 16 位浮點(diǎn)精度。
const f16 = new Float16Array(2);
f16[0] = 1.5;
console.log(f16[0]); // 1.5
const buf = new ArrayBuffer(2);
const view = new DataView(buf);
view.setFloat16(0, 1.5);
console.log(view.getFloat16(0)); // 1.5
console.log(Math.f16round(1.337)); // 1.3369140625
使用場景:
- WebGPU / WebGL 中節(jié)省帶寬與內(nèi)存;
- 深度學(xué)習(xí)中傳遞模型參數(shù);
- 模擬硬件精度限制。