如何替换 JavaScript 中所有出现的字符串?

How do I replace all occurrences of a string in JavaScript?

提问人:Ali 提问时间:7/18/2009 最后编辑:Mateen UlhaqAli 更新时间:3/26/2023 访问量:4468444

问:

给定一个字符串:

s = "Test abc test test abc test test test abc test test abc";

这似乎只删除了上面字符串中出现的第一个:abc

s = s.replace('abc', '');

如何替换所有出现的它?

JavaScript 字符串 替换

评论

19赞 reinierpost 8/2/2019
当将所有出现的 in 替换为 时,您期望得到什么结果????abaababacacabaabcacca
19赞 sideshowbarker 6/29/2020
String.prototype.replaceAll()现在是 ECMAScript tc39.es/ecma262/#sec-string.prototype.replaceall 的标准部分,记录在 developer.mozilla.org/docs/Web/JavaScript/Reference/... 并在 Safari 13.1、Firefox 77 和 Chrome Dev/Canary 中提供,并将在 Chrome 85 中发布。来自文档:“如果 searchValue 是一个字符串,则替换所有出现的 searchValue(就好像使用了全局和正确转义的正则表达式一样)。如果 searchValue 是非全局正则表达式,则抛出异常”.split(searchValue).join(replaceValue)
19赞 sarea 7/29/2020
使用正则表达式而不是字符串,应该看起来像 so g 来获取所有匹配项。str.replace(/abc/g, '');

答:

86赞 scronide 5/7/2009 #1

与全局正则表达式匹配:

anotherString = someString.replace(/cat/g, 'dog');
5190赞 Sean Bright 7/18/2009 #2

截至 2020 年 8 月:现代浏览器支持 ECMAScript 2021 语言规范定义的 String.replaceAll() 方法


对于旧版/旧版浏览器:

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

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

以下是这个答案的演变过程:

str = str.replace(/abc/g, '');

在回应评论“如果'abc'作为变量传递会怎样?

var find = 'abc';
var re = new RegExp(find, 'g');

str = str.replace(re, '');

作为对 Click Upvote 评论的回应,您可以进一步简化它:

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

注意:正则表达式包含特殊(元)字符,因此,在上面的函数中盲目传递参数而不对其进行预处理以转义这些字符是危险的。这在Mozilla开发者网络JavaScript正则表达式指南中有所介绍,其中提供了以下实用函数(自最初编写此答案以来,该函数至少更改了两次,因此请务必查看MDN站点以获取潜在的更新):find

function escapeRegExp(string) {
  return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

因此,为了使上述功能更安全,如果您还包含以下内容,则可以将其修改为以下内容:replaceAll()escapeRegExp

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

评论

0赞 MMMahdy-PAPION 12/30/2021
在 和 是额外的(没有必要转义)。最好是这样的:escapeRegExp]}.replace(/[.^$*+?()[{|\\]/g, "\\$&")
1赞 YipYip 7/15/2022
您还需要对替换字符串进行转义(考虑如何在替换字符串中使用特殊行为)。将最后一个代码块中的最后一个更改为 。请参阅 stackoverflow.com/a/6969486/2730641 测试用例:escapeRegExp$&replacereplace.replace(/\$/g, '$$$$')replaceAll('abc def abc', 'abc', '$&@%#!') // Censor 'abc'
0赞 Nisharg Shah 9/26/2022
@Sean Bright,请阅读评论 stackoverflow.com/a/63587267/8798220
0赞 Sean Bright 9/26/2022
@NishargShah这个答案的第一句话引用了该方法。replaceAll()
1赞 Sean Bright 9/29/2022
@NishargShah 我不记得 2 年前对这个答案有什么评论,但如果您想编辑这个答案并相信自己,请随时。
60赞 SolutionYogi 7/18/2009 #3
str = str.replace(/abc/g, '');

或者尝试以下方法,如以下答案中建议的那样:replaceAll

str = str.replaceAll('abc', '');

艺术

var search = 'abc';
str = str.replaceAll(search, '');

编辑:关于可用性的说明replaceAll

该方法被添加到 的原型中。这意味着它将可用于所有字符串对象/文字。replaceAllString

例:

var output = "test this".replaceAll('this', 'that'); // output is 'test that'.
output = output.replaceAll('that', 'this'); // output is 'test this'
42赞 Donnie DeBoer 7/18/2009 #4

使用正则表达式:

str.replace(/abc/g, '');
2379赞 Matthew Crumley 7/18/2009 #5

在大多数流行浏览器的最新版本中,您可以使用 replaceAll,如下所示:

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

但请先检查“我可以使用吗”或其他兼容性表,以确保您目标浏览器已首先添加对它的支持。


对于 Node.js 以及与旧版/非当前浏览器的兼容性:

注意:请勿在性能关键型代码中使用以下解决方案。

作为简单文字字符串的正则表达式的替代方法,您可以使用

str = "Test abc test test abc test...".split("abc").join("");

一般模式是

str.split(search).join(replacement)

在某些情况下,这曾经比使用正则表达式更快,但在现代浏览器中似乎不再是这种情况。replaceAll

基准: https://jsben.ch/TZYzj

结论:

如果您有性能关键型用例(例如,处理数百个字符串),请使用正则表达式方法。但对于大多数典型用例来说,这非常值得担心特殊字符。

评论

18赞 Tom Smykowski 10/20/2020
我不鼓励在此时(2020 年)使用 replaceAll。今年有更新的一些浏览器不支持它 caniuse.com/?search=replaceAll 现在还为时过早
22赞 Abion47 2/25/2021
NodeJS 在 15.x 版本中支持。replaceAll
0赞 Kunal Tanwar 8/28/2021
区分大小写的情况应如何处理
0赞 Tristan Forward 2/12/2022
基准测试的普通替换函数不等同于正则表达式 /g。 “如果 pattern 是一个字符串,则只会替换第一个出现。例如:replaceAll_0(“foo bar foo”) => “bar foo”,而它应该只是“bar”。-MDN系列
0赞 fonzane 6/21/2023
这些解决方案比基于正则表达式的解决方案更具可读性。Imo 这应该是最重要的答案。
6赞 Vitim.us 10/28/2011 #6

我的实现,非常不言自明

function replaceAll(string, token, newtoken) {
    if(token!=newtoken)
    while(string.indexOf(token) > -1) {
        string = string.replace(token, newtoken);
    }
    return string;
}

评论

1赞 Bryan 4/16/2013
这是不正确的。 应该返回,但返回 .replaceAll("123434", "1234", "12")"1234""12"
2赞 Vitim.us 4/17/2013
这取决于你是否允许“递归”替换。
10赞 user1002973 5/16/2013
replaceAll(“abc”, “a”, “ab”) 永不终止
97赞 Elias Van Ootegem 3/1/2012 #7

使用单词边界 (\b)

'a cat is not a caterpillar'.replace(/\bcat\b/gi,'dog');
//"a dog is not a caterpillar"

这是一个简单的正则表达式,在大多数情况下可以避免替换部分单词。但是,破折号仍被视为单词边界。因此,在这种情况下可以使用条件语句来避免替换字符串,例如:-cool-cat

'a cat is not a cool-cat'.replace(/\bcat\b/gi,'dog');//wrong
//"a dog is not a cool-dog" -- nips
'a cat is not a cool-cat'.replace(/(?:\b([^-]))cat(?:\b([^-]))/gi,'$1dog$2');
//"a dog is not a cool-cat"

基本上,这个问题和这里的问题是一样的:在JavaScript中将“ ' ”替换为“ '' ”

正则表达式不是替换子字符串的多次出现的唯一方法,远非如此。灵活思考,拆分思维!

var newText = "the cat looks like a cat".split('cat').join('dog');

或者,为了防止替换单词部分——批准的答案也会这样做!您可以使用正则表达式来解决这个问题,我承认,这些正则表达式稍微复杂一些,而且作为结果,速度也慢了一点:

var regText = "the cat looks like a cat".replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");

输出与接受的答案相同,但是,使用此字符串上的表达式:/cat/g

var oops = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/cat/g,'dog');
//returns "the dog looks like a dog, not a dogerpillar or cooldog" ??

哎呀,这可能不是你想要的。那么,什么是呢?恕我直言,一个只有条件地替换“cat”的正则表达式(即,不是单词的一部分),如下所示:

var caterpillar = 'the cat looks like a cat, not a caterpillar or coolcat'.replace(/(?:(^|[^a-z]))(([^a-z]*)(?=cat)cat)(?![a-z])/gi,"$1dog");
//return "the dog looks like a dog, not a caterpillar or coolcat"

我的猜测是,这满足了您的需求。当然,它不是万无一失的,但它应该足以让你开始。我建议在这些页面上阅读更多内容。这将证明有助于完善此表达式以满足您的特定需求。


下面是与回调函数一起使用的示例。在这种情况下,它极大地简化了表达式提供了更大的灵活性,例如用正确的大小写替换或一次性替换两者:.replacecatcats

'Two cats are not 1 Cat! They\'re just cool-cats, you caterpillar'
   .replace(/(^|.\b)(cat)(s?\b.|$)/gi,function(all,char1,cat,char2)
    {
       // Check 1st, capitalize if required
       var replacement = (cat.charAt(0) === 'C' ? 'D' : 'd') + 'og';
       if (char1 === ' ' && char2 === 's')
       { // Replace plurals, too
           cat = replacement + 's';
       }
       else
       { // Do not replace if dashes are matched
           cat = char1 === '-' || char2 === '-' ? cat : replacement;
       }
       return char1 + cat + char2;//return replacement string
    });
//returns:
//Two dogs are not 1 Dog! They're just cool-cats, you caterpillar
139赞 jesal 2/12/2013 #8

下面是一个基于已接受答案的字符串原型函数:

String.prototype.replaceAll = function(find, replace) {
    var str = this;
    return str.replace(new RegExp(find, 'g'), replace);
};

如果包含特殊字符,则需要对它们进行转义:find

String.prototype.replaceAll = function(find, replace) {
    var str = this;
    return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
};

小提琴:http://jsfiddle.net/cdbzL/

18赞 Owen 5/15/2013 #9

我喜欢这种方法(它看起来更干净一点):

text = text.replace(new RegExp("cat","g"), "dog"); 
29赞 Raseela 6/5/2013 #10

循环它,直到出现次数达到 0,如下所示:

function replaceAll(find, replace, str) {
    while (str.indexOf(find) > -1) {
        str = str.replace(find, replace);
    }
    return str;
}

评论

28赞 Rob W 10/29/2013
这种方法很危险,不要使用它。如果替换字符串包含搜索关键字,则将发生无限循环。至少,将结果存储在变量中,并将此变量用作 的第二个参数(减去关键字的长度,加上替换字符串的长度)。.indexOf.indexOf
24赞 rakslice 6/20/2013 #11

如果要查找的内容已在字符串中,并且手头没有正则表达式转义符,则可以使用 join/split:

    function replaceMulti(haystack, needle, replacement)
    {
        return haystack.split(needle).join(replacement);
    }

    someString = 'the cat looks like a cat';
    console.log(replaceMulti(someString, 'cat', 'dog'));

2532赞 Cory Gross 7/12/2013 #12

为了完整起见,我开始考虑应该使用哪种方法来执行此操作。基本上有两种方法可以做到这一点,正如本页上的其他答案所建议的那样。

注意:通常,通常不建议在 JavaScript 中扩展内置原型。我作为 String 原型的扩展提供只是为了说明目的,在内置原型上展示了假设标准方法的不同实现。String


基于正则表达式的实现

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.replace(new RegExp(search, 'g'), replacement);
};

