Replacing a substring is a very common task. It should also be a very simple one but actually it isn’t.
String.prototype.replace only replaces the first occurrence when used with a string as pattern argument. A global regex can be used to replace all occurrences instead.
String.prototype.replaceAll will fix that and also replace all occurrences with a string pattern.
We want to replace 🌧 with 🌈 in this weather forecast which is basically a string.
// Input: "Mon: 🌧, Tue: 🌧, Wed 🌧" // Result: "Mon: 🌈, Tue: 🌈, Wed 🌈"
The first approach most (newbie) developers would use is
String.prototype.replace with a substring argument.
replace takes two arguments. The first argument can be either a substring or a regex pattern, the second argument is the replacement substring.
"Mon: 🌧, Tue: 🌧, Wed 🌧".replace("🌧", "🌈");
The result would look like this. Only the first occurrence would be replaced.
// Result: "Mon: 🌈, Tue: 🌧, Wed 🌧"
String.prototype.replace only replaces the first occurrence when used with a substring argument.
The pitfall is that you might test your code for a single replacement but it then fails when the string has more then one occurrence.
I said that would be the approach taken by newbies but honestly I still find myself walking in this trap from time to time.
Now let’s have a look how you can replace all occurrences in a string.
When using a global regex pattern instead of a simple substring for the first argument the
String.prototype.replace function replaces all occurrences.
// Input: "Mon: 🌧, Tue: 🌧, Wed 🌧" // Result: "Mon: 🌈, Tue: 🌈, Wed 🌈" "Mon: 🌧, Tue: 🌧, Wed 🌧".replace(/🌧/g, "🌈");
This approach works, is supported by all browsers and is fast. But it’s harder to read and you have to remember to use the regex pattern if you want to replace all occurrences.
For many use cases a regex is not required and just makes the code a little bit harder to read. That’s were the new
String.prototype.replaceAll comes in. ReplaceAll is a stage 4 proposal but is already supported by most modern browsers.
It allows you to replace all occurrences with the substring argument.
// Input: "Mon: 🌧, Tue: 🌧, Wed 🌧" // Result: "Mon: 🌈, Tue: 🌈, Wed 🌈" "Mon: 🌧, Tue: 🌧, Wed 🌧".replaceAll("🌧", "🌈");
There are a few things to consider.
Compatibility. Check if your targets support
Performance. Both functions are very fast for short strings. If you don’t plan to parse a full book the difference is neglectable.
Here are the results of the benchmark in Safari. Those results differ depending on your browser and machine. They might also change with future browser versions.
"...".replace(/🌧/g, "🌈"); // 130,000,000 ops/s "...".replaceAll("🌧", "🌈"); // 6,300,000 ops/s "...".replaceAll(/🌧/g, "🌈"); // 1,600,000 ops/s
I came up with two simple rules which makes it easier to decide what to use.
Always use replaceAll if your environment supports it. You can use it with the string pattern or the regex pattern and you avoid the pitfall of replacing only the first occurrence. This is imho how replace should work.
If you have to use replace, avoid the string pattern and always use the regex patten. You could even add a linting rule to avoid the pitfall.
I hope I could show you the problem with replace and how to avoid it.
If you liked the article 🙌, spread the word and follow me on Twitter for more posts on web technologies.
Did you find typos 🤓? Please help improve the blogpost and open an issue here
GitHub - tc39/proposal-string-replaceall: ECMAScript proposal: String.prototype.replaceAll
String.prototype.replaceAll · V8
core-js/esnext.string.replace-all.js at master · zloirock/core-js · GitHub