String.prototype.replace()
replace() 方法是 String 值的例項方法,它會返回一個新字串,其中一個、一些或所有匹配項都替換為 replacement。pattern 可以是字串或 RegExp,replacement 可以是字串或為每個匹配項呼叫的函式。如果 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!"
語法
replace(pattern, replacement)
引數
pattern-
可以是字串或帶有
Symbol.replace方法的物件——典型的例子是正則表示式。任何沒有Symbol.replace方法的值都將被強制轉換為字串。 replacement-
可以是字串或函式。
返回值
一個新字串,其中模式的一個、一些或所有匹配項都被指定的替換項替換。
描述
此方法不會更改呼叫它的字串值。它返回一個新字串。
字串模式只會被替換一次。要執行全域性搜尋和替換,請使用帶有 g 標誌的正則表示式,或者改用 replaceAll()。
如果 pattern 是一個帶有 Symbol.replace 方法的物件(包括 RegExp 物件),則該方法將以目標字串和 replacement 作為引數呼叫。它的返回值將成為 replace() 的返回值。在這種情況下,replace() 的行為完全由 [Symbol.replace]() 方法編碼——例如,下面描述中提到的“捕獲組”實際上是 RegExp.prototype[Symbol.replace]() 提供的功能。
如果 pattern 是一個空字串,替換項將新增到字串的開頭。
"xxx".replace("", "_"); // "_xxx"
帶有 g 標誌的正則表示式是 replace() 多次替換的唯一情況。有關正則表示式屬性(尤其是粘性標誌)如何與 replace() 互動的更多資訊,請參閱 RegExp.prototype[Symbol.replace]()。
將字串指定為替換項
替換字串可以包含以下特殊替換模式
| 模式 | 插入 |
|---|---|
$$ |
插入一個 "$"。 |
$& |
插入匹配的子字串。 |
$` |
插入匹配子字串之前的部分。 |
$' |
插入匹配子字串之後的部分。 |
$n |
插入第 n 個(1-索引)捕獲組,其中 n 是小於 100 的正整數。 |
$<Name> |
插入命名捕獲組,其中 Name 是組名。 |
$n 和 $<Name> 僅在 pattern 引數是 RegExp 物件時可用。如果 pattern 是字串,或者正則表示式中不存在相應的捕獲組,則模式將按字面值替換。如果組存在但未匹配(因為它屬於析取),它將替換為空字串。
"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
將函式指定為替換項
您可以將函式指定為第二個引數。在這種情況下,函式將在執行匹配後呼叫。函式的(返回值)將用作替換字串。
注意:上述特殊替換模式不適用於替換函式返回的字串。
函式具有以下簽名
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 - #$*%'
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() 中定義,幷包含忽略大小寫標誌。
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'。
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 替換模式。
const re = /(\w+)\s(\w+)/;
const str = "Maria Cruz";
const newStr = str.replace(re, "$2, $1");
console.log(newStr); // Cruz, Maria
這將記錄 'Cruz, Maria'。
使用修改匹配字元的行內函數
在此示例中,字串中所有大寫字母都轉換為小寫,並在匹配位置之前插入連字元。這裡重要的是,在將匹配項作為替換項返回之前,需要對其進行額外的操作。
替換函式接受匹配的程式碼片段作為其引數,並使用它來轉換大小寫並在返回之前連線連字元。
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() 將無效。
// 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 標誌。
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 引數,如果正則表示式是靜態已知的,這將很簡單。
"abcd".replace(/(bc)/, (match, p1, offset) => `${match} (${offset}) `);
// "abc (1) d"
但是,如果我們要使其適用於任何正則表示式模式,此替換器將難以泛化。替換器是可變引數的——它接收的引數數量取決於存在的捕獲組的數量。我們可以使用剩餘引數,但它也會將 offset、string 等收集到陣列中。groups 是否傳遞取決於正則表示式的標識,這也使得很難通用地知道哪個引數對應於 offset。
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 是一個字串。
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 |
瀏覽器相容性
載入中…