拆分和联接(功能)实现

String.prototype.replaceAll = function(search, replacement) {
    var target = this;
    return target.split(search).join(replacement);
};

由于不太了解正则表达式在幕后如何工作的效率,我过去倾向于拆分和联接实现,而不考虑性能。当我想知道哪个更有效率,以及效率更高时,我以此为借口来找出答案。

在我的 Chrome Windows 8 机器上,基于正则表达式的实现速度最快,拆分和联接实现速度慢 53%。这意味着对于我使用的 lorem ipsum 输入,正则表达式的速度是其两倍。

查看此基准测试,将这两种实现相互运行。


正如 @ThomasLeduc 和其他人在下面的评论中指出的那样,如果包含某些在正则表达式中保留为特殊字符的字符,则基于正则表达式的实现可能存在问题。该实现假定调用方将事先对字符串进行转义,或者仅传递正则表达式 (MDN) 中表中没有字符的字符串。search

MDN 还提供了一个转义字符串的实现。如果这也被标准化为 ,那就太好了,但唉,它不存在:RegExp.escape(str)

function escapeRegExp(str) {
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}

我们可以在我们的实现中调用,但是,我不确定这会对性能产生多大影响(甚至可能对于不需要转义的字符串,例如所有字母数字字符串)。escapeRegExpString.prototype.replaceAll

评论

0赞 MMMahdy-PAPION 12/26/2021
2021 年,String.prototype.replaceAll() 原生存在。因此,在使用之前应首先检查此实现。
0赞 Sunil Garg 1/5/2022
m 使用 nestjs,所以打字稿显示错误,replaceAll 不是 String 原型的方法,有什么解决方案吗?
14赞 pkdkk 9/4/2013 #13
var str = "ff ff f f a de def";
str = str.replace(/f/g,'');
alert(str);

http://jsfiddle.net/ANHR9/

6赞 SiwachGaurav 12/24/2013 #14

要替换所有类型的字符,请尝试以下代码:

假设我们需要在我的字符串中发送 “ 和 \。然后我们将它转换为“”,将\转换为\。

所以这种方法将解决这个问题。

String.prototype.replaceAll = function (find, replace) {
     var str = this;
     return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
 };

var message = $('#message').val();
message = message.replaceAll('\\', '\\\\'); /*it will replace \ to \\ */
message = message.replaceAll('"', '\\"');   /*it will replace " to \\"*/

