String.prototype.replaceAll 全局替换

在 JavaScript 的字符串处理中,替换特定文本是一个常见需求。在 ES12 (ECMAScript 2021) 之前,开发者通常使用 String.prototype.replace() 方法配合正则表达式来实现全局替换。ES12 引入了 String.prototype.replaceAll() 方法,为字符串全局替换提供了更直观、更简洁的解决方案。

replace() 方法的局限性

replaceAll() 出现之前,如果我们想要替换字符串中所有匹配的子串,通常需要这样做:

javascript 复制代码
const str = "apple,orange,apple,banana";
const newStr = str.replace(/apple/g, "kiwi");
console.log(newStr); // "kiwi,orange,kiwi,banana"

这种方法虽然有效,但存在几个问题:

  1. 必须使用正则表达式并添加 g 标志
  2. 对于需要转义的特殊字符处理较为复杂
  3. 代码可读性不如直接的字符串替换方法

replaceAll() 方法介绍

replaceAll() 方法解决了上述问题,它提供了一种更简单的方式来进行全局替换:

javascript 复制代码
const str = "apple,orange,apple,banana";
const newStr = str.replaceAll("apple", "kiwi");
console.log(newStr); // "kiwi,orange,kiwi,banana"

基本语法

javascript 复制代码
str.replaceAll(searchValue, replaceValue)
  • searchValue: 可以是字符串或正则表达式(必须带有 g 标志)
  • replaceValue: 替换的字符串或函数

使用字符串作为搜索值

javascript 复制代码
const text = "Hello world, world is beautiful";
console.log(text.replaceAll("world", "Earth"));
// 输出: "Hello Earth, Earth is beautiful"

使用正则表达式作为搜索值

javascript 复制代码
const text = "The quick brown fox jumps over the lazy dog";
console.log(text.replaceAll(/[aeiou]/g, "*"));
// 输出: "Th* q**ck br*wn f*x j*mps *v*r th* l*zy d*g"

注意:当使用正则表达式时,必须包含 g 标志,否则会抛出 TypeError。

特殊替换模式

replaceAll() 支持与 replace() 相同的特殊替换模式:

javascript 复制代码
const text = "John Smith, Jane Doe";
console.log(text.replaceAll(/(\w+)\s(\w+)/g, "$2, $1"));
// 输出: "Smith, John, Doe, Jane"

使用函数作为替换值

replaceAll() 也支持使用函数来动态生成替换内容:

javascript 复制代码
const text = "The prices are $5 and $10";
const result = text.replaceAll(/\$\d+/g, match => {
  const amount = parseInt(match.slice(1));
  return `€${amount * 0.85}`;
});
console.log(result); // "The prices are €4.25 and €8.5"

浏览器兼容性

replaceAll() 作为 ES2021 的新特性,在现代浏览器和 Node.js 12+ 中都已支持。对于旧环境,可以使用以下 polyfill:

javascript 复制代码
if (!String.prototype.replaceAll) {
  String.prototype.replaceAll = function(str, newStr) {
    if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
      if (!str.global) {
        throw new TypeError('replaceAll called with a non-global RegExp');
      }
      return this.replace(str, newStr);
    }
    return this.replace(new RegExp(str, 'g'), newStr);
  };
}

性能考虑

在大多数情况下,replaceAll() 与使用带有 g 标志的正则表达式的 replace() 性能相当。但对于简单的字符串替换,replaceAll() 可能更高效,因为它不需要正则表达式的解析开销。

实际应用场景

  1. 数据清洗:批量替换文本中的敏感信息或错误数据
  2. 模板渲染:替换模板字符串中的占位符
  3. 国际化:替换语言包中的变量
  4. 代码转换:在构建工具中转换代码语法

总结

String.prototype.replaceAll() 是 ES2021 引入的一个实用方法,它简化了全局字符串替换的操作,使代码更加清晰易读。虽然它的功能可以通过 replace() 方法配合正则表达式实现,但 replaceAll() 提供了更直观的 API,减少了开发者的认知负担。

对于现代 JavaScript 开发,建议在需要全局替换字符串时优先使用 replaceAll(),它不仅能提高代码的可读性,还能减少因忘记添加 g 标志而导致的错误。