String.prototype.replace()

String 值的 replace() 方法返回一个新字符串,其中 pattern 的一个、部分或全部匹配项被 replacement 替换。pattern 可以是字符串或 RegExpreplacement 可以是字符串或每次匹配调用的函数。如果 pattern 是字符串,则仅替换第一次出现的位置。原始字符串保持不变。

¥The replace() method of String values returns a new string with one, some, or all matches of a pattern replaced by a replacement. The pattern can be a string or a RegExp, and the replacement can be a string or a function called for each match. If pattern is a string, only the first occurrence will be replaced. The original string is left unchanged.

Try it

语法

¥Syntax

js
replace(pattern, replacement)

参数

¥Parameters

pattern

可以是字符串或具有 Symbol.replace 方法的对象 - 典型示例是 正则表达式。任何不具有 Symbol.replace 方法的值都将被强制转换为字符串。

replacement

: 可以是字符串或函数。

  • 如果是字符串,则会替换 pattern 匹配的子字符串。支持多种特殊替换模式;请参阅下面的 指定字符串作为替换 部分。
  • 如果它是一个函数,它将在每次匹配时调用它,并将其返回值用作替换文本。下面的 指定一个函数作为替换 部分描述了提供给该函数的参数。

返回值

¥Return value

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

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

描述

¥Description

此方法不会改变它所调用的字符串值。它返回一个新字符串。

¥This method does not mutate the string value it's called on. It returns a new string.

字符串模式只会被替换一次。要执行全局搜索和替换,请使用带有 g 标志的正则表达式,或改用 replaceAll()

¥A string pattern will only be replaced once. To perform a global search and replace, use a regular expression with the g flag, or use replaceAll() instead.

如果 pattern 是具有 Symbol.replace 方法的对象(包括 RegExp 对象),则使用目标字符串和 replacement 作为参数来调用该方法。它的返回值成为 replace() 的返回值。在这种情况下,replace() 的行为完全由 @@replace 方法编码 - 例如,下面描述中提到的 "捕获组" 实际上是 RegExp.prototype[@@replace] 提供的功能。

¥If pattern is an object with a Symbol.replace method (including RegExp objects), that method is called with the target string and replacement as arguments. Its return value becomes the return value of replace(). In this case the behavior of replace() is entirely encoded by the @@replace method — for example, any mention of "capturing groups" in the description below is actually functionality provided by RegExp.prototype[@@replace].

如果 pattern 是空字符串,则替换内容将添加到字符串的开头。

¥If the pattern is an empty string, the replacement is prepended to the start of the string.

js
"xxx".replace("", "_"); // "_xxx"

带有 g 标志的正则表达式是 replace() 替换多次的唯一情况。有关正则表达式属性(尤其是 sticky 标志)如何与 replace() 交互的更多信息,请参阅 RegExp.prototype[@@replace]()

¥A regexp with the g flag is the only case where replace() replaces more than once. For more information about how regex properties (especially the sticky flag) interact with replace(), see RegExp.prototype[@@replace]().

指定字符串作为替换

¥Specifying a string as the replacement

替换字符串可以包含以下特殊替换模式:

¥The replacement string can include the following special replacement patterns:

