How do I replace all occurrences of a string?

How do I replace all occurrences of a string?

技术背景

在 JavaScript 开发中,经常会遇到需要替换字符串中所有指定子字符串的需求。虽然现代浏览器支持 String.prototype.replaceAll() 方法,但在处理旧浏览器或特定场景时,我们需要了解更多实现方式。

实现步骤

现代浏览器使用 String.prototype.replaceAll()

从 2020 年 8 月起,现代浏览器开始支持 ECMAScript 2021 语言规范中定义的 String.prototype.replaceAll() 方法。

1
2
let result = "1 abc 2 abc 3".replaceAll("abc", "xyz");
// result 是 "1 xyz 2 xyz 3"

旧浏览器或不支持 replaceAll 的环境

正则表达式实现

1
2
3
4
5
6
7
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& 表示整个匹配的字符串
}

function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

拆分和拼接实现

1
2
3
function replaceAll(str, find, replace) {
return str.split(find).join(replace);
}

性能考虑

在 Chrome Windows 8 机器上的测试表明,基于正则表达式的实现最快,拆分和拼接实现比正则表达式实现慢 53%。

处理特殊字符

正则表达式包含特殊(元)字符,因此在传递 find 参数时需要先进行转义处理,避免出现意外结果。

1
2
3
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

兼容性处理

replaceAll 填充函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (!String.prototype.replaceAll) {
Object.defineProperty(String.prototype, 'replaceAll', {
configurable: true,
writable: true,
enumerable: false,
value: function(search, replace) {
return this.replace(
Object.prototype.toString.call(search) === '[object RegExp]'
? search.global
? search
: RegExp(search.source, /\/([a-z]*)$/.exec(search.toString())[1] + 'g')
: RegExp(String(search).replace(/[.^$*+?()[{|\\]/g, "\\$&"), "g"),
replace
);
}
});
}

核心代码

正则表达式替换

1
2
3
4
5
6
7
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}

function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}

拆分和拼接替换

1
2
3
function replaceAll(str, find, replace) {
return str.split(find).join(replace);
}

replaceAll 填充函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (!String.prototype.replaceAll) {
Object.defineProperty(String.prototype, 'replaceAll', {
configurable: true,
writable: true,
enumerable: false,
value: function(search, replace) {
return this.replace(
Object.prototype.toString.call(search) === '[object RegExp]'
? search.global
? search
: RegExp(search.source, /\/([a-z]*)$/.exec(search.toString())[1] + 'g')
: RegExp(String(search).replace(/[.^$*+?()[{|\\]/g, "\\$&"), "g"),
replace
);
}
});
}

最佳实践

  • 性能优先场景:如果需要处理大量字符串,建议使用基于正则表达式的实现。
  • 兼容性优先场景:对于需要兼容旧浏览器的场景,可以使用 replaceAll 填充函数或拆分和拼接的实现。
  • 避免意外替换:在使用正则表达式时,确保对特殊字符进行转义处理。

常见问题

正则表达式中的特殊字符

如果 search 参数包含正则表达式的特殊字符,需要先进行转义处理,否则可能会导致意外结果。

递归实现的性能问题

递归实现可能会导致性能问题,特别是处理长字符串时,可能会出现栈溢出错误。

旧浏览器兼容性问题

旧浏览器可能不支持 String.prototype.replaceAll() 方法,需要使用填充函数或其他替代方法。


How do I replace all occurrences of a string?
https://119291.xyz/posts/2025-05-08.how-to-replace-all-occurrences-of-a-string/
作者
ww
发布于
2025年5月8日
许可协议