ES2015 在 JavaScript 語言推出了許多新功能,包括對使用萬國碼 (Unicode) (/u
) 和固定式 (/y
) 旗標的規則運算式語法做出大幅改善。但開發功能從那時就沒有停止。在 TC39 (ECMAScript 標準內文) 中與其他成員展開合作,V8 團隊已提議並共同設計幾項新功能,讓規則運算式更強大。
我們目前正建議將這些功能納入 JavaScript 規格。即使提案尚未完全接受,這些提案已在TC39 程序的第 3 階段階段。我們已在標記後方實作這些功能 (請參閱下方說明),以便在規格定案前,向個別提案作者及時提供設計與實作意見回饋。
這篇網誌文章可讓您預覽這個令人期待的未來。如要參與後續範例,請在 chrome://flags/#enable-javascript-harmony
啟用實驗性 JavaScript 功能。
已命名的擷取內容
規則運算式可以包含所謂的擷取 (或群組),可以擷取部分相符文字。到目前為止,開發人員只能根據擷取的索引參照這些擷取內容,索引取決於模式中的擷取位置。
const pattern = /(\d{4})-(\d{2})-(\d{2})/u;
const result = pattern.exec('2017-07-10');
// result[0] === '2017-07-10'
// result[1] === '2017'
// result[2] === '07'
// result[3] === '10'
然而,規則運算式在讀取、寫入及維護方面仍更加困難,而數字參照可能會導致進一步的小工具。舉例來說,在較長模式中,要判斷特定擷取的索引,可能很困難:
/(?:(.)(.(?<=[^(])(.)))/ // Index of the last capture?
更糟的是,模式變更可能會改變所有現有擷取的索引:
/(a)(b)(c)\3\2\1/ // A few simple numbered backreferences.
/(.)(a)(b)(c)\4\3\2/ // All need to be updated.
已命名擷取是即將推出的功能,可讓開發人員指派名稱來擷取,有助於減輕這些問題。語法與 Perl、Java、.Net 和 Ruby 相似:
const pattern = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/u;
const result = pattern.exec('2017-07-10');
// result.groups.year === '2017'
// result.groups.month === '07'
// result.groups.day === '10'
已命名的擷取也可透過已命名的反向參照和 String.prototype.replace
參照:
// Named backreferences.
/(?<LowerCaseX>x)y\k<LowerCaseX>/.test('xyx'); // true
// String replacement.
const pattern = /(?<fst>a)(?<snd>b)/;
'ab'.replace(pattern, '$<snd>$<fst>'); // 'ba'
'ab'.replace(pattern, (m, p1, p2, o, s, {fst, snd}) => fst + snd); // 'ba'
如需這項新功能的完整詳情,請參閱規格提案。
dotAll 標記
根據預設,規則運算式中的 .
Atom 會比對任何字元,但行結束字元除外:
/foo.bar/u.test('foo\nbar'); // false
提案導入了 dotAll 模式,可透過 /s
標記啟用。在 dotAll 模式中,.
也會比對行結束字元。
/foo.bar/su.test('foo\nbar'); // true
如需這項新功能的完整詳情,請參閱規格提案。
萬國碼 (Unicode) 屬性逸出
隨著 ES2015 推出萬國碼 (Unicode) 感知功能,就突然有更多字元可視為數字,例如圓圈中的數字 1: 或視為字詞字元,例如,雪的中文字元:第。
兩者都無法與 \d
或 \w
配對。變更這些簡寫的意義可能會破壞現有的規則運算式模式。
我們正在推出新的屬性逸出序列。請注意,這些運算式僅適用於以 /u
旗標表示的萬國碼 (Unicode) 感知規則運算式。
/\p{Number}/u.test('①'); // true
/\p{Alphabetic}/u.test('雪'); // true
反之則可與 \P
進行比對。
/\P{Number}/u.test('①'); // false
/\P{Alphabetic}/u.test('雪'); // false
Unicode 聯盟定義了更多屬性,例如數學符號或日文平假名字元:
/^\p{Math}+$/u.test('∛∞∉'); // true
/^\p{Script_Extensions=Hiragana}+$/u.test('ひらがな'); // true
如需支援的 Unicode 屬性類別完整清單,請參閱目前的規格提案。如需更多範例,請參閱這篇資訊豐富的說明文章。
遮蔽斷言
提前斷言從一開始就是 JavaScript 規則運算式語法的一部分。他們反對的斷言及斷言最終會推出。有些人可能已經記得,這已經是 V8 的一部分。我們甚至會運用 Look 斷言,實作 ES2015 中指定的 Unicode 標記。
名稱已經能充分描述它的意義。這個方法可將模式限制為僅在前方有模式時進行比對。有相符和不相符的變種版本:
/(?<=\$)\d+/.exec('$1 is worth about ¥123'); // ['1']
/(?<!\$)\d+/.exec('$1 is worth about ¥123'); // ['123']
詳情請參閱我們的上一篇網誌文章,其中專門發表斷言,以及相關 V8 測試案例的範例。
特別銘謝
這篇網誌文章之所以如此,是因為有部分已努力達成這個目標的人,便是如此。尤其是語言冠軍 Mathias Bynens、Dan Ehrenberg、Claude Pache、Brian Terlson、Thomas Wood、Gorkem Yakin 和 Irregexp guru 也貢獻了這些語言,其他員工也有所貢獻。
希望您和我們一樣,對新的規則運算式功能感到滿意!