图案 刀片
$$ 插入 "$"
$& 插入匹配的子字符串。
`$`` 插入匹配子字符串之前的字符串部分。
$' 插入匹配子字符串后面的字符串部分。
$n 插入第 n 个(1 索引)捕获组,其中 n 是小于 100 的正整数。
$<Name> 插入命名的捕获组,其中 Name 是组名称。

仅当 pattern 参数是 RegExp 对象时,$n$<Name> 才可用。如果 pattern 是字符串,或者正则表达式中不存在相应的捕获组,则该模式将被替换为文字。如果该组存在但不匹配(因为它是析取的一部分),它将被替换为空字符串。

¥$n and $<Name> are only available if the pattern argument is a RegExp object. If the pattern is a string, or if the corresponding capturing group isn't present in the regex, then the pattern will be replaced as a literal. If the group is present but isn't matched (because it's part of a disjunction), it will be replaced with an empty string.

js
"foo".replace(/(f)/, "$2");
// "$2oo"; the regex doesn't have the second group

"foo".replace("f", "$1");
// "$1oo"; the pattern is a string, so it doesn't have any groups

"foo".replace(/(f)|(g)/, "$2");
// "oo"; the second group exists but isn't matched

指定一个函数作为替换

¥Specifying a function as the replacement

你可以指定一个函数作为第二个参数。在这种情况下,将在执行匹配后调用该函数。函数的结果(返回值)将用作替换字符串。

¥You can specify a function as the second parameter. In this case, the function will be invoked after the match has been performed. The function's result (return value) will be used as the replacement string.

注意:上述特殊替换模式不适用于从 Replacer 函数返回的字符串。

¥Note: The above-mentioned special replacement patterns do not apply for strings returned from the replacer function.

该函数具有以下签名:

¥The function has the following signature:

js
function replacer(match, p1, p2, /* …, */ pN, offset, string, groups) {
  return replacement;
}

该函数的参数如下:

¥The arguments to the function are as follows:

match

匹配的子串。(对应上面的 $&。)

p1, p2, …, pN

捕获组(包括命名捕获组)找到的第 n 个字符串,前提是 replace() 的第一个参数是 RegExp 对象。(对应上面的 $1$2 等。)例如,如果 pattern/(\a+)(\b+)/,则 p1\a+ 的匹配,p2\b+ 的匹配。如果该组是析取的一部分(例如 "abc".replace(/(a)|(b)/, replacer)),则不匹配的替代项将是 undefined

offset

所检查的整个字符串中匹配子字符串的偏移量。例如,如果整个字符串是 'abcd',匹配的子字符串是 'bc',则该参数将为 1

string

正在检查整个字符串。

groups

一个对象,其键是使用的组名称,其值是匹配部分(如果不匹配则为 undefined)。仅当 pattern 包含至少一个命名捕获组时才存在。

参数的确切数量取决于第一个参数是否是 RegExp 对象 - 如果是,则它有多少个捕获组。

¥The exact number of arguments depends on whether the first argument is a RegExp object — and, if so, how many capture groups it has.

以下示例将 newString 设置为 'abc - 12345 - #$*%'

¥The following example will set newString to 'abc - 12345 - #$*%':

js
function replacer(match, p1, p2, p3, offset, string) {
  // p1 is non-digits, p2 digits, and p3 non-alphanumerics
  return [p1, p2, p3].join(" - ");
}
const newString = "abc12345#$*%".replace(/([^\d]*)(\d*)([^\w]*)/, replacer);
console.log(newString); // abc - 12345 - #$*%

如果第一个参数中的正则表达式是全局的,则对于要替换的每个完整匹配项,该函数将被多次调用。

¥The function will be invoked multiple times for each full match to be replaced if the regular expression in the first parameter is global.

示例

¥Examples

在 replace()中定义正则表达式

¥Defining the regular expression in replace()

在以下示例中,正则表达式在 replace() 中定义并包含忽略大小写标志。

¥In the following example, the regular expression is defined in replace() and includes the ignore case flag.

js
const str = "Twas the night before Xmas...";
const newstr = str.replace(/xmas/i, "Christmas");
console.log(newstr); // Twas the night before Christmas...

这会记录 'Twas the night before Christmas...'

¥This logs 'Twas the night before Christmas...'.

注意:有关正则表达式的更多说明,请参阅 正则表达式指南

¥Note: See the regular expression guide for more explanations about regular expressions.

将全局和 ignoreCase 标志与 replace()一起使用

¥Using the global and ignoreCase flags with replace()

全局替换只能使用正则表达式来完成。在以下示例中,正则表达式包括 全局和忽略大小写标志,它允许 replace() 将字符串中每次出现的 'apples' 替换为 'oranges'

¥Global replace can only be done with a regular expression. In the following example, the regular expression includes the global and ignore case flags which permits replace() to replace each occurrence of 'apples' in the string with 'oranges'.

js
const re = /apples/gi;
const str = "Apples are round, and apples are juicy.";
const newstr = str.replace(re, "oranges");
console.log(newstr); // oranges are round, and oranges are juicy.

这会记录 'oranges are round, and oranges are juicy'

¥This logs 'oranges are round, and oranges are juicy'.

交换字符串中的单词

¥Switching words in a string

以下脚本切换字符串中的单词。对于替换文本,脚本使用 捕获组 以及 $1$2 替换模式。

¥The following script switches the words in the string. For the replacement text, the script uses capturing groups and the $1 and $2 replacement patterns.

js
const re = /(\w+)\s(\w+)/;
const str = "Maria Cruz";
const newstr = str.replace(re, "$2, $1");
console.log(newstr); // Cruz, Maria

这会记录 'Cruz, Maria'

¥This logs 'Cruz, Maria'.

使用修改匹配字符的内联函数

¥Using an inline function that modifies the matched characters

在此示例中,字符串中所有出现的大写字母都将转换为小写,并在匹配位置之前插入连字符。这里重要的是,在将匹配的物品作为替换件返还之前,需要对匹配的物品进行额外的操作。

¥In this example, all occurrences of capital letters in the string are converted to lower case, and a hyphen is inserted just before the match location. The important thing here is that additional operations are needed on the matched item before it is given back as a replacement.

替换函数接受匹配的代码片段作为其参数,并使用它来转换大小写并在返回之前连接连字符。

¥The replacement function accepts the matched snippet as its parameter, and uses it to transform the case and concatenate the hyphen before returning.

js
function styleHyphenFormat(propertyName) {
  function upperToHyphenLower(match, offset, string) {
    return (offset > 0 ? "-" : "") + match.toLowerCase();
  }
  return propertyName.replace(/[A-Z]/g, upperToHyphenLower);
}

给定 styleHyphenFormat('borderTop'),返回 'border-top'

¥Given styleHyphenFormat('borderTop'), this returns 'border-top'.

因为我们想要在最终替换之前进一步转换比赛结果,所以我们必须使用一个函数。这迫使在 toLowerCase() 方法之前对匹配进行评估。如果我们尝试使用不带函数的匹配来执行此操作,则 toLowerCase() 将不起作用。

¥Because we want to further transform the result of the match before the final substitution is made, we must use a function. This forces the evaluation of the match prior to the toLowerCase() method. If we had tried to do this using the match without a function, the toLowerCase() would have no effect.

js
// Won't work
const newString = propertyName.replace(/[A-Z]/g, "-" + "$&".toLowerCase());

这是因为在使用字符作为模式之前,'$&'.toLowerCase() 首先会被评估为字符串文字(导致相同的 '$&')。

¥This is because '$&'.toLowerCase() would first be evaluated as a string literal (resulting in the same '$&') before using the characters as a pattern.

将华氏度替换为相应的摄氏度

¥Replacing a Fahrenheit degree with its Celsius equivalent

以下示例将华氏度替换为其等效的摄氏度。华氏度应该是以 "F" 结尾的数字。该函数返回以 "C" 结尾的摄氏度。例如,如果输入数字为 "212F",则函数返回 "100C"。如果数字是 "0F",则该函数返回 "-17.77777777777778C"

¥The following example replaces a Fahrenheit degree with its equivalent Celsius degree. The Fahrenheit degree should be a number ending with "F". The function returns the Celsius number ending with "C". For example, if the input number is "212F", the function returns "100C". If the number is "0F", the function returns "-17.77777777777778C".

正则表达式 test 检查是否有任何以 F 结尾的数字。该函数可通过其第二个参数 p1 访问华氏度数。该函数根据字符串中传递给 f2c() 函数的华氏度数设置摄氏度。然后 f2c() 返回摄氏度。该函数近似于 Perl 的 s///e 标志。

¥The regular expression test checks for any number that ends with F. The number of Fahrenheit degrees is accessible to the function through its second parameter, p1. The function sets the Celsius number based on the number of Fahrenheit degrees passed in a string to the f2c() function. f2c() then returns the Celsius number. This function approximates Perl's s///e flag.

js
function f2c(x) {
  function convert(str, p1, offset, s) {
    return `${((p1 - 32) * 5) / 9}C`;
  }
  const s = String(x);
  const test = /(-?\d+(?:\.\d*)?)F\b/g;
  return s.replace(test, convert);
}

制作通用替代品

¥Making a generic replacer

假设我们要创建一个替换器,将偏移量数据附加到每个匹配的字符串。因为替换函数已经接收了 offset 参数,所以如果正则表达式是静态已知的,那么这将是微不足道的。

¥Suppose we want to create a replacer that appends the offset data to every matched string. Because the replacer function already receives the offset parameter, it will be trivial if the regex is statically known.

js
"abcd".replace(/(bc)/, (match, p1, offset) => `${match} (${offset}) `);
// "abc (1) d"

然而,如果我们希望它能够与任何正则表达式模式一起使用,那么这个替换器将很难概括。替换器是可变的 - 它接收的参数数量取决于存在的捕获组的数量。我们可以使用 其余参数,但它也会将 offsetstring 等收集到数组中。事实上,groups 可能会或可能不会被传递取决于正则表达式的身份,这也使得很难一般地知道哪个参数对应于 offset

¥However, this replacer would be hard to generalize if we want it to work with any regex pattern. The replacer is variadic — the number of arguments it receives depends on the number of capturing groups present. We can use rest parameters, but it would also collect offset, string, etc. into the array. The fact that groups may or may not be passed depending on the identity of the regex would also make it hard to generically know which argument corresponds to the offset.

js
function addOffset(match, ...args) {
  const offset = args.at(-2);
  return `${match} (${offset}) `;
}

console.log("abcd".replace(/(bc)/, addOffset)); // "abc (1) d"
console.log("abcd".replace(/(?<group>bc)/, addOffset)); // "abc (abcd) d"

当正则表达式包含命名组时,上面的 addOffset 示例不起作用,因为在这种情况下,args.at(-2) 将是 string 而不是 offset

¥The addOffset example above doesn't work when the regex contains a named group, because in this case args.at(-2) would be the string instead of the offset.

相反,你需要根据类型提取最后几个参数,因为 groups 是一个对象,而 string 是一个字符串。

¥Instead, you need to extract the last few arguments based on type, because groups is an object while string is a string.

js
function addOffset(match, ...args) {
  const hasNamedGroups = typeof args.at(-1) === "object";
  const offset = hasNamedGroups ? args.at(-3) : args.at(-2);
  return `${match} (${offset}) `;
}

console.log("abcd".replace(/(bc)/, addOffset)); // "abc (1) d"
console.log("abcd".replace(/(?<group>bc)/, addOffset)); // "abc (1) d"

规范

Specification
ECMAScript Language Specification
# sec-string.prototype.replace

¥Specifications

浏览器兼容性

BCD tables only load in the browser

¥Browser compatibility

也可以看看