matchall返回regexpstringiterator,仅支持for...of、展开运算符或next();具名捕获组需显式声明且正则必须带g标志,groups为只读对象,未匹配组值为undefined。

matchAll 返回的是迭代器,不能直接用 for...in 遍历
很多人写 for (const match in str.matchAll(regex)),结果什么也拿不到——matchAll 返回的是一个 RegExpStringIterator,它只支持 for...of、展开运算符或手动调用 next(),for...in 遍历的是对象属性名,不是匹配结果。
正确做法是用 for...of 或转成数组:
const str = "id:123 name:alice age:30";
const regex = /(?<key>\w+):(?<value>\w+)/g;
for (const match of str.matchAll(regex)) {
console.log(match.groups); // { key: "id", value: "123" } 等
}</value></key>
具名捕获组必须在正则中显式声明,且全局标志 g 不可省略
matchAll 的设计前提就是“找所有匹配”,如果正则没带 g 标志,它只会返回第一个匹配(和 exec 行为一致),后续调用 next() 全是 { done: true }。
具名捕获组语法是 (?<name>...)</name>,名字只能是合法标识符(不能以数字开头、不能含短横线等),且区分大小写:
-
/(?<userid>\d+)/g</userid>✅ -
/(?<user-id>\d+)/g</user-id>❌(解析失败,SyntaxError) -
/(?\w+)/g❌(非法标识符)
不加 g 时,matchAll 不报错,但只产出一次结果,容易误以为漏匹配。
matchAll 每次 yield 的 match 对象结构固定,groups 是只读属性
每个 match 是一个 Array 实例,除了索引访问捕获内容(match[0] 是全匹配,match[1] 是第一个捕获组),还带三个关键属性:
-
match.index:本次匹配在原字符串中的起始位置 -
match.input:原始输入字符串 -
match.groups:一个普通对象,键是具名捕获组名,值是对应匹配内容;若某组未参与匹配(比如分支中未命中),值为undefined
注意:match.groups 是只读的,改它不会影响后续匹配;也没有 match.groupNames 这种 API,组名只能从正则源码里提取(需解析 regex.source 字符串)。
处理空匹配或可选组时,groups 中对应字段为 undefined 而非空字符串
比如正则 /(?<pre class="brush:php;toolbar:false;" fix>pre-)?(?<main>\w+)/g</main></pre> 匹配 "item",match.groups.prefix 是 undefined,不是 ""。这和 exec 行为一致,但容易在解构赋值时出错:
const { prefix = "", main } = match.groups; // 必须显式提供默认值
另外,如果正则有零宽断言或空字符匹配(如 /(?<sep>^|$)/g</sep>),match.groups.sep 会是 "",因为确实匹配到了空字符串——这取决于正则是否实际消费了字符,而不是“有没有写 ?”。
真正难调试的是嵌套具名组 + 可选量词组合,比如 /(?<a>(?:x(?<b>y)?)?)/g</b></a>,此时 b 在 a 存在但 y 缺失时也会是 undefined,需要逐层检查 groups.a 是否存在再取 b。