我使用的是 Ajax,我需要以 JSON 格式发送参数。那么我的方法看起来像这样:

 function sendMessage(source, messageID, toProfileID, userProfileID) {

     if (validateTextBox()) {
         var message = $('#message').val();
         message = message.replaceAll('\\', '\\\\');
         message = message.replaceAll('"', '\\"');
         $.ajax({
             type: "POST",
             async: "false",
             contentType: "application/json; charset=utf-8",
             url: "services/WebService1.asmx/SendMessage",
             data: '{"source":"' + source + '","messageID":"' + messageID + '","toProfileID":"' + toProfileID + '","userProfileID":"' + userProfileID + '","message":"' + message + '"}',
             dataType: "json",
             success: function (data) {
                 loadMessageAfterSend(toProfileID, userProfileID);
                 $("#<%=PanelMessageDelete.ClientID%>").hide();
                 $("#message").val("");
                 $("#delMessageContainer").show();
                 $("#msgPanel").show();
             },
             error: function (result) {
                 alert("message sending failed");
             }
         });
     }
     else {
         alert("Please type message in message box.");
         $("#message").focus();

     }
 }

 String.prototype.replaceAll = function (find, replace) {
     var str = this;
     return str.replace(new RegExp(find.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'), 'g'), replace);
 };
1赞 Antonio Mirarchi 1/8/2014 #15

试试这个:

String.prototype.replaceAll = function (sfind, sreplace) {
    var str = this;

    while (str.indexOf(sfind) > -1) {
        str = str.replace(sfind, sreplace);
    }

    return str;
};

评论

8赞 Aamir Afridi 10/9/2014
不要修改不属于您的对象
4赞 Jonathan ANTOINE 6/24/2016
如果替换包含“find”youi,则将有一个无限循环
28赞 Cole Lawrence 4/5/2014 #16

这是不使用正则表达式的最快版本。

修订后的 jsperf

replaceAll = function(string, omit, place, prevstring) {
  if (prevstring && string === prevstring)
    return string;
  prevstring = string.replace(omit, place);
  return replaceAll(prevstring, omit, place, string)
}

它的速度几乎是拆分和连接方法的两倍

正如此处的评论中指出的,如果您的变量包含 ,这将不起作用,例如: ,因为它始终能够替换该单词的另一个出现。omitplacereplaceAll("string", "s", "ss")

在我的递归替换中还有另一个带有变体的 jsperf,它们的速度更快 (http://jsperf.com/replace-all-vs-split-join/12)!

  • 2017 年 7 月 27 日更新:看起来 RegExp 现在在最近发布的 Chrome 59 中具有最快的性能。

评论

1赞 Peter Mortensen 9/25/2022
回复“几乎两倍的速度”:它测试了什么?浏览器、JavaScript 运行时、硬件、操作系统等。所有版本和规格(例如时钟速度、CPU 类型等)。
15赞 zdennis 4/29/2014 #17
while (str.indexOf('abc') !== -1)
{
    str = str.replace('abc', '');
}

评论

0赞 RixTheTyrunt 7/31/2023
我已经在代码中使用了它,它非常方便!+1
4赞 Guy 9/15/2014 #18

如果使用库是您的一种选择,那么您将获得库功能附带的测试和社区支持的好处。例如,string.js 库有一个 replaceAll() 函数,可以执行您要查找的操作:

// Include a reference to the string.js library and call it (for example) S.
str = S(str).replaceAll('abc', '').s;
10赞 SamGoody 9/29/2014 #19

如果你试图确保你所查找的字符串在替换后也不存在,你需要使用循环。

例如:

var str = 'test aabcbc';
str = str.replace(/abc/g, '');

完成后,您仍将拥有“测试abc”!

解决此问题的最简单循环是:

var str = 'test aabcbc';
while (str != str.replace(/abc/g, '')){
   str.replace(/abc/g, '');
}

但这会为每个周期运行两次更换。也许(有被否决的风险)可以组合成一个稍微更有效但可读性较差的形式:

var str = 'test aabcbc';
while (str != (str = str.replace(/abc/g, ''))){}
// alert(str); alerts 'test '!

这在查找重复字符串时特别有用。
例如,如果我们有“a,,,b”,并且我们希望删除所有重复的逗号。
[在这种情况下,可以执行 .replace(/,+/g,','),但在某些时候,正则表达式变得复杂且缓慢到足以循环。

20赞 Tim Rivoli 9/30/2014 #20
function replaceAll(str, find, replace) {
  var i = str.indexOf(find);
  if (i > -1){
    str = str.replace(find, replace); 
    i = i + replace.length;
    var st2 = str.substring(i);
    if(st2.indexOf(find) > -1){
      str = str.substring(0,i) + replaceAll(st2, find, replace);
    }       
  }
  return str;
}
8赞 Reza Fahmi 6/5/2015 #21

只需添加/g

document.body.innerHTML = document.body.innerHTML.replace('hello', 'hi');

// Replace 'hello' string with /hello/g regular expression.
document.body.innerHTML = document.body.innerHTML.replace(/hello/g, 'hi');

/g表示全球

34赞 Chris Rosete 6/20/2015 #22

替换单引号:

function JavaScriptEncode(text){
    text = text.replace(/'/g,'&apos;')
    // More encode here if required

    return text;
}
6赞 Termininja 1/13/2016 #23

我使用 p 来存储上一次递归替换的结果:

function replaceAll(s, m, r, p) {
    return s === p || r.contains(m) ? s : replaceAll(s.replace(m, r), m, r, s);
}

它将替换字符串 s 中出现的所有匹配项,直到可能为止:

replaceAll('abbbbb', 'ab', 'a') → 'abbbb' → 'abbb' → 'abb' → 'ab' → 'a'

为了避免无限循环,我检查替换 r 是否包含匹配的 m

replaceAll('abbbbb', 'a', 'ab') → 'abbbbb'
6赞 tk_ 2/15/2016 #24

您可以简单地使用以下方法

/**
 * Replace all the occerencess of $find by $replace in $originalString
 * @param  {originalString} input - Raw string.
 * @param  {find} input - Target key word or regex that need to be replaced.
 * @param  {replace} input - Replacement key word
 * @return {String}       Output string
 */
function replaceAll(originalString, find, replace) {
  return originalString.replace(new RegExp(find, 'g'), replace);
};
7赞 Sandeep Gantait 2/16/2016 #25

以下功能对我有用:

String.prototype.replaceAllOccurence = function(str1, str2, ignore)
{
    return this.replace(new RegExp(str1.replace(/([\/\,\!\\\^\$\{\}\[\]\(\)\.\*\+\?\|\<\>\-\&])/g,"\\$&"),(ignore?"gi":"g")),(typeof(str2)=="string")?str2.replace(/\$/g,"$$$$"):str2);
} ;

现在调用函数,如下所示:

"you could be a Project Manager someday, if you work like this.".replaceAllOccurence ("you", "I");

只需将此代码复制并粘贴到浏览器控制台中即可进行 TEST。

3赞 Nivesh Saharan 3/4/2016 #26

以下是原型的工作代码:

String.prototype.replaceAll = function(find, replace) {
    var str = this;
    return str.replace(new RegExp(find.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1"), 'g'), replace);
};
3赞 theWalker 4/12/2016 #27
function replaceAll(str, find, replace) {
    var $r="";
    while($r!=str){ 
        $r = str;
        str = str.replace(find, replace);
    }
    return str;
}

评论

3赞 Jonathan ANTOINE 6/24/2016
如果替换包含“find”youi,则将有一个无限循环
10赞 Cheezy Code 5/4/2016 #28

尽管人们提到了正则表达式的使用,但如果您想替换文本,而不管文本的大小写如何,还有更好的方法。如大写或小写。使用以下语法:

// Consider the below example
originalString.replace(/stringToBeReplaced/gi, '');

// The output will be all the occurrences removed irrespective of casing.

您可以参考此处的详细示例。

评论

0赞 alikuli 8/3/2016
来自示例站点:“/toBeplacedString/gi 是您需要使用的正则表达式。这里 g 表示全局匹配,i 表示不区分大小写。默认情况下,正则表达式区分大小写”
43赞 Emilio Grisolía 9/10/2016 #29

假设您要用“x”替换所有“abc”:

let some_str = 'abc def def lom abc abc def'.split('abc').join('x')
console.log(some_str) //x def def lom x x def

我试图考虑一些比修改字符串原型更简单的事情。

2赞 C. Morgan 10/16/2016 #30

这可以使用正则表达式和标志来解决,这意味着在找到第一个匹配项后不要停止。真的,正则表达式是救命稻草!g

function replaceAll(string, pattern, replacement) {
    return string.replace(new RegExp(pattern, "g"), replacement);
}

// or if you want myString.replaceAll("abc", "");

String.prototype.replaceAll = function(pattern, replacement) {
    return this.replace(new RegExp(pattern, "g"), replacement);
};
6赞 User 3/17/2017 #31

大多数人可能这样做是为了对 URL 进行编码。要对 URL 进行编码,您不仅应该考虑空格,还应该使用 .encodeURI

encodeURI("http://www.google.com/a file with spaces.html")

要获取:

http://www.google.com/a%20file%20with%20spaces.html
45赞 Alireza 6/6/2017 #32

JavaScript 中使用可以为您完成这项工作。只需简单地执行以下代码,并且不要忘记之后的出色表现:RegExp/g

var str ="Test abc test test abc test test test abc test test abc";
str = str.replace(/abc/g, '');

如果您考虑重用,请创建一个函数来为您执行此操作,但不建议这样做,因为它只有一行函数。但同样,如果你大量使用它,你可以写这样的东西:

String.prototype.replaceAll = String.prototype.replaceAll || function(string, replaced) {
  return this.replace(new RegExp(string, 'g'), replaced);
};

只需在代码中一遍又一遍地使用它,如下所示:

var str ="Test abc test test abc test test test abc test test abc";
str = str.replaceAll('abc', '');

但正如我之前提到的,它不会在要写的台词或性能方面产生巨大差异。仅缓存函数可能会影响长字符串的更快性能,如果要重用,这也是 DRY 代码的良好做法。

5赞 Paulo Buchsbaum 8/17/2017 #33

在我的应用程序中,我使用了为此目的最强大的自定义函数,即使将解决方案包装在更简单的情况下,它在 Chrome 60 和 Firefox 54 (JSBEN.CH)比其他溶液。我的电脑运行Windows 7 64位。split/join

优点是此自定义函数可以使用字符串或字符同时处理许多替换,这可以成为某些应用程序的快捷方式。

与上面的拆分/联接解决方案一样,下面的解决方案在转义字符方面没有任何问题,这与正则表达式方法不同。

function replaceAll(s, find, repl, caseOff, byChar) {
    if (arguments.length<2)
        return false;
    var destDel = ! repl;       // If destDel delete all keys from target
    var isString = !! byChar;   // If byChar, replace set of characters
    if (typeof find !== typeof repl && ! destDel)
        return false;
    if (isString && (typeof find !== "string"))
        return false;

    if (! isString && (typeof find === "string")) {
        return s.split(find).join(destDel ? "" : repl);
    }

    if ((! isString) && (! Array.isArray(find) ||
        (! Array.isArray(repl) && ! destDel)))
        return false;

    // If destOne replace all strings/characters by just one element
    var destOne = destDel ? false : (repl.length === 1);

    // Generally source and destination should have the same size
    if (! destOne && ! destDel && find.length !== repl.length)
        return false

    var prox, sUp, findUp, i, done;
    if (caseOff)  { // Case insensitive

    // Working with uppercase keys and target
    sUp = s.toUpperCase();
    if (isString)
       findUp = find.toUpperCase()
    else
       findUp = find.map(function(el) {
                    return el.toUpperCase();
                });
    }
    else { // Case sensitive
        sUp = s;
        findUp = find.slice(); // Clone array/string
    }

    done = new Array(find.length); // Size: number of keys
    done.fill(null);

    var pos = 0;  // Initial position in target s
    var r = "";   // Initial result
    var aux, winner;
    while (pos < s.length) {       // Scanning the target
        prox  = Number.MAX_SAFE_INTEGER;
        winner = -1;  // No winner at the start
        for (i=0; i<findUp.length; i++) // Find next occurence for each string
            if (done[i]!==-1) { // Key still alive

                // Never search for the word/char or is over?
                if (done[i] === null || done[i] < pos) {
                    aux = sUp.indexOf(findUp[i], pos);
                    done[i] = aux;  // Save the next occurrence
                }
                else
                    aux = done[i]   // Restore the position of last search

                if (aux < prox && aux !== -1) { // If next occurrence is minimum
                    winner = i; // Save it
                    prox = aux;
                }
        } // Not done

        if (winner === -1) { // No matches forward
            r += s.slice(pos);
            break;
        } // No winner

        // Found the character or string key in the target

        i = winner;  // Restore the winner
        r += s.slice(pos, prox); // Update piece before the match

        // Append the replacement in target
        if (! destDel)
            r += repl[destOne ? 0 : i];
        pos = prox + (isString ? 1 : findUp[i].length); // Go after match
    }  // Loop

    return r; // Return the resulting string
}

文档如下:

 replaceAll

 Syntax
 ======

      replaceAll(s, find, [repl, caseOff, byChar)

 Parameters
 ==========

   "s" is a string target of replacement.
   "find" can be a string or array of strings.
   "repl" should be the same type than "find" or empty

  If "find" is a string, it is a simple replacement for
    all "find" occurrences in "s" by string "repl"

  If "find" is an array, it will replaced each string in "find"
    that occurs in "s" for corresponding string in "repl" array.
  The replace specs are independent: A replacement part cannot
  be replaced again.


  If "repl" is empty all "find" occurrences in "s" will be deleted.
  If "repl" has only one character or element,
      all occurrences in "s" will be replaced for that one.

  "caseOff" is true if replacement is case insensitive
       (default is FALSE)

  "byChar" is true when replacement is based on set of characters.
  Default is false

  If "byChar", it will be replaced in "s" all characters in "find"
  set of characters for corresponding character in "repl"
  set of characters

 Return
 ======

  The function returns the new string after the replacement.

公平地说,我在没有参数测试的情况下运行了基准测试

这是我的测试集,使用 Node.js:

function l() {
    return console.log.apply(null, arguments);
}

var k = 0;
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"], ["do", "fa"]));  // 1
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"], ["do"])); // 2
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"])); // 3
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
     "aeiou", "", "", true)); // 4
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      "aeiou", "a", "", true)); // 5
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      "aeiou", "uoiea", "", true)); // 6
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      "aeiou", "uoi", "", true)); // 7
l(++k, replaceAll("banana is a ripe fruit harvested near the river",
      ["ri", "nea"], ["do", "fa", "leg"])); // 8
l(++k, replaceAll("BANANA IS A RIPE FRUIT HARVESTED NEAR THE RIVER",
      ["ri", "nea"], ["do", "fa"])); // 9
l(++k, replaceAll("BANANA IS A RIPE FRUIT HARVESTED NEAR THE RIVER",
      ["ri", "nea"], ["do", "fa"], true)); // 10
return;

结果如下:

1 “香蕉是多佛尔远地收获的水果”
2 “香蕉是多佛尔收获的水果”
3 “香蕉是收获的 pe 水果”
4 'BNN s rp frt hrvstd nr th rvr'
5 '香蕉是 rapa fraat harvastad naar tha ravar'
6 'Bununu is u ripo frait hurvostod nour tho rivor'
7 假 8 假

9 “香蕉是在河边收获的成熟水果”
10 '香蕉是一种收获的水果 faR THE DOVER'

评论

2赞 Bart Read 9/4/2017
被否决是因为使用这么多代码来实现如此基本的东西对我来说感觉有点矫枉过正。
1赞 Paulo Buchsbaum 9/6/2017
这是见仁见智的问题。对我来说,这是一个强大的快速功能。我已经用了很多年了。一个人不能在更少的行上做到这一点。对于那些只想替换字符串中的字符和片段而不用担心正则表达式中的转义字符的人来说,这可能是一个不错的选择。行数并不重要,因为它的工作原理是一个经过测试的黑匣子
0赞 MMMahdy-PAPION 1/20/2022
我喜欢该函数处理数组输入的方式,与PHP的str_replace方法相同,但是: 1.当输入为字符串时,函数“caseOff”将不起作用。- 2.基准测试在逻辑上绝对看起来不公平,当您将函数定义为原型并重新定义代码并注释部分并且仅使用字符串输入时,结果是不公平的。展会可以是这样的:jsben.ch/38Gj1(结果有很大不同)
14赞 4 revs, 3 users 70%mostafa elmadany #34

如果字符串包含类似的模式,例如 ,则可以使用以下命令:abccc

str.replace(/abc(\s|$)/g, "")
3赞 KARTHIKEYAN.A 12/28/2017 #35

在字符串中的第一个元素搜索和替换

var str = '[{"id":1,"name":"karthikeyan.a","type":"developer"}]'
var i = str.replace('"[','[').replace(']"',']');
console.log(i,'//first element search and replace')

在字符串中全局搜索和替换

var str = '[{"id":1,"name":"karthikeyan.a","type":"developer"}]'
var j = str.replace(/\"\[/g,'[').replace(/\]\"/g,']');
console.log(j,'//global search and replace')

评论

0赞 Peter Mortensen 9/25/2022
文本是 ***** 难以理解的 *****:“在字符串中第一个元素搜索和替换”和“在字符串中全局搜索和替换”。您是否正在使用机器翻译和/或缺少一些单词?你能解决它吗?
30赞 csomakk 12/28/2017 #36

str = str.replace(new RegExp("abc", 'g'), "");

对我来说比以前的答案更好。因此,创建一个与文本 () 的所有出现 ( flag) 匹配的正则表达式。第二部分是被替换的内容,在本例中为空字符串 ()。 是字符串,我们必须覆盖它,因为只返回结果,而不是覆盖。在某些情况下,您可能希望使用它。new RegExp("abc", 'g')'g'"abc"""strreplace(...)

评论

1赞 MMMahdy-PAPION 1/15/2022
警告!此方法仅适用于简单情况,但绝不能成为主要选项。例如,如果字符串中存在任何正则表达式特殊字符,则无法返回预期的结果。.^$*+?()[{|\\
2赞 Andrés 1/27/2018 #37

我只想分享我的解决方案,基于最新版本的 JavaScript 的一些功能特性:

   var str = "Test abc test test abc test test test abc test test abc";

   var result = str.split(' ').reduce((a, b) => {
      return b == 'abc' ? a : a + ' ' + b;   })

  console.warn(result)
3赞 TheAivis 4/11/2018 #38

对于唯一的可替换值

String.prototype.replaceAll = function(search_array, replacement_array) {
  //
  var target = this;
  //
  search_array.forEach(function(substr, index) {
    if (typeof replacement_array[index] != "undefined") {
      target = target.replace(new RegExp(substr, 'g'), replacement_array[index])
    }
  });
  //
  return target;
};

//  Use:
var replacedString = "This topic commented on :year. Talking :question.".replaceAll([':year', ':question'], ['2018', 'How to replace all occurrences of a string in JavaScript']);
//
console.log(replacedString);

评论

0赞 rak007 4/20/2018
如果单词共享相同的字母,则代码不起作用。示例:var test = “Groups_4_Questions_0__Options_0_Wording”.replaceAll([4, 0, 0], [100, 200, 300])
0赞 TheAivis 4/20/2018
不是故意的。仅适用于唯一的可替换值。
1赞 rak007 4/20/2018
在大多数情况下,这是没有用的
7赞 Ferie 9/5/2018 #39

就与主要答案相关的性能而言,这些是一些在线测试

以下是一些使用的性能测试(它们在您自己的控制台中效果最好,因为在以下代码片段中看到的时间非常短)。console.time()

console.time('split and join');
"javascript-test-find-and-replace-all".split('-').join(' ');
console.timeEnd('split and join')

console.time('regular expression');
"javascript-test-find-and-replace-all".replace(new RegExp('-', 'g'), ' ');
console.timeEnd('regular expression');

console.time('while');
let str1 = "javascript-test-find-and-replace-all";
while (str1.indexOf('-') !== -1) {
    str1 = str1.replace('-', ' ');
}
console.timeEnd('while');

有趣的是,如果你多次运行它们,结果总是不同的,即使正则表达式解决方案平均看起来最快,而循环解决方案最慢。while

12赞 Black 10/23/2018 #40

前面的答案太复杂了。只需像这样使用替换函数:

str.replace(/your_regex_pattern/g, replacement_string);

例:

var str = "Test abc test test abc test test test abc test test abc";

var res = str.replace(/[abc]+/g, "");

console.log(res);

0赞 Arian Saputra 1/22/2019 #41

你可以试试这样:

示例数据:

var text = "heloo,hai,hei"

text = text.replace(/[,]+/g, '')

text.forEach((value) => {
  hasil = hasil.replace(',', '')
})
6赞 Ashish 1/29/2019 #42

方法 1

尝试实现正则表达式:

“测试 abc 测试测试 abc 测试测试 abc 测试测试 abc”.replace(/\abc/g, ' ');

方法 2

拆分和联接。用 abc 拆分并用空白空间连接。

“测试 abc 测试测试 abc 测试测试测试 abc 测试测试 abc”.split(“abc”).join(“ ”)

2赞 Yash 2/7/2019 #43

最好的解决方案是,为了替换任何字符,我们使用 , , 和函数将匹配的字符串替换为当前字符串中提供的字符串。indexOf()includes()substring()

  • String.indexOf() 函数用于查找第 1 个匹配索引位置。n
  • String.includes() 方法确定是否可以在另一个字符串中找到一个字符串,并根据需要返回 true 或 false。
  • String.substring() 函数用于获取 String(,) 的各个部分。在这些部分之间添加替换 String 以生成最终返回的 String。precedingexceding

以下函数允许使用任何字符。
其中,由于正则表达式不允许某些特殊字符,例如某些字符需要转义,例如 .
**$

String.prototype.replaceAllMatches = function(obj) { // Obj format: { 'matchkey' : 'replaceStr' }
    var retStr = this;
    for (var x in obj) {
        //var matchArray = retStr.match(new RegExp(x, 'ig'));
        //for (var i = 0; i < matchArray.length; i++) {
        var prevIndex = retStr.indexOf(x); // matchkey = '*', replaceStr = '$*' While loop never ends.
        while (retStr.includes(x)) {
            retStr = retStr.replaceMatch(x, obj[x], 0);
            var replaceIndex = retStr.indexOf(x);
            if( replaceIndex <  prevIndex + (obj[x]).length) {
                break;
            } else {
                prevIndex = replaceIndex;
            }
        }
    }
    return retStr;
};
String.prototype.replaceMatch = function(matchkey, replaceStr, matchIndex) {
    var retStr = this, repeatedIndex = 0;
    //var matchArray = retStr.match(new RegExp(matchkey, 'ig'));
    //for (var x = 0; x < matchArray.length; x++) {
    for (var x = 0; (matchkey != null) && (retStr.indexOf(matchkey) > -1); x++) {
        if (repeatedIndex == 0 && x == 0) {
            repeatedIndex = retStr.indexOf(matchkey);
        } else { // matchIndex > 0
            repeatedIndex = retStr.indexOf(matchkey, repeatedIndex + 1);
        }
        if (x == matchIndex) {
            retStr = retStr.substring(0, repeatedIndex) + replaceStr + retStr.substring(repeatedIndex + (matchkey.length));
            matchkey = null; // To break the loop.
        }
    }
    return retStr;
};

我们还可以使用正则表达式对象将文本与模式进行匹配。以下是将使用正则表达式对象的函数。

当您使用无效的正则表达式模式(如 )时,将收到 SyntaxError。'**'

String.prototype.replaceAllRegexMatches = function(obj) { // Obj format: { 'matchkey' : 'replaceStr' }
    var retStr = this;
    for (var x in obj) {
        retStr = retStr.replace(new RegExp(x, 'ig'), obj[x]);
    }
    return retStr;
};

请注意,正则表达式是不带引号的。


使用上述功能的示例:

var str = "yash yas $dfdas.**";
console.log('String: ', str);

// No need to escape any special character
console.log('Index matched replace: ', str.replaceMatch('as', '*', 2));
console.log('Index Matched replace: ', str.replaceMatch('y', '~', 1));
console.log('All Matched replace: ', str.replaceAllMatches({'as': '**', 'y':'Y', '$':'-'}));
console.log('All Matched replace : ', str.replaceAllMatches({'**': '~~', '$':'&$&', '&':'%', '~':'>'}));

// You need to escape some special Characters
console.log('REGEX all matched replace: ', str.replaceAllRegexMatches({'as' : '**', 'y':'Y', '\\$':'-'}));

结果:

String:  yash yas $dfdas.**
Index Matched replace:  yash yas $dfd*.**
Index Matched replace:  yash ~as $dfdas.**

All Matched replace:  Y**h Y** -dfd**.**
All Matched replace:  yash yas %$%dfdas.>>

REGEX All Matched replace:  Y**h Y** -dfd**.**

评论

0赞 David Mårtensson 5/20/2020
在循环中,您正在重复替换字符串。这会在循环的每次迭代中创建一个新字符串,对于长字符串,这将消耗大量性能。正则表达式已经支持一次性完成所有替换,这要快得多,因为它将使用技巧来避免创建多个新字符串。
1赞 Brijesh Kumar Kushwaha 2/9/2019 #44

最简单的解决方案——

let str = "Test abc test test abc test test test abc test test abc";

str = str.split(" ");
str = str.filter((ele, key)=> ele!=="abc")
str = str.join(" ")

或者干脆——

str = str.split(" ").filter((ele, key) => ele != "abc").join(" ")

7赞 prime 2/16/2019 #45

这可以使用正则表达式来实现。一些可能对某人有帮助的组合:

var word = "this,\\ .is*a*test,    '.and? / only /     'a \ test?";
var stri = "This      is    a test         and only a        test";

要替换所有非字母字符,

console.log(word.replace(/([^a-z])/g,' ').replace(/ +/g, ' '));
Result: [this is a test and only a test]

要用一个空格替换多个连续空格,

console.log(stri.replace(/  +/g,' '));
Result: [This is a test and only a test]

要替换所有 * 字符,

console.log(word.replace(/\*/g,''));
Result: [this,\ .isatest,    '.and? / only /     'a  test?]

替换问号 (?)

console.log(word.replace(/\?/g,'#'));
Result: [this,\ .is*a*test,    '.and# / only /     'a  test#]

要替换引号,

console.log(word.replace(/'/g,'#'));
Result: [this,\ .is*a*test,    #.and? / only /     #a  test?]

要替换所有 ' 字符,

console.log(word.replace(/,/g,''));
Result: [this\ .is*a*test    '.and? / only /     'a  test?]

要替换特定单词,

console.log(word.replace(/test/g,''));
Result: [this,\ .is*a*,    '.and? / only /     'a  ?]

要替换反斜杠,

console.log(word.replace(/\\/g,''));
Result: [this, .is*a*test,    '.and? / only /     'a  test?]

要替换正斜杠,

console.log(word.replace(/\//g,''));
Result: [this,\ .is*a*test,    '.and?  only      'a  test?]

要替换所有空格,

console.log(word.replace(/ /g,'#'));
Result: [this,\#.is*a*test,####'.and?#/#only#/#####'a##test?]

要替换点,

console.log(word.replace(/\./g,'#'));
Result: [this,\ #is*a*test,    '#and? / only /     'a  test?]
2赞 Rinold 2/27/2019 #46
var myName = 'r//i//n//o//l////d';
var myValidName = myName.replace(new RegExp('\//', 'g'), ''); > // rinold
console.log(myValidName);

var myPetName = 'manidog';
var renameManiToJack = myPetName.replace(new RegExp('mani', 'g'), 'jack'); > // jackdog
102赞 Adnan Toky 3/25/2019 #47

这些是最常见和最可读的方法。

var str = "Test abc test test abc test test test abc test test abc"

方法1:

str = str.replace(/abc/g, "replaced text");

方法2:

str = str.split("abc").join("replaced text");

方法3:

str = str.replace(new RegExp("abc", "g"), "replaced text");

方法4:

while(str.includes("abc")){
   str = str.replace("abc", "replaced text");
}

输出:

console.log(str);
// Test replaced text test test replaced text test test test replaced text test test replaced text

评论

1赞 Gangula 3/16/2023
到目前为止,我发现方法1最简单,最可靠。这里也提到了它。
0赞 Grzegorz Adam Kowalski 7/27/2023
方法 2 在 Sharepoint SPFx 中非常适合替换动态字符串 - 编译器规则显式阻止其他方法
7赞 VhsPiceros 4/16/2019 #48

我使用拆分和连接或这个函数:

function replaceAll(text, busca, reemplaza) {
  while (text.toString().indexOf(busca) != -1)
    text = text.toString().replace(busca, reemplaza);
  return text;
}

评论

0赞 MMMahdy-PAPION 1/29/2022
在以下情况下工作错误replaceAll('aaaaaa','aa','a')
2赞 Jessie Lesbian 5/9/2019 #49

这应该有效。

String.prototype.replaceAll = function (search, replacement) {
    var str1 = this.replace(search, replacement);
    var str2 = this;
    while(str1 != str2) {
        str2 = str1;
        str1 = str1.replace(search, replacement);
    }
    return str1;
}

例:

Console.log("Steve is the best character in Minecraft".replaceAll("Steve", "Alex"));

评论

0赞 Peter Mortensen 3/9/2020
@aabbccsmith:以什么方式?你能详细说明一下吗?
0赞 alistair 3/9/2020
编辑当然清除了它。无论如何,像这样的字符串循环不应该被认可,因为它们相当慢,并且可能会在每秒运行多次的大规模应用程序中导致主线程出现重大滞后。
0赞 Luiz Felipe 5/7/2020
“ 像这样的字符串循环不应该被认可 ” 如果这种编程语言不是那么糟糕,那就太好了
15赞 sajadre 5/15/2019 #50

在不使用任何正则表达式的情况下执行此操作的最简单方法是拆分连接,如下所示:

var str = "Test abc test test abc test test test abc test test abc";
console.log(str.split('abc').join(''));

0赞 Nouman Dilshad 5/20/2019 #51

所有的答案都被接受,你可以通过多种方式做到这一点。执行此操作的诀窍之一是:

const str = "Test abc test test abc test test test abc test test abc";

const compare = "abc";
arrayStr = str.split(" ");
arrayStr.forEach((element, index) => {
  if (element == compare) {
    arrayStr.splice(index, 1);
  }
});
const newString = arrayStr.join(" ");
console.log(newString);

73赞 Indrajeet Singh 5/29/2019 #52

要更换一次,请使用:

var res = str.replace('abc', "");

如需多次更换,请使用:

var res = str.replace(/abc/g, "");

评论

0赞 Sarath 9/12/2023
var res = str.replace(/abc/gi, “”);忽略大小写
7赞 Raghavendra S 5/30/2019 #53

检查这个答案。也许它会有所帮助,我在我的项目中使用了它。

function replaceAll(searchString, replaceString, str) {
    return str.split(searchString).join(replaceString);
}

replaceAll('abc', '',"Test abc test test abc test test test abc test test abc" ); // "Test  test test  test test test  test test "
1赞 Stefan Steiger 7/11/2019 #54

您可以在没有正则表达式的情况下执行此操作,但如果替换文本包含搜索文本,则需要小心。

例如

replaceAll("nihIaohi", "hI", "hIcIaO", true)

所以这里是 replaceAll 的适当变体,包括 string-prototype:

function replaceAll(str, find, newToken, ignoreCase)
{
    let i = -1;

    if (!str)
    {
        // Instead of throwing, act as COALESCE if find == null/empty and str == null
        if ((str == null) && (find == null))
            return newToken;

        return str;
    }

    if (!find) // sanity check 
        return str;

    ignoreCase = ignoreCase || false;
    find = ignoreCase ? find.toLowerCase() : find;

    while ((
        i = (ignoreCase ? str.toLowerCase() : str).indexOf(
            find, i >= 0 ? i + newToken.length : 0
        )) !== -1
    )
    {
        str = str.substring(0, i) +
            newToken +
            str.substring(i + find.length);
    } // Whend 

    return str;
}

或者,如果你想有一个字符串原型函数:

String.prototype.replaceAll = function (find, replace) {
    let str = this;

    let i = -1;

    if (!str)
    {
        // Instead of throwing, act as COALESCE if find == null/empty and str == null
        if ((str == null) && (find == null))
            return newToken;

        return str;
    }

    if (!find) // sanity check 
        return str;

    ignoreCase = ignoreCase || false;
    find = ignoreCase ? find.toLowerCase() : find;

    while ((
        i = (ignoreCase ? str.toLowerCase() : str).indexOf(
            find, i >= 0 ? i + newToken.length : 0
        )) !== -1
    )
    {
        str = str.substring(0, i) +
            newToken +
            str.substring(i + find.length);
    } // Whend 

    return str;
};
2赞 Rakib Uddin 10/4/2019 #55
str = "Test abc test test abc test test test abc test test abc"

str.split(' ').join().replace(/abc/g,'').replace(/,/g, ' ')
4赞 CertainPerformance 10/18/2019 #56

现在已经有一个完整的提案,可以集成到官方规范中。最终,开发人员将不必提出自己的实现 - 相反,现代 JavaScript 引擎将原生支持它。String.prototype.replaceAllreplaceAll

该提案处于第 4 阶段,这意味着一切都已完成,剩下的就是让浏览器开始实现它。

已在最新版本的 Chrome、Firefox 和 Safari 中提供。

以下是实施细节:

根据当前的 TC39 共识,除以下两种情况,在所有情况下的行为都相同:String.prototype.replaceAllString.prototype.replace

  1. 如果是字符串,则仅替换 的单个匹配项,而替换 的所有匹配项(就好像使用了全局和正确转义的正则表达式一样)。searchValueString.prototype.replacesearchValueString.prototype.replaceAllsearchValue.split(searchValue).join(replaceValue)
  2. If 是非全局正则表达式,替换单个匹配项,而引发异常。这样做是为了避免缺少全局标志(这意味着“不要全部替换”)和被调用方法的名称(强烈建议“全部替换”)之间的固有混淆。searchValueString.prototype.replaceString.prototype.replaceAll

值得注意的是,其行为类似于 if 是全局正则表达式。String.prototype.replaceAllString.prototype.replacesearchValue

您可以在此处看到符合规范的 polyfill

在受支持的环境中,以下代码片段将记录 ,而不会引发错误:foo-bar-baz

const str = 'foo bar baz';
console.log(
  str.replaceAll(' ', '-')
);

13赞 Thomas Orlita 11/11/2019 #57

截至 2020 年 8 月,ECMAScript 有一个第 4 阶段建议,该建议将 replaceAll 方法添加到 .String

Chrome 85+、Edge 85+、Firefox 77+、Safari 13.1+ 现在支持此功能。

用法与 replace 方法相同:

String.prototype.replaceAll(searchValue, replaceValue)

下面是一个用法示例:

'Test abc test test abc test.'.replaceAll('abc', 'foo'); // -> 'Test foo test test foo test.'

大多数现代浏览器都支持它,但存在 polyfills:

它在实验标志后面的 V8 发动机中受支持。 在 V8 网站上阅读更多内容。--harmony-string-replaceall

评论

0赞 pcworld 6/3/2020
根据 MDN 的说法,自 Firefox 77 和 Chromium 85 以来,这已经可用。
-2赞 Ws Memon 11/22/2019 #58

检查这个。我相信它会帮助你:

<!DOCTYPE html>
<html>
<body>
<p>Click the button to do a global search and replace for "is" in a string.</p>
<button onclick="myFunction()">Try it</button>
<p id="demo"></p>
<script>
function myFunction() {
  var str = 'Is this "3" dris "3"?';
  var allvar= '"3"';
  var patt1 = new RegExp( allvar, 'g' );
  document.getElementById("demo").innerHTML = str.replace(patt1,'"5"');
}
</script>
</body>
</html>

这里是 JSFiddle 链接

3赞 Ace 12/13/2019 #59

2019 年 11 月,JavaScript 中添加了一项新功能。string.prototype.replaceAll()

目前它只支持 Babel,但也许将来它可以在所有浏览器中实现。有关更多信息,请阅读此处

评论

5赞 Ali 12/13/2019
哇,javascript 终于增加了 Java 1.0 在 1995 年所拥有的东西。伟大!
38赞 Kamil Kiełczewski 12/28/2019 #60

性能

今天 27.12.2019 我在 macOS v10.13.6 (High Sierra) 上对所选解决方案进行测试。

结论

  • C) 是适用于所有字符串的一个很好的跨浏览器快速解决方案。str.replace(/abc/g, '');
  • 基于(A,B)或(C,D)的求解速度很快split-joinreplace
  • 基于 (E,F,G,H) 的解速度很慢 - 对于小字符串,通常慢 ~4 倍,对于长字符串,通常慢约 ~3000 倍 (!)while
  • 递归解决方案(RA,RB)速度较慢,不适用于长字符串

我还创建了自己的解决方案。看起来目前它是完成问题工作的最短的一个:

str.split`abc`.join``

str = "Test abc test test abc test test test abc test test abc";
str = str.split`abc`.join``

console.log(str);

测试是在Chrome 79.0、Safari 13.0.4和Firefox 71.0(64位)上进行的。测试并使用递归。结果RARB

Enter image description here

短字符串 - 55 个字符

您可以在此处在计算机上运行测试。Chrome的结果:

Enter image description here

长字符串:275 000 个字符

RARB 给出的递归解

RangeError:超出最大调用堆栈大小

对于 1M 字符,他们甚至会破坏 Chrome

enter image description here

我尝试对其他解决方案的 1M 字符执行测试,但 E、F、G、H 花费了太多时间,以至于浏览器要求我中断脚本,所以我将测试字符串缩小到 275K 个字符。您可以在此处在计算机上运行测试。Chrome 搜索结果

enter image description here

测试中使用的代码

var t="Test abc test test abc test test test abc test test abc"; // .repeat(5000)
var log = (version,result) => console.log(`${version}: ${result}`);


function A(str) {
  return str.split('abc').join('');
}

function B(str) {
  return str.split`abc`.join``; // my proposition
}


function C(str) {
  return str.replace(/abc/g, '');
}

function D(str) {
  return str.replace(new RegExp("abc", "g"), '');
}

function E(str) {
  while (str.indexOf('abc') !== -1) { str = str.replace('abc', ''); }
  return str;
}

function F(str) {
  while (str.indexOf('abc') !== -1) { str = str.replace(/abc/, ''); }
  return str;
}

function G(str) {
  while(str.includes("abc")) { str = str.replace('abc', ''); }
  return str;
}

// src: https://stackoverflow.com/a/56989553/860099
function H(str)
{
    let i = -1
    let find = 'abc';
    let newToken = '';

    if (!str)
    {
        if ((str == null) && (find == null)) return newToken;
        return str;
    }

    while ((
        i = str.indexOf(
            find, i >= 0 ? i + newToken.length : 0
        )) !== -1
    )
    {
        str = str.substring(0, i) +
            newToken +
            str.substring(i + find.length);
    }
    return str;
}

// src: https://stackoverflow.com/a/22870785/860099
function RA(string, prevstring) {
  var omit = 'abc';
  var place = '';
  if (prevstring && string === prevstring)
    return string;
  prevstring = string.replace(omit, place);
  return RA(prevstring, string)
}

// src: https://stackoverflow.com/a/26107132/860099
function RB(str) {
  var find = 'abc';
  var replace = '';
  var i = str.indexOf(find);
  if (i > -1){
    str = str.replace(find, replace);
    i = i + replace.length;
    var st2 = str.substring(i);
    if(st2.indexOf(find) > -1){
      str = str.substring(0,i) + RB(st2, find, replace);
    }
  }
  return str;
}




log('A ', A(t));
log('B ', B(t));
log('C ', C(t));
log('D ', D(t));
log('E ', E(t));
log('F ', F(t));
log('G ', G(t));
log('H ', H(t));
log('RA', RA(t)); // use reccurence
log('RB', RB(t)); // use reccurence
<p style="color:red">This snippet only presents codes used in tests. It not perform test itself!<p>

评论

3赞 Márk Gergely Dolinka 12/31/2019
现在这是一个深入的答案!谢谢!虽然,我很好奇的是为什么“新正则表达式(...)”语法会带来如此多的改进。
0赞 Lova Chittumuri 2/6/2020 #61

我们可以在 JavaScript 中使用 replace 方法:

var result = yourString.replace('regexPattern', "replaceString");

var str = "Test abc test test abc test test test abc test test abc";

var expectedString = str.replace(/abc(\s|$)/g, "");

console.log(expectedString);

0赞 e102 3/2/2020 #62

我知道这不是最好的方法,但你可以试试这个:

var annoyingString = "Test abc test test abc test test test abc test test abc";

while (annoyingString.includes("abc")) {
    annoyingString = annoyingString.replace("abc", "")
}
0赞 Shavais 5/24/2020 #63

我在“库”部分的这个性能测试页面中添加了以下函数:

https://jsben.ch/LFfWA

function _replace(t, s, r){
    var i = t.indexOf(s);
    if (i == -1) return t;
    return t.slice(0, i) + r + _replace(t.slice(i + s.length, t.length), s,r);
}

..并将其作为测试:

var replaced = _replace(testString, 'abc', '123');

..对我来说,该函数的执行速度比 split 或正则表达式快约 34%。这个想法/希望是最终将越来越小的字符串片段粘贴到堆栈上,然后通过展开堆栈来构建整个结果,从而最大限度地减少额外的字符串副本和通过相同的字符串数据进行的额外搜索,并希望优化 CPU 缓存的使用。

部分想法是,如果字符串不是太大,它最终可能会进入 CPU 缓存;传递它并粘贴它的一部分,将这些位放入缓存中,然后搜索可以完全使用 CPU 缓存数据进行操作。现在,无论这是否真的是最终发生的事情,我敢肯定,这完全取决于 JavaScript 的实现。

这不是尽可能快的,但它是我在没有可变字符串的情况下所能管理的。JavaScript 中的数组可能每个元素都有一个指针,因此,涉及大量数组元素的解决方案不太可能像这样对 CPU 缓存友好。

评论

0赞 Peter Mortensen 9/25/2022
Re “执行速度提高了约 34%”:它测试了什么?浏览器、JavaScript 运行时、硬件、操作系统等。所有版本和规格(例如时钟速度、CPU 类型等)。
0赞 Matěj Štágl 6/9/2020 #64

从 v85 开始,Chrome 现在支持原生。请注意,这优于所有其他建议的解决方案,一旦得到主要支持,就应使用。String.prototype.replaceAll

功能状态:https://chromestatus.com/feature/6040389083463680

var s = "hello hello world";
s = s.replaceAll("hello", ""); // s is now "world"
console.log(s)

4赞 Iftikhar Hussain 6/22/2020 #65

这是一个非常简单的解决方案。 可以将新方法分配给 String 对象

String.prototype.replaceAll = function(search, replace){
   return this.replace(new RegExp(search, 'g'), replace)
}

var str = "Test abc test test abc test test test abc test test abc";
str = str.replaceAll('abc', '');

console.log(str) // -> Test  test test  test test test  test test

评论

1赞 Moritz 7/28/2020
分配给全局对象的原型称为原型填充,被认为是一种非常糟糕的反模式。它只适用于为尚不支持函数的旧引擎实现函数指定行为的 polyfill。此实现具有与规范不同的语义。 考虑 'hi'.replaceAll('.', 'x') // => 'xx'
0赞 Iftikhar Hussain 7/30/2020
谢谢莫里茨,我认为扩展或修改任何对象的原型,尤其是原生对象的原型被认为是不好的做法,但不要添加新方法如果您有任何来源请分享
2赞 Moritz 7/31/2020
扩展和“添加新方法”对我来说似乎是一回事。这是一个问题,因为现在规范中实际上有一个 replaceAll 方法,它具有不同的语义,即使在外部依赖项中也可能会破坏代码。请参见:flaviocopes.com/javascript-why-not-modify-object-prototype
3赞 Asakkour Soufiane 7/8/2020 #66

使用拆分联接

var str = "Test abc test test abc test test test abc test test abc";
var replaced_str = str.split('abc').join('');
console.log(replaced_str);

评论

0赞 Peter Mortensen 9/25/2022
像以前的许多答案一样。有什么不同?
0赞 zed 1/2/2023
拆分和联接是一种很好的方法,原因有两个: 1- 可用性取决于您使用的 NodeJS 版本。2- 如果搜索的替换值包含字符,则使用 with 正则表达式全局标志变得更加困难。replaceAllString.prototype.replaceAllreplace
-1赞 Mohit Yadav 8/25/2020 #67

我建议通过将字符串类附加到原型链中来为字符串类添加一个全局方法。

String.prototype.replaceAll = function(fromReplace, toReplace, {ignoreCasing} = {}) { return this.replace(new RegExp(fromReplace, ignoreCasing ? 'ig': 'g'), toReplace);}

它可以像以下方式使用:

'stringwithpattern'.replaceAll('pattern', 'new-pattern')

评论

0赞 Khalid Khan 8/25/2020
你能详细说明上面的代码在做什么吗?试着给出正确的答案,而不是一个衬里。
0赞 Mohit Yadav 8/25/2020
@KhalidKhan更新了,无论如何它是不言自明的,但由于删除投票,这是不必要的,我更新了答案,任何要求删除的人现在都可以尝试理解。
0赞 Jake Coxon 8/26/2020
这不起作用,尝试在您的示例中解构 undefined。并且在使用箭头函数时不引用字符串{ignoreCasing}this
1赞 Mohit Yadav 8/26/2020
@JakeCoxon是的,我的坏,更新了答案以解决问题:D干杯!
1赞 Nisharg Shah 8/26/2020 #68

2020年8月

没有更多的正则表达式的东西

const str = "Test abc test test abc test test test abc test test abc";
const modifiedStr = str.replaceAll('abc', '');
console.log(modifiedStr);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll

评论

0赞 raven 3/12/2021
Uncaught TypeError: str.replaceAll is not a function",
0赞 Nisharg Shah 3/13/2021
只有现代浏览器支持它,如果您不使用现代浏览器,请使用regex
0赞 Peter Mortensen 9/25/2022
至少一个先前的答案已经涵盖了这一点。
0赞 Nisharg Shah 9/26/2022
@PeterMortensen 可能是我错了,但当我发布这个答案时,没有人有这个解决方案
0赞 Nisharg Shah 9/26/2022
我只记得,我在这个问题的前 3 个答案上留下了我的答案评论,结果被删除了,第二天他们在不承认我的情况下编辑了答案。作为证明,您可以在投票最多的答案中看到第 14 次修订 stackoverflow.com/posts/1144788/revisions
2赞 Drewry Pope 9/7/2020 #69

该解决方案结合了以前的一些答案,并且更符合建议的 2020 年 8 月标准解决方案。这个解决方案在 2020 年 9 月对我来说仍然可行,因为我使用的 Node.js 二进制文件中不可用。String.replaceAll


RegExp.escape是一个单独的问题,但在这里很重要,因为官方提出的解决方案将自动转义基于输入。这个 polyfill 不会没有逻辑。stringfindString.replaceAllRegExp.escape

我添加了一个不 polyfill 的答案,以防您不想要。RegExp.Escape


如果将正则表达式传递给 ,则必须包含为标志。这个 polyfill 不会为你提供一个很好的 TypeError,并且会给你带来一个重大的糟糕时刻。findg

如果你需要精确的标准一致性,对于一个严格依赖标准实现的应用程序,那么我建议使用 Babel 或其他一些工具来让你每次都能得到“正确的答案”,而不是 Stack Overflow。这样你就不会有任何意外。


法典:

if (!Object.prototype.hasOwnProperty.call(RegExp, 'escape')) {
  RegExp.escape = function(string) {
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#Escaping
    // https://github.com/benjamingr/RegExp.escape/issues/37
    return string.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
  };
}

if (!Object.prototype.hasOwnProperty.call(String, 'replaceAll')) {
  String.prototype.replaceAll = function(find, replace) {
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
    // If you pass a RegExp to 'find', you _MUST_ include 'g' as a flag.
    // TypeError: "replaceAll must be called with a global RegExp" not included, will silently cause significant errors. _MUST_ include 'g' as a flag for RegExp.
    // String parameters to 'find' do not require special handling.
    // Does not conform to "special replacement patterns" when "Specifying a string as a parameter" for replace
    // Does not conform to "Specifying a function as a parameter" for replace
    return this.replace(
          Object.prototype.toString.call(find) == '[object RegExp]' ?
            find :
            new RegExp(RegExp.escape(find), 'g'),
          replace
        );
  }
}

代码,缩小:

Object.prototype.hasOwnProperty.call(RegExp,"escape")||(RegExp.escape=function(e){return e.replace(/[.*+\-?^${}()|[\]\\]/g,"\\$&")}),Object.prototype.hasOwnProperty.call(String,"replaceAll")||(String.prototype.replaceAll=function(e,t){return this.replace("[object RegExp]"==Object.prototype.toString.call(e)?e:new RegExp(RegExp.escape(e),"g"),t)});

例:

console.log(
  't*.STVAL'
    .replaceAll(
      new RegExp(RegExp.escape('T*.ST'), 'ig'),
      'TEST'
    )
);

console.log(
  't*.STVAL'
    .replaceAll(
      't*.ST',
      'TEST'
    );
);

不带代码:RegExp.Escape

if (!Object.prototype.hasOwnProperty.call(String, 'replaceAll')) {
  String.prototype.replaceAll = function(find, replace) {
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replaceAll
    // If you pass a RegExp to 'find', you _MUST_ include 'g' as a flag.
    // TypeError: "replaceAll must be called with a global RegExp" not included, will silently cause significant errors. _MUST_ include 'g' as a flag for RegExp.
    // String parameters to 'find' do not require special handling.
    // Does not conform to "special replacement patterns" when "Specifying a string as a parameter" for replace
    // Does not conform to "Specifying a function as a parameter" for replace
    return this.replace(
          Object.prototype.toString.call(find) == '[object RegExp]' ?
            find :
            new RegExp(find.replace(/[.*+\-?^${}()|[\]\\]/g, '\\$&'), 'g'),
          replace
        );
  }
}

代码不带,缩小:RegExp.Escape

Object.prototype.hasOwnProperty.call(String,"replaceAll")||(String.prototype.replaceAll=function(e,t){return this.replace("[object RegExp]"==Object.prototype.toString.call(e)?e:new RegExp(e.replace(/[.*+\-?^${}()|[\]\\]/g,"\\$&"),"g"),t)});

评论

0赞 Drewry Pope 9/13/2020
RegExp.Escape 基于我在这里链接的答案:stackoverflow.com/a/63838890/5979634
1赞 MMMahdy-PAPION 1/2/2022
无论如何都会返回 false,因为它归 所以它应该是这样的:Object.prototype.hasOwnProperty.call(String, 'replaceAll')String.prototypeObject.prototype.hasOwnProperty.call(String.prototype, 'replaceAll')
0赞 Sebastian 3/15/2023
MMMahdy-PAPION 是对的,但除此之外,简单地检查会更简单、更透明String.prototype.hasOwnProperty('replaceAll')
0赞 Chungmin Park 2/20/2021 #70

有一种方法可以使用新方法。replaceAll()

但是您需要使用尖端的浏览器或 JavaScript 运行时环境。

您可以在此处检查浏览器兼容性。

2赞 Satish Chandra Gupta 4/19/2021 #71

JavaScript 提供了一种直接的方法,可以将字符串的一部分替换为另一个字符串,并且还有一些技巧可以做到这一点。

替换您可以在 JavaScript 中使用 or 方法的所有匹配项。replace()replaceAll

  1. replace() method- 要使用此方法替换所有元素,请使用正则表达式作为模式来查找匹配的字符串,然后将其替换为新字符串。请考虑将标志与它一起使用。/g

const str = "To do or not to do";
const pattern = /do/g;
const replaceBy = "Code";
console.log(str.replace(pattern, replaceBy));

  1. replaceAll() method- 要使用此方法替换所有元素,请使用字符串或正则表达式作为模式来查找匹配的字符串,然后将其替换为新字符串。我们必须在 replaceAll 方法中使用带有正则表达式的标志。/g

const str = "To do or not to do";
const pattern = "do";
const replaceBy = "Code";
console.log(str.replaceAll(pattern, replaceBy));

const pattern2 = /do/g;
console.log(str.replaceAll(pattern2, replaceBy));

替代方法:使用拆分和联接方法

将字符串拆分为要替换的内容,并使用新字符串作为分隔符进行联接。请参阅示例。

const str = "To do or not to do";
const newStr = str.split("do").join("Code");
console.log(newStr);

1赞 Force Bolt 6/7/2021 #72
// Try this way

const str = "Test abc test test abc test test test abc test test abc";
const result = str.split('abc').join('');
console.log(result);
9赞 francis 7/25/2021 #73

使用正则表达式 i 标志表示不区分大小写

console.log('App started'.replace(/a/g, '')) // Result: "App strted"
console.log('App started'.replace(/a/gi, '')) // Result: "pp strted"
13赞 Oliver M Grech 8/30/2021 #74

经过几次尝试和多次失败,我发现在浏览器兼容性和易用性方面,以下功能似乎是最好的全能型。这是我发现的旧浏览器的唯一有效解决方案。(是的,即使不鼓励使用旧浏览器并且已经过时,某些旧版应用程序仍然大量使用 OLE 浏览器(例如旧的 Visual Basic 6 应用程序或带有窗体的 Excel .xlsm 宏)。

无论如何,这是一个简单的函数。

function replaceAll(str, match, replacement){
   return str.split(match).join(replacement);
}

评论

1赞 Sebastian Simon 8/30/2021
这已经在其他18个答案中提出或提及,并在问题下的评论中提到。兼容性注意事项很容易在 CanIUseMDN 上找到。这都是在接受的答案中提到的。
0赞 Oliver M Grech 8/30/2021
乍一看,我没有发现任何在遗留代码中提及旧浏览器和 OLE 实现的内容。只是认为它可能会帮助某人,没有必要对有用的答案投反对票。你也不必投赞成票,我只关心有人可能会觉得它有用。尽管如此,感谢您的贡献
2赞 pedro casas 9/29/2021 #75

重复上述步骤,直到将它们全部替换完毕:

const regex = /^>.*/im;
while (regex.test(cadena)) {
    cadena = cadena.replace(regex, '*');
}

评论

0赞 Sebastian Simon 9/29/2021
此方法将替换仅在替换后才出现的实例。例如,当替换所有出现的 by 时,给定输入字符串应该产生输出,但你的方法将产生 ."bc""b""abcc""abc""ab"
0赞 pedro casas 9/30/2021
正如 Sebastian 所说,这个简单的脚本还会删除与表达式匹配的结果。这有其好的一面和坏的一面。坏消息已经被他告诉了。好消息是,它对于在 XSS 和 JavaScript Inject 攻击中删除 JS 标签非常有用。
21赞 Ran Turner 10/16/2021 #76

String.prototype.replaceAll - ECMAScript 2021

new 方法返回一个新字符串,其中模式的所有匹配项都替换为替换项。模式可以是字符串或 ,替换可以是字符串或要为每个匹配项调用的函数。String.prototype.replaceAll()RegExp

const message = 'dog barks meow meow';
const messageFormatted = message.replaceAll('meow', 'woof')

console.log(messageFormatted);

评论

7赞 Sebastian Simon 10/16/2021
replaceAll已经在近 20 个其他答案和评论中被提出,包括接受的答案和得票最高的答案。这增加了什么?
0赞 RixTheTyrunt 3/20/2022
如果要在 Node.js 中查找该方法,这将不起作用。replit.com/@RixTheTyrunt/rixxyplayer-parser?v=1
2赞 Sebastian Simon 3/21/2022
@RixTheTyrunt 当然,这将在最新版本的 Node.js 中起作用。
0赞 Beyondo 7/31/2023
@RixTheTyrunt 不,它会起作用。如果您使用的是 Typescript,请确保在文件内设置 to 或 above。targetes2021compilerOptionstsconfig.json
0赞 Alecx 12/9/2021 #77

我已经阅读了这个问题和答案,但我没有找到适合我的解决方案。尽管答案非常有用,但我决定从头开始创建自己的解决方案。这种替换的问题是:

  • 通常,仅仅找到一个与任何大写或小写匹配的字符串是不够的。例如,对于搜索结果,我需要将其替换为相同的大小写
  • 如果我处理innerHTML,我很容易损坏HTML标签(例如,href属性中出现hr)。
  • replaceAll() 方法对于许多用例来说太新鲜了,它并不能解决所有问题。

因此,我正在编写函数来突出显示表格中的搜索结果,其中表格数据单元格内部可能包含链接以及其他 HTML 标签。而这些链接本来是要保留的,所以innerText是不够的。

我决定为有相同问题的每个人提供解决方案。当然,您不仅可以将其用于表格,还可以将其用于任何元素。代码如下:

/* Iterate over table data cells to insert a highlight tag */
function highlightSearchResults(textFilter) {
  textFilter = textFilter.toLowerCase().replace('<', '&lt;').replace('>', '&gt;');
  let tds;
  tb = document.getElementById('sometable'); //root element where to search
  if (tb) {
    tds = tb.getElementsByTagName("td"); //sub-elements where to make replacements
  }
  if (textFilter && tds) {
    for (td of tds) {
      //specify your span class or whatever you need before and after
      td.innerHTML = insertCaseInsensitive(td.innerHTML, textFilter, '<span class="highlight">', '</span>');
    }
  }
}

/* Insert a highlight tag */
function insertCaseInsensitive(srcStr, lowerCaseFilter, before, after) {
  let lowStr = srcStr.toLowerCase();
  let flen = lowerCaseFilter.length;
  let i = -1;
  while ((i = lowStr.indexOf(lowerCaseFilter, i + 1)) != -1) {
    if (insideTag(i, srcStr)) continue;
    srcStr = srcStr.slice(0, i) + before + srcStr.slice(i, i+flen) + after + srcStr.slice(i+flen);
    lowStr = srcStr.toLowerCase();
    i += before.length + after.length;
  }
  return srcStr;
}

/* Check if an ocurrence is inside any tag by index */
function insideTag(si, s) {
  let ahead = false;
  let back = false;
  for (let i = si; i < s.length; i++) {
    if (s[i] == "<") {
      break;
    }
    if (s[i] == ">") {
      ahead = true;
      break;
    }
  }
  for (let i = si; i >= 0; i--) {
    if (s[i] == ">") {
      break;
    }
    if (s[i] == "<") {
      back = true;
      break;
    }
  }
  return (ahead && back);
}

评论

0赞 Sebastian Simon 12/9/2021
相关:如何动态突出显示网页上的字符串?使用 JS 查找和替换文档中的特定文本字符。这两个链接都指向我的答案,其中对如何替换文档中的文本内容进行了相当深入的介绍。
0赞 Alecx 12/10/2021
哦,那些答案与突出显示有关!但是,我只发现这个与替换相关的线程正在寻找一些替换解决方案。现在我尝试了这些功能:如果我没看错,它们不会以不区分大小写的方式突出显示,我的意思是:如果找到短语“Text”或“TEXT”(甚至“TexT”、“tExT”等),它们应该按原样突出显示,而不是转换为小写/大写。您的代码片段的好处是它们可以完成整个文档和现成的解决方案。我的这些功能应该根据个人的需求进行调整,我认为这很容易。
17赞 MMMahdy-PAPION 12/26/2021 #78

当然,在2021年,正确的答案是:

字符串.prototype.replaceAll()

console.log(
  'Change this and this for me'.replaceAll('this','that') // Normal case
);
console.log(
  'aaaaaa'.replaceAll('aa','a') // Challenged case
);

如果您不想处理 replace() + RegExp

但是,如果浏览器是 2020 年之前的呢?

在这种情况下,我们需要 polyfill(强制旧浏览器支持新功能)(我认为几年是必要的)。 我在答案中找不到完全正确的方法。因此,我建议将这个函数定义为 polyfill。

我建议的 polyfill 选项:replaceAll

replaceAllpolyfill(有全局标志错误)(更原则的版本)
if (!String.prototype.replaceAll) { // Check if the native function not exist
    Object.defineProperty(String.prototype, 'replaceAll', { // Define replaceAll as a prototype for (Mother/Any) String
        configurable: true, writable: true, enumerable: false, // Editable & non-enumerable property (As it should be)
        value: function(search, replace) { // Set the function by closest input names (For good info in consoles)
            return this.replace( // Using native String.prototype.replace()
                Object.prototype.toString.call(search) === '[object RegExp]' // IsRegExp?
                    ? search.global // Is the RegEx global?
                        ? search // So pass it
                        : function(){throw new TypeError('replaceAll called with a non-global RegExp argument')}() // If not throw an error
                    : RegExp(String(search).replace(/[.^$*+?()[{|\\]/g, "\\$&"), "g"), // Replace all reserved characters with '\' then make a global 'g' RegExp
                replace); // passing second argument
        }
    });
}
replaceAllpolyfill (本身缺少处理全局标志) (我的第一偏好) - 为什么?
if (!String.prototype.replaceAll) { // Check if the native function not exist
    Object.defineProperty(String.prototype, 'replaceAll', { // Define replaceAll as a prototype for (Mother/Any) String
        configurable: true, writable: true, enumerable: false, // Editable & non-enumerable property (As it should be)
        value: function(search, replace) { // Set the function by closest input names (For good info in consoles)
            return this.replace( // Using native String.prototype.replace()
                Object.prototype.toString.call(search) === '[object RegExp]' // IsRegExp?
                    ? search.global // Is the RegEx global?
                        ? search // So pass it
                        : RegExp(search.source, /\/([a-z]*)$/.exec(search.toString())[1] + 'g') // If not, make a global clone from the RegEx
                    : RegExp(String(search).replace(/[.^$*+?()[{|\\]/g, "\\$&"), "g"), // Replace all reserved characters with '\' then make a global 'g' RegExp
                replace); // passing second argument
        }
    });
}
缩小(我的第一偏好):
if(!String.prototype.replaceAll){Object.defineProperty(String.prototype,'replaceAll',{configurable:!0,writable:!0,enumerable:!1,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)}})}
尝试一下:

if(!String.prototype.replaceAll){Object.defineProperty(String.prototype,'replaceAll',{configurable:!0,writable:!0,enumerable:!1,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)}})}

console.log(
  'Change this and this for me'.replaceAll('this','that')
); // Change that and that for me

console.log(
  'aaaaaa'.replaceAll('aa','a')
); // aaa

console.log(
  '{} (*) (*) (RegEx) (*) (\*) (\\*) [reserved characters]'.replaceAll('(*)','X')
); // {} X X (RegEx) X X (\*) [reserved characters]

console.log(
  'How (replace) (XX) with $1?'.replaceAll(/(xx)/gi,'$$1')
); // How (replace) ($1) with $1?

console.log(
  'Here is some numbers 1234567890 1000000 123123.'.replaceAll(/\d+/g,'***')
); // Here is some numbers *** *** *** and need to be replaced.

console.log(
  'Remove numbers under 233: 236   229  711   200   5'.replaceAll(/\d+/g, function(m) {
    return parseFloat(m) < 233 ? '' : m
  })
); // Remove numbers under 233: 236     711

console.log(
  'null'.replaceAll(null,'x')
); // x


// The difference between My first preference and the original:
// Now in 2022 with browsers > 2020 it should throw an error (But possible it be changed in future)

//   console.log(
//      'xyz ABC abc ABC abc xyz'.replaceAll(/abc/i,'')
//   );

// Browsers < 2020:
// xyz     xyz
// Browsers > 2020
// TypeError: String.prototype.replaceAll called with a non-global RegExp

浏览器支持:
  • Internet Explorer 9 及更高版本(基于 Internet Explorer 11)。
  • 所有其他浏览器(2012 年之后)。

结果与本机 replaceAll 相同,如果第一个参数输入为:、、、、、nullundefinedObjectFunctionDateRegExpNumberString

参考: 22.1.3.19 String.prototype.replaceAll ( searchValue, replaceValue) + RegExp 语法

重要提示:正如一些专业人士所提到的,答案中建议的许多递归函数将返回错误的结果。(使用上述代码片段的受质疑案例进行尝试。 也许一些棘手的方法,如 .split('searchValue').join('replaceValue') 或一些管理良好的函数给出相同的结果,但性能肯定比native replaceAll() / polyfill replaceAll() / replace() + RegExp


polyfill 分配的其他方法

幼稚,但支持更旧的浏览器(最好避免)

例如,我们也可以支持 IE7+,不使用 Object.defineProperty() 并使用我以前的朴素赋值方法:

if (!String.prototype.replaceAll) {
    String.prototype.replaceAll = function(search, replace) { // <-- Naive method for assignment
        // ... (Polyfill code Here)
    }
}

它应该适用于IE7+上的基本用途。
正如@sebastian-simon在这里解释的那样,在更高级的用途中,这可能会产生次要问题。例如:

for (var k in 'hi') console.log(k);
// 0
// 1
// replaceAll  <-- ?
完全值得信赖,但很重

事实上,我建议的选择有点乐观。就像我们信任环境(浏览器和 Node.js)一样,它肯定是在 2012-2021 年左右。此外,它是一个标准/著名的,因此不需要任何特殊考虑。

但是可能会有更老的浏览器一些意想不到的问题,polyfills 仍然可以支持和解决更多可能的环境问题。因此,如果我们需要尽可能大的支持,我们可以使用 polyfill 库,例如:

https://polyfill.io/

专门用于 replaceAll

<script src="https://polyfill.io/v3/polyfill.min.js?features=String.prototype.replaceAll"></script>