String.prototype.replaceAll
proposal
Champion: Mathias Bynens (Google, @mathiasbynens).
This proposal is at stage 4 of the TC39 process, and is scheduled to be included in ES2021.
(Also see our TL;DR explainer.)
Currently there is no way to replace all instances of a substring in a string without use of a global regexp. String.prototype.replace
only affects the first occurrence when used with a string argument. There is a lot of evidence that developers are trying to do this in JS — see the StackOverflow question with thousands of votes.
Currently the most common way of achieving this is to use a global regexp.
const queryString = 'q=query+string+parameters'; const withSpaces = queryString.replace(/\+/g, ' ');
This approach has the downside of requiring special RegExp characters to be escaped — note the escaped '+'
.
An alternate solution is to combine String#split
with Array#join
:
const queryString = 'q=query+string+parameters'; const withSpaces = queryString.split('+').join(' ');
This approach avoids any escaping but comes with the overhead of splitting the string into an array of parts only to glue it back together.
We propose the addition of a new method to the String prototype - replaceAll
. This would give developers a straight-forward way to accomplish this common, basic operation.
const queryString = 'q=query+string+parameters'; const withSpaces = queryString.replaceAll('+', ' ');
It also removes the need to escape special regexp characters (note the unescaped '+'
).
The proposed signature is the same as the existing String.prototype.replace
method:
String.prototype.replaceAll(searchValue, replaceValue)
Per the current TC39 consensus, String.prototype.replaceAll
behaves identically to String.prototype.replace
in all cases, except for the following two cases:
searchValue
is a string, String.prototype.replace
only replaces a single occurrence of the searchValue
, whereas String.prototype.replaceAll
replaces all occurrences of the searchValue
(as if .split(searchValue).join(replaceValue)
or a global & properly-escaped regular expression had been used).searchValue
is a non-global regular expression, String.prototype.replace
replaces a single match, whereas String.prototype.replaceAll
throws an exception. This is done to avoid the inherent confusion between the lack of a global flag (which implies "do NOT replace all") and the name of the method being called (which strongly suggests "replace all").Notably, String.prototype.replaceAll
behaves just like String.prototype.replace
if searchValue
is a global regular expression.
replace
, accepting a CharSequence
and replacing all occurrences. Java also has replaceAll
which accepts a regex as the search term (requiring the user to escape special regex characters), again replacing all occurrences by default.replace
replaces all occurrences, but accepts an optional param to limit the number of replacements.str_replace
which has an optional limit parameter like python.gsub
, accepting a regexp or string, but also accepts a callback block and a hash of match -> replacement pairs.A simplified API for this common use-case that does not require RegExp knowledge. A way to global-replace strings without having to escape RegExp syntax characters. Possibly improved optimization potential on the VM side.
What about adding alimit
parameter to replace
instead?
A: This is an awkward interface — because the default limit is 1, the user would have to know how many occurrences already exist, or use something like Infinity.
What happens ifsearchValue
is the empty string?
String.prototype.replaceAll
follows the precedent set by String.prototype.replace
, and returns the input string with the replacement value spliced in between every UCS-2/UTF-16 code unit.
'x'.replace('', '_'); // → '_x' 'xxx'.replace(/(?:)/g, '_'); // → '_x_x_x_' 'xxx'.replaceAll('', '_'); // → '_x_x_x_'
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4