String.prototype.replace()

Baseline 已廣泛支援

此特性已相當成熟,可在許多裝置和瀏覽器版本上使用。自 ⁨2015 年 7 月⁩以來,各瀏覽器均已提供此特性。

replace() 方法是 String 值的例項方法,它會返回一個新字串,其中一個、一些或所有匹配項都替換為 replacementpattern 可以是字串或 RegExpreplacement 可以是字串或為每個匹配項呼叫的函式。如果 pattern 是字串,則只替換第一個匹配項。原始字串保持不變。

試一試

const paragraph = "I think Ruth's dog is cuter than your dog!";

console.log(paragraph.replace("Ruth's", "my"));
// Expected output: "I think my dog is cuter than your dog!"

const regex = /dog/i;
console.log(paragraph.replace(regex, "ferret"));
// Expected output: "I think Ruth's ferret is cuter than your dog!"

語法

js
replace(pattern, replacement)

引數

pattern

可以是字串或帶有 Symbol.replace 方法的物件——典型的例子是正則表示式。任何沒有 Symbol.replace 方法的值都將被強制轉換為字串。

replacement

可以是字串或函式。

  • 如果它是一個字串,它將替換 pattern 匹配的子字串。支援一些特殊的替換模式;請參閱下面的將字串指定為替換項部分。
  • 如果它是一個函式,它將為每個匹配項呼叫,其返回值將用作替換文字。此函式提供的引數在下面的將函式指定為替換項部分中描述。

返回值

一個新字串,其中模式的一個、一些或所有匹配項都被指定的替換項替換。

描述

此方法不會更改呼叫它的字串值。它返回一個新字串。

字串模式只會被替換一次。要執行全域性搜尋和替換,請使用帶有 g 標誌的正則表示式,或者改用 replaceAll()

如果 pattern 是一個帶有 Symbol.replace 方法的物件(包括 RegExp 物件),則該方法將以目標字串和 replacement 作為引數呼叫。它的返回值將成為 replace() 的返回值。在這種情況下,replace() 的行為完全由 [Symbol.replace]() 方法編碼——例如,下面描述中提到的“捕獲組”實際上是 RegExp.prototype[Symbol.replace]() 提供的功能。

如果 pattern 是一個空字串,替換項將新增到字串的開頭。

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

帶有 g 標誌的正則表示式是 replace() 多次替換的唯一情況。有關正則表示式屬性(尤其是粘性標誌)如何與 replace() 互動的更多資訊,請參閱 RegExp.prototype[Symbol.replace]()

將字串指定為替換項

替換字串可以包含以下特殊替換模式

模式 插入
$$ 插入一個 "$"
$& 插入匹配的子字串。
$` 插入匹配子字串之前的部分。
$' 插入匹配子字串之後的部分。
$n 插入第 n 個(1-索引)捕獲組,其中 n 是小於 100 的正整數。
$<Name> 插入命名捕獲組,其中 Name 是組名。

$n$<Name> 僅在 pattern 引數是 RegExp 物件時可用。如果 pattern 是字串,或者正則表示式中不存在相應的捕獲組,則模式將按字面值替換。如果組存在但未匹配(因為它屬於析取),它將替換為空字串。

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

將函式指定為替換項

您可以將函式指定為第二個引數。在這種情況下,函式將在執行匹配後呼叫。函式的(返回值)將用作替換字串。

注意:上述特殊替換模式適用於替換函式返回的字串。

函式具有以下簽名

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

函式的引數如下

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 物件——如果是,它有多少個捕獲組。

以下示例將 newString 設定為 '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 - #$*%

如果第一個引數中的正則表示式是全域性的,則函式將為每個要替換的完整匹配項多次呼叫。

示例

在 replace() 中定義正則表示式

在以下示例中,正則表示式在 replace() 中定義,幷包含忽略大小寫標誌。

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...'

注意:有關正則表示式的更多解釋,請參閱正則表示式指南

將全域性和忽略大小寫標誌與 replace() 一起使用

全域性替換隻能透過正則表示式完成。在以下示例中,正則表示式包含全域性和忽略大小寫標誌,它允許 replace() 將字串中每個出現的 'apples' 替換為 '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'

切換字串中的單詞

以下指令碼切換字串中的單詞。對於替換文字,指令碼使用捕獲組以及 $1$2 替換模式。

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

這將記錄 'Cruz, Maria'

使用修改匹配字元的行內函數

在此示例中,字串中所有大寫字母都轉換為小寫,並在匹配位置之前插入連字元。這裡重要的是,在將匹配項作為替換項返回之前,需要對其進行額外的操作。

替換函式接受匹配的程式碼片段作為其引數,並使用它來轉換大小寫並在返回之前連線連字元。

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'

因為我們希望在進行最終替換之前進一步轉換匹配的結果,所以我們必須使用函式。這強制在 toLowerCase() 方法之前對匹配進行評估。如果我們嘗試在沒有函式的情況下使用匹配來執行此操作,則 toLowerCase() 將無效。

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

這是因為 '$&'.toLowerCase() 將首先被評估為字串字面量(結果為相同的 '$&'),然後才使用這些字元作為模式。

將華氏度替換為其攝氏度當量

以下示例將華氏度替換為其等效的攝氏度。華氏度應該是一個以 "F" 結尾的數字。該函式返回一個以 "C" 結尾的攝氏度數字。例如,如果輸入數字是 "212F",該函式返回 "100C"。如果數字是 "0F",該函式返回 "-17.77777777777778C"

正則表示式 test 檢查任何以 F 結尾的數字。華氏度數可透過其第二個引數 p1 訪問該函式。該函式根據以字串形式傳遞給 f2c() 函式的華氏度數設定攝氏度數。然後 f2c() 返回攝氏度數。此函式近似於 Perl 的 s///e 標誌。

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);
}

製作通用替換器

假設我們想要建立一個替換器,它將偏移資料附加到每個匹配的字串。由於替換器函式已經接收 offset 引數,如果正則表示式是靜態已知的,這將很簡單。

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

但是,如果我們要使其適用於任何正則表示式模式,此替換器將難以泛化。替換器是可變引數的——它接收的引數數量取決於存在的捕獲組的數量。我們可以使用剩餘引數,但它也會將 offsetstring 等收集到陣列中。groups 是否傳遞取決於正則表示式的標識,這也使得很難通用地知道哪個引數對應於 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

相反,您需要根據型別提取最後幾個引數,因為 groups 是一個物件而 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"

規範

規範
ECMAScript® 2026 語言規範
# sec-string.prototype.replace

瀏覽器相容性

另見