TypeError: matchAll/replaceAll must be called with a global RegExp

当使用 String.prototype.matchAll()String.prototype.replaceAll() 方法时,如果使用的 RegExp 对象未设置 global 标志,则会抛出 JavaScript 异常 "TypeError: matchAll/replaceAll must be called with a global RegExp"。

消息

TypeError: String.prototype.matchAll called with a non-global RegExp argument (V8-based)
TypeError: String.prototype.replaceAll called with a non-global RegExp argument (V8-based)
TypeError: matchAll must be called with a global RegExp (Firefox)
TypeError: replaceAll must be called with a global RegExp (Firefox)
TypeError: String.prototype.matchAll argument must not be a non-global regular expression (Safari)
TypeError: String.prototype.replaceAll argument must not be a non-global regular expression (Safari)

错误类型

TypeError

哪里出错了?

String.prototype.matchAll()String.prototype.replaceAll() 方法要求 RegExp 对象设置 global 标志。此标志表示正则表达式可以匹配输入字符串的所有位置,而不是在第一次匹配时停止。尽管在使用这些方法时 g 标志是多余的(因为这些方法总是执行全局替换),但仍需要它们来明确意图。

值得注意的是,g 标志验证是在 matchAllreplaceAll 方法中完成的。如果你改用 RegExp[Symbol.matchAll]() 方法,则不会出现此错误,但只会有一个匹配项。

示例

无效案例

js
"abc".matchAll(/./); // TypeError
"abc".replaceAll(/./, "f"); // TypeError

有效情况

如果你打算进行全局匹配/替换:请添加 g 标志,或者如果想保持原始正则表达式不变,则使用 g 标志构造一个新的 RegExp 对象。

js
[..."abc".matchAll(/./g)]; // [[ "a" ], [ "b" ], [ "c" ]]
"abc".replaceAll(/./g, "f"); // "fff"

const existingPattern = /./;
const newPattern = new RegExp(
  existingPattern.source,
  `${existingPattern.flags}g`,
);
"abc".replaceAll(newPattern, "f"); // "fff"

如果你只打算进行单个匹配/替换:请改用 String.prototype.match()String.prototype.replace()。如果你想要一个类似 matchAll 返回的迭代器,且只包含一个匹配项,也可以使用 [Symbol.matchAll]() 方法,但这会非常令人困惑。

js
"abc".match(/./); // [ "a" ]
"abc".replace(/./, "f"); // "fbc"

[..././[Symbol.matchAll]("abc")]; // [[ "a" ]]

另见