TypeError: matchAll/replaceAll 必须与全局正则表达式一起使用

String.prototype.matchAll()String.prototype.replaceAll() 方法与没有设置 global 标志的 RegExp 对象一起使用时,会发生 JavaScript 异常 "TypeError: matchAll/replaceAll 必须使用全局 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)

错误类型

出了什么问题?

String.prototype.matchAll()String.prototype.replaceAll() 方法需要一个设置了 global 标志的 RegExp 对象。此标志表示正则表达式可以匹配输入字符串的所有位置,而不是在第一个匹配项处停止。虽然在使用这些方法时 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" ]]

另请参阅