String.prototype.matchAll()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since January 2020.
尝试一下
语法
matchAll(regexp)
参数
regexp
-
一个正则表达式对象,或者是任何具有
Symbol.matchAll
方法的对象。如果
regexp
不是一个RegExp
对象,并且没有Symbol.matchAll
方法,它将通过new RegExp(regexp, 'g')
被隐式转换为一个RegExp
对象。
返回值
一个匹配结果的可迭代迭代器对象(它不可重新开始)。每个匹配结果都是一个数组,其形状与 RegExp.prototype.exec()
的返回值相同。
异常
描述
String.prototype.matchAll
方法本身的实现非常简单,它只是调用了参数的 Symbol.matchAll
方法,并将字符串作为第一个参数传递了进去(除了额外的输入验证,即正则表达式必须是全局的)。实际的实现来自 RegExp.prototypeSymbol.matchAll]()
。
示例
Regexp.prototype.exec() 和 matchAll()
如果没有 matchAll()
方法,仍然可以使用带有 g
标志的正则表达式调用 regexp.exec()
来在循环中获取所有匹配结果:
const regexp = /foo[a-z]*/g;
const str = "table football, foosball";
let match;
while ((match = regexp.exec(str)) !== null) {
console.log(
`找到 ${match[0]} 起始位置=${match.index} 结束位置=${regexp.lastIndex}。`,
);
}
// 找到 football 起始位置=6 结束位置=14。
// 找到 foosball 起始位置=16 结束位置=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(
`找到 ${match[0]} 起始位置=${match.index} 结束位置=${
match.index + match[0].length
}.`,
);
}
// 找到 football 起始位置=6 结束位置=14.
// 找到 foosball 起始位置=16 结束位置=24.
// 匹配迭代器在 for...of 迭代后用尽
// 再次调用 matchAll 以创建新的迭代器
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]
使用实现了 [Symbol.matchAll]()
的非正则对象调用 matchAll()
如果一个对象有一个 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."]]
规范
Specification |
---|
ECMAScript Language Specification # sec-string.prototype.matchall |
浏览器兼容性
BCD tables only load in the browser