As of August 2020: Modern browsers have support for the String.replaceAll() method defined by the ECMAScript 2021 language specification.
For older/legacy browsers:
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Here is how this answer evolved:
str = str.replace(/abc/g, '');
In response to comment "what's if 'abc' is passed as a variable?":
var find = 'abc';
var re = new RegExp(find, 'g');
str = str.replace(re, '');
In response to Click Upvote's comment, you could simplify it even more:
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
Note: Regular expressions contain special (meta) characters, and as such it is dangerous to blindly pass an argument in the find function above without pre-processing it to escape those characters. This is covered in the Mozilla Developer Network's JavaScript Guide on Regular Expressions, where they present the following utility function (which has changed at least twice since this answer was originally written, so make sure to check the MDN site for potential updates):
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
So in order to make the replaceAll() function above safer, it could be modified to the following if you also include escapeRegExp:
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Answer from user21926 on Stack OverflowAs of August 2020: Modern browsers have support for the String.replaceAll() method defined by the ECMAScript 2021 language specification.
For older/legacy browsers:
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Here is how this answer evolved:
str = str.replace(/abc/g, '');
In response to comment "what's if 'abc' is passed as a variable?":
var find = 'abc';
var re = new RegExp(find, 'g');
str = str.replace(re, '');
In response to Click Upvote's comment, you could simplify it even more:
function replaceAll(str, find, replace) {
return str.replace(new RegExp(find, 'g'), replace);
}
Note: Regular expressions contain special (meta) characters, and as such it is dangerous to blindly pass an argument in the find function above without pre-processing it to escape those characters. This is covered in the Mozilla Developer Network's JavaScript Guide on Regular Expressions, where they present the following utility function (which has changed at least twice since this answer was originally written, so make sure to check the MDN site for potential updates):
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}
So in order to make the replaceAll() function above safer, it could be modified to the following if you also include escapeRegExp:
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
For the sake of completeness, I got to thinking about which method I should use to do this. There are basically two ways to do this as suggested by the other answers on this page.
Note: In general, extending the built-in prototypes in JavaScript is generally not recommended. I am providing as extensions on the String prototype simply for purposes of illustration, showing different implementations of a hypothetical standard method on the String built-in prototype.
Regular Expression Based Implementation
String.prototype.replaceAll = function(search, replacement) {
var target = this;
return target.replace(new RegExp(search, 'g'), replacement);
};
Split and Join (Functional) Implementation
String.prototype.replaceAll = function(search, replacement) {
var target = this;
return target.split(search).join(replacement);
};
Not knowing too much about how regular expressions work behind the scenes in terms of efficiency, I tended to lean toward the split and join implementation in the past without thinking about performance. When I did wonder which was more efficient, and by what margin, I used it as an excuse to find out.
On my Chrome Windows 8 machine, the regular expression based implementation is the fastest, with the split and join implementation being 53% slower. Meaning the regular expressions are twice as fast for the lorem ipsum input I used.
Check out this benchmark running these two implementations against each other.
As noted in the comment below by @ThomasLeduc and others, there could be an issue with the regular expression-based implementation if search contains certain characters which are reserved as special characters in regular expressions. The implementation assumes that the caller will escape the string beforehand or will only pass strings that are without the characters in the table in Regular Expressions (MDN).
MDN also provides an implementation to escape our strings. It would be nice if this was also standardized as RegExp.escape(str), but alas, it does not exist:
function escapeRegExp(str) {
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string
}
We could call escapeRegExp within our String.prototype.replaceAll implementation, however, I'm not sure how much this will affect the performance (potentially even for strings for which the escape is not needed, like all alphanumeric strings).
From gleaning the documentation for replaceAll, we find the following tidbits:
const newStr = str.replaceAll(regexp|substr, newSubstr|function)
Note: When using a
regexpyou have to set the global ("g") flag; otherwise, it will throw a TypeError: "replaceAll must be called with a global RegExp".
In other words, when calling replaceAll with a regex literal or RegExp, it must use the global flag. So, there doesn't seem to be much gained by calling replaceAll versus just using the current replace. However, one difference with replaceAll is that when passing it a string, it will automatically do a global replacement. This is where you might save yourself a bit of typing, by not having to enter a global flag.
There are performance and memory footprint differences between those methods. This might be important in low-level operations that are executed many times on your web page (such as general replacements done on page load). You can get away using replace function most of the time, but never use split/join.
Split-join
Split-join is very inefficient; never use it for replacements. It performs a search, creates an array (possibly very large), and then loops over the array to build a new string. Replacements should simply construct a new string directly.
// ❌ don't do this
console.log(source.split(str1).join(str2));
replaceAll(string) vs replace
Use replaceAll with a string when you can. The call to replaceAll(string, string) will be significantly faster than using a RegExp, as it's easier to optimize. Benchmarks show replaceAll is about 2x faster in Firefox 147 (even for very short strings). Also note that there is no point in compiling regular expressions when you only need to work with strings (new RegExp adds both object creation and parser overhead).
// ✅replaceAll(str) wins over ❌replace(re)
console.log(source.replace(new RegExp(str1,"g"), str2));
//versus
console.log(source.replaceAll(str1, str2));
On top of performance issues, if str1 contains special characters, you might get very unusual results:
// ❌ this will just be wrong; all this is part of a regexp: `[/, '').replace(/]`
'ab[c]'.replace(/[/, '').replace(/]/, ''); // -> b[c]
// ❌ `[` should be escaped and so you get: SyntaxError: unterminated character class.
'ab[c]'.replace(new RegExp('['), '').replace(new RegExp(']'), '')
replaceAll(RegExp) vs replace
When you want to use a regular expression, there is less of a difference between replaceAll and replace. In terms of performance, replace might actually be better, as it has been optimized over a longer period of time in browsers.
// replaceAll(re) ~= replace(re)
console.log(source.replace(regex, replacement));
//versus
console.log(source.replaceAll(regex, replacement));
Note however that it might be a good thing that 'abc'.replaceAll(/abc/, '') throws an error. If your intention is to replace all occurrences, it's very easy to make a mistake and forget the g modifier. So replace might fail silently, but replaceAll will let you know.
/** Replaces all occurrences of "ice" with "summer" */
function replaceIceWithSummer(text) {
// ❌oh no we forgot g, ✅but replaceAll will remind us to replace all of ice
return text.replaceAll(/ice/i, "summer");
}
That is even more important when the regexp is used in many places.