使用 String.prototype.matchAll() 提高比對結果

Joe Medley
Joe Medley

Chrome 73 推出 String.prototype.matchAll() 方法。它的行為類似於 match(),但會傳回迭代器,其中包含全域或黏性規則運算式中的所有規則運算式比對結果。這可提供簡單的方法,讓您重複執行相符項目,特別是在需要存取擷取群組時。

match() 有什麼問題?

簡單來說,除非您嘗試使用擷取群組傳回全域比對結果,否則不需要。以下是程式設計謎題,請考慮使用以下程式碼:

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const results = string.match(regex);
console.log(results);
// → ['test1', 'test2']

在控制台中執行這段程式碼,您會發現它會傳回包含字串 'test1''test2' 的陣列。如果從規則運算式中移除 g 標記,我會取得所有擷取群組,但只會取得第一個相符項目。這是訂閱按鈕的圖示:

['test1', 'e', 'st1', '2', index: 0, input: 'test1test2', groups: undefined]

這個字串包含第二個可能的 'test2' 開頭比對結果,但我沒有這個字串。接下來是謎題:如何取得每個相符項目的所有擷取群組?String.prototype.matchAll() 提案的說明說明瞭兩種可能的方法。我不會描述這些內容,因為希望您很快就不需要這些內容。

String.prototype.matchAll()

matchAll() 的說明範例會是什麼樣子?瞧一眼吧。

const regex = /t(e)(st(\d?))/g;
const string = 'test1test2';
const matches = string.matchAll(regex);
for (const match of matches) {
  console.log(match);
}

這裡有幾點需要注意。match() 會在全域搜尋中傳回陣列,而 matchAll() 會傳回迭代器,可與 for...of 迴圈完美搭配運作。迭代器會為每個比對結果產生陣列,包括擷取群組和一些額外項目。如果您將這些內容列印到控制台中,它們會如下所示:

['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', groups: undefined]
['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', groups: undefined]

您可能會注意到,每個比對的值都是陣列,格式與 match() 針對非全域規則運算式傳回的格式完全相同。

額外內容

這篇文章主要適用於不熟悉或不擅長正規表示式的使用者。您可能會注意到,match() 和 matchAll() 的結果 (針對每個迭代) 都是陣列,其中包含一些額外的命名屬性。在準備這篇文章時,我發現這些屬性在 MDN 上有某些文件缺失情形 (我已修正)。以下簡要說明。

index
原始字串中第一個結果的索引。在上述範例中,test2 從第 5 個位置開始,因此 index 的值為 5。
input
系統執行 matchAll() 的完整字串。在我的範例中,這個值是 'test1test2'
groups
包含規則運算式中指定的任何命名擷取群組結果。

結論

如果我遺漏了任何內容,請在下方留言告訴我。如要進一步瞭解 JavaScript 的近期變更,請參閱先前的更新V8 網站