RegExp.prototype[Symbol.replace]()

RegExp 实例的 [Symbol.replace]() 方法指定当正则表达式作为模式传入时 String.prototype.replace()String.prototype.replaceAll() 应如何表现。

¥The [Symbol.replace]() method of RegExp instances specifies how String.prototype.replace() and String.prototype.replaceAll() should behave when the regular expression is passed in as the pattern.

Try it

语法

¥Syntax

js
regexp[Symbol.replace](str, replacement)

参数

¥Parameters

str

作为替换对象的 String

replacement

: 可以是字符串或函数。

  • 如果是字符串,它将替换当前正则表达式匹配的子字符串。支持多种特殊替换模式;请参阅 String.prototype.replace指定字符串作为替换 部分。
  • 如果它是一个函数,它将在每次匹配时调用它,并将返回值用作替换文本。提供给该函数的参数在 String.prototype.replace指定一个函数作为替换 部分中描述。

返回值

¥Return value

一个新字符串,其中模式的一个、部分或全部匹配项被指定的替换所替换。

¥A new string, with one, some, or all matches of the pattern replaced by the specified replacement.

描述

¥Description

如果 pattern 参数是 RegExp 对象,则在 String.prototype.replace()String.prototype.replaceAll() 内部调用此方法。例如,以下两个示例返回相同的结果。

¥This method is called internally in String.prototype.replace() and String.prototype.replaceAll() if the pattern argument is a RegExp object. For example, the following two examples return the same result.

js
"abc".replace(/a/, "A");

/a/[Symbol.replace]("abc", "A");

如果正则表达式是全局的(带有 g 标志),则将重复调用正则表达式的 exec() 方法,直到 exec() 返回 null。否则,exec() 只会被调用一次。对于每个 exec() 结果,将根据 String.prototype.replace() 中的描述准备替换。

¥If the regex is global (with the g flag), the regex's exec() method will be repeatedly called until exec() returns null. Otherwise, exec() would only be called once. For each exec() result, the substitution will be prepared based on the description in String.prototype.replace().

因为 [Symbol.replace]() 会一直调用 exec() 直到返回 null,而当最后一次匹配失败时,exec() 会自动将正则表达式的 lastIndex 重置为 0,所以 [Symbol.replace]() 在退出时通常不会产生副作用。但是,当正则表达式为 sticky 但不是全局时,lastIndex 不会被重置。在这种情况下,每次调用 replace() 可能会返回不同的结果。

¥Because [Symbol.replace]() would keep calling exec() until it returns null, and exec() would automatically reset the regex's lastIndex to 0 when the last match fails, [Symbol.replace]() would typically not have side effects when it exits. However, when the regex is sticky but not global, lastIndex would not be reset. In this case, each call to replace() may return a different result.

js
const re = /a/y;

for (let i = 0; i < 5; i++) {
  console.log("aaa".replace(re, "b"), re.lastIndex);
}

// baa 1
// aba 2
// aab 3
// aaa 0
// baa 1

当正则表达式是粘性和全局性时,它仍然会执行粘性匹配 - 即,它将无法匹配 lastIndex 之外的任何匹配项。

¥When the regex is sticky and global, it would still perform sticky matches — i.e. it would fail to match any occurrences beyond the lastIndex.

js
console.log("aa-a".replace(/a/gy, "b")); // "bb-a"

如果当前匹配是空字符串,则 lastIndex 仍会提前 - 如果正则表达式是 Unicode 感知,则它将提前一个 Unicode 代码点;否则,前进一个 UTF-16 代码单元。

¥If the current match is an empty string, the lastIndex would still be advanced — if the regex is Unicode-aware, it would advance by one Unicode code point; otherwise, it advances by one UTF-16 code unit.

js
console.log("😄".replace(/(?:)/g, " ")); // " \ud83d \ude04 "
console.log("😄".replace(/(?:)/gu, " ")); // " 😄 "

此方法用于自定义 RegExp 子类中的替换行为。

¥This method exists for customizing replace behavior in RegExp subclasses.

示例

¥Examples

直接致电

¥Direct call

该方法的使用方式与 String.prototype.replace() 几乎相同,只是 this 和参数顺序不同。

¥This method can be used in almost the same way as String.prototype.replace(), except the different this and the different arguments order.

js
const re = /-/g;
const str = "2016-01-01";
const newstr = re[Symbol.replace](str, ".");
console.log(newstr); // 2016.01.01

在子类中使用 [Symbol.replace]()

¥Using [Symbol.replace]() in subclasses

RegExp 的子类可以重写 [Symbol.replace]() 方法来修改默认行为。

¥Subclasses of RegExp can override the [Symbol.replace]() method to modify the default behavior.

js
class MyRegExp extends RegExp {
  constructor(pattern, flags, count) {
    super(pattern, flags);
    this.count = count;
  }
  [Symbol.replace](str, replacement) {
    // Perform [Symbol.replace]() `count` times.
    let result = str;
    for (let i = 0; i < this.count; i++) {
      result = RegExp.prototype[Symbol.replace].call(this, result, replacement);
    }
    return result;
  }
}

const re = new MyRegExp("\\d", "", 3);
const str = "01234567";
const newstr = str.replace(re, "#"); // String.prototype.replace calls re[Symbol.replace]().
console.log(newstr); // ###34567

规范

Specification
ECMAScript Language Specification
# sec-regexp.prototype-@@replace

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看