String.prototype.matchAll()

String 值的 matchAll() 方法返回与 正则表达式 匹配该字符串的所有结果的迭代器,包括 捕获组

¥The matchAll() method of String values returns an iterator of all results matching this string against a regular expression, including capturing groups.

Try it

语法

¥Syntax

js
matchAll(regexp)

参数

¥Parameters

regexp

正则表达式对象,或任何具有 Symbol.matchAll 方法的对象。

如果 regexp 不是 RegExp 对象并且没有 Symbol.matchAll 方法,则使用 new RegExp(regexp, 'g') 将其隐式转换为 RegExp

如果 regexp 是一个正则表达式,则它必须设置全局 (g) 标志,否则会抛出 TypeError

返回值

¥Return value

可迭代的迭代器对象(不可重新启动)匹配项或空迭代器(如果未找到匹配项)。迭代器产生的每个值都是一个与 RegExp.prototype.exec() 的返回值形状相同的数组。

¥An iterable iterator object (which is not restartable) of matches or an empty iterator if no matches are found. Each value yielded by the iterator is an array with the same shape as the return value of RegExp.prototype.exec().

例外情况

¥Exceptions

TypeError

如果 regexp 是一个正则表达式 没有设置全局 (g) 标志(其 flags 属性不包含 "g"),则抛出该错误。

描述

¥Description

String.prototype.matchAll 本身的实现非常简单 - 它只是以字符串作为第一个参数调用参数的 Symbol.matchAll 方法(除了正则表达式是全局的额外输入验证之外)。实际实现来自 RegExp.prototype[Symbol.matchAll]()

¥The implementation of String.prototype.matchAll itself is very simple — it simply calls the Symbol.matchAll method of the argument with the string as the first parameter (apart from the extra input validation that the regex is global). The actual implementation comes from RegExp.prototype[Symbol.matchAll]().

示例

¥Examples

Regexp.prototype.exec() and matchAll()

如果没有 matchAll(),可以在循环中使用对 regexp.exec()(以及带有 g 标志的正则表达式)的调用来获取所有匹配项:

¥Without matchAll(), it's possible to use calls to regexp.exec() (and regexes with the g flag) in a loop to obtain all the matches:

js
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
let match;

while ((match = regexp.exec(str)) !== null) {
  console.log(
    `Found ${match[0]} start=${match.index} end=${regexp.lastIndex}.`,
  );
}
// Found football start=6 end=14.
// Found foosball start=16 end=24.

有了 matchAll(),你就可以避免 while 循环以及 execg。相反,你可以使用一个迭代器来使用更方便的 for...of数组扩展Array.from() 构造:

¥With matchAll() available, you can avoid the while loop and exec with g. Instead, you get an iterator to use with the more convenient for...of, array spreading, or Array.from() constructs:

js
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
const matches = str.matchAll(regexp);

for (const match of matches) {
  console.log(
    `Found ${match[0]} start=${match.index} end=${
      match.index + match[0].length
    }.`,
  );
}
// Found football start=6 end=14.
// Found foosball start=16 end=24.

// matches iterator is exhausted after the for...of iteration
// Call matchAll again to create a new iterator
Array.from(str.matchAll(regexp), (m) => m[0]);
// [ "football", "foosball" ]

如果缺少 g 标志,matchAll 将引发异常。

¥matchAll will throw an exception if the g flag is missing.

js
const regexp = /[a-c]/;
const str = "abc";
str.matchAll(regexp);
// TypeError

matchAll 在内部克隆了 regexp,因此,与 regexp.exec() 不同,lastIndex 在扫描字符串时不会发生变化。

¥matchAll internally makes a clone of the regexp — so, unlike regexp.exec(), lastIndex does not change as the string is scanned.

js
const regexp = /[a-c]/g;
regexp.lastIndex = 1;
const str = "abc";
Array.from(str.matchAll(regexp), (m) => `${regexp.lastIndex} ${m[0]}`);
// [ "1 b", "1 c" ]

但是,这意味着与在循环中使用 regexp.exec() 不同,你无法改变 lastIndex 以使正则表达式前进或后退。

¥However, this means that unlike using regexp.exec() in a loop, you can't mutate lastIndex to make the regex advance or rewind.

更好地访问捕获组(比 String.prototype.match())

¥Better access to capturing groups (than String.prototype.match())

matchAll 的另一个令人信服的原因是改进了对捕获组的访问。

¥Another compelling reason for matchAll is the improved access to capture groups.

match() 与全局 g 标志一起使用时,捕获组将被忽略:

¥Capture groups are ignored when using match() with the global g flag:

js
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";

str.match(regexp); // ['test1', 'test2']

使用 matchAll,你可以轻松访问捕获组:

¥Using matchAll, you can access capture groups easily:

js
const array = [...str.matchAll(regexp)];

array[0];
// ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4]
array[1];
// ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4]

使用 matchAll() 使用非 RegExp 实现 [Symbol.matchAll]()

¥Using matchAll() with a non-RegExp implementing [Symbol.matchAll]()

如果一个对象有 Symbol.matchAll 方法,它可以用作自定义匹配器。Symbol.matchAll 的返回值成为 matchAll() 的返回值。

¥If an object has a Symbol.matchAll method, it can be used as a custom matcher. The return value of Symbol.matchAll becomes the return value of matchAll().

js
const str = "Hmm, this is interesting.";

str.matchAll({
  [Symbol.matchAll](str) {
    return [["Yes, it's interesting."]];
  },
}); // returns [["Yes, it's interesting."]]

规范

Specification
ECMAScript Language Specification
# sec-string.prototype.matchall

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看