试一试
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";
const array = [...str.matchAll(regexp)];
console.log(array[0]);
// Expected output: Array ["test1", "e", "st1", "1"]
console.log(array[1]);
// Expected output: Array ["test2", "e", "st2", "2"]
语法
matchAll(regexp)
参数
regexp-
一个正则表达式对象,或者任何具有
Symbol.matchAll方法的对象。如果
regexp不是RegExp对象且不具有Symbol.matchAll方法,它将通过使用new RegExp(regexp, 'g')被隐式转换为RegExp。
返回值
一个 可迭代的迭代器对象(不可重新启动),包含匹配项,或者在未找到匹配项时返回一个空迭代器。迭代器产生的每个值都是一个数组,其形状与 RegExp.prototype.exec() 的返回值相同。
异常
描述
String.prototype.matchAll 的实现除了对正则表达式是否全局进行额外输入验证之外,主要就是调用参数的 Symbol.matchAll 方法,并将字符串作为第一个参数传入。实际的实现来自 RegExp.prototype[Symbol.matchAll]()。
示例
Regexp.prototype.exec() 和 matchAll()
在 matchAll() 出现之前,可以通过在循环中使用 regexp.exec() 调用(以及设置了 g 标志的正则表达式)来获取所有匹配项。
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 循环和带 g 的 exec。取而代之的是,你可以获取一个迭代器,并使用更方便的 for...of、数组展开 或 Array.from() 构造。
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 将抛出异常。
const regexp = /[a-c]/;
const str = "abc";
str.matchAll(regexp);
// TypeError
matchAll 内部会创建一个 regexp 的克隆——因此,与 regexp.exec() 不同,在扫描字符串时 lastIndex 不会改变。
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 来让正则表达式前进或后退。
比 String.prototype.match() 更方便地访问捕获组
matchAll 另一个引人注目的原因是它改进了对捕获组的访问。
当使用带有全局 g 标志的 match() 时,捕获组会被忽略。
const regexp = /t(e)(st(\d?))/g;
const str = "test1test2";
str.match(regexp); // ['test1', 'test2']
使用 matchAll,你可以轻松访问捕获组。
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() 与实现了 [Symbol.matchAll]() 的非 RegExp 对象一起使用
如果一个对象具有 Symbol.matchAll 方法,它就可以被用作自定义匹配器。Symbol.matchAll 的返回值将成为 matchAll() 的返回值。
const str = "Hmm, this is interesting.";
str.matchAll({
[Symbol.matchAll](str) {
return [["Yes, it's interesting."]];
},
}); // returns [["Yes, it's interesting."]]
规范
| 规范 |
|---|
| ECMAScript® 2026 语言规范 # sec-string.prototype.matchall |
浏览器兼容性
加载中…