Portrait Dr. Axel Rauschmayer
Dr. Axel Rauschmayer
Homepage | Twitter
Cover of book “JavaScript for impatient programmers”
Book, exercises, quizzes
(free to read online)
Cover of book “Deep JavaScript”
Book (50% free online)
Logo of newsletter “ES.next news”
Newsletter (free)

ECMAScript proposal: String.prototype.replaceAll

[2019-12-21] dev, javascript, es proposal
(Ad, please don’t block)

The normal string method .replace() only lets you replace one occurrence if you search for string (and not a regular expression with the flag /g). The proposal “String.prototype.replaceAll (by Peter Marshall, Jakob Gruber, Mathias Bynens) fixes that.

.replace(): the status quo  

Let’s look at three options for replacing that we currently have.

First, we can search for a string and replace the first occurrence:

> 'Cyan + magenta + yellow + black'.replace('+', 'and')
'Cyan and magenta + yellow + black'

Second, we can search for a regular expression with the flag /g and replace all occurrences:

> 'Cyan + magenta + yellow + black'.replace(/\+/g, 'and')
'Cyan and magenta and yellow and black'

Third, we can convert a string into a regular expression with flag /g and replace all occurrences:

function escapeForRegExp(str) {
  return str.replace(/[\\^$.*+?()[\]{}|]/g, '\\$&'); // (A)
}
const regExp = new RegExp(escapeForRegExp('+'), 'g');
assert.equal(
  'Cyan + magenta + yellow + black'.replace(regExp, 'and'),
  'Cyan and magenta and yellow and black'
);

“JavaScript for impatient programmers” has a few more details on escapeForRegExp().

.replaceAll(): replacing strings multiple times  

The proposed string method .replaceAll() provides one service that .replace() can’t: Searching for a string and replacing all occurrences:

> 'Cyan + magenta + yellow + black'.replaceAll('+', 'and')
'Cyan and magenta and yellow and black'

.replaceAll() throws an exception if we use a regular expression that does not have the flag /g. The assumption is that we made a mistake and should switch to .replace() if we really only want to replace the first occurrence. The following code demonstrates that:

assert.throws(
  () => 'abcdef'.replaceAll(/abc/, 'x'),
  TypeError
);

Other than that, .replaceAll() works like .replace(). This table summarizes the differences between .replace() and .replaceAll():

Search: for string for RegExp w/o \g for RegExp with /g
.replace First occurrence First occurrence All occurrences
.replaceAll All occurrences TypeError All occurrences

Implementations  

Further reading