Why 'ABC'.replace('B', '$`') gives AAC

Why this code prints AAC instead of expected A$`C?

console.log('ABC'.replace('B', '$`'));

==>

AAC

And how to make it give the expected result?


Solution 1:

To insert a literal $ you have to pass $$, because $`:

Inserts the portion of the string that precedes the matched substring.

console.log('ABC'.replace('B', "$$`"));

See the documentation.

Other patterns:

Pattern Inserts
$$ Inserts a $.
$& Inserts the matched substring.
$` Inserts the portion of the string that precedes the matched substring.
$' Inserts the portion of the string that follows the matched substring.
$n Where n is a positive integer less than 100, inserts the _n_th parenthesized submatch string, provided the first argument was a RegExp object. Note that this is 1-indexed. If a group n is not present (e.g., if group is 3), it will be replaced as a literal (e.g., $3).
$<Name> Where Name is a capturing group name. If the group is not in the match, or not in the regular expression, or if a string was passed as the first argument to replace instead of a regular expression, this resolves to a literal (e.g., $<Name>). Only available in browser versions supporting named capturing groups.

JSFiddle

Also, there are even more things on the reference link I’ve posted above. If you still have any issue or doubt you probably can find an answer there, the screenshot above was taken from the link posted at the beginning of the answer.

It is worth saying, in my opinion, that any pattern that doesn’t match the above doesn’t need to be escaped, hence $ doesn’t need to be escaped, same story happens with $AAA.

In the comments above a user asked about why you need to “escape” $ with another $: despite I’m not truly sure about that, I think it is also worth to point out, from what we said above, that any invalid pattern won’t be interpreted, hence I think (and suspect, at this point) that $$ is a very special case, because it covers the cases where you need to replace the match with a dollar sign followed by a “pattern-locked” character, like the tick (`) as an example (or really the & as another).

In any other case, though, the dollar sign doesn’t need to be escaped, hence it probably makes sense that they decided to create such a specific rule, else you would’ve needed to escape the $ everywhere else (and I think this could’ve had an impact on any string object, because that would mean that even in var a = "hello, $ hey this one is a dollar";, you would’ve needed to escape the $).

If you’re still interested and want to read more, please also check regular-expressions.info and this JSFiddle with more cases.

Solution 2:

In the replacement the $ dollar sign has a special meaning and is used when data from the match should be used in the replacement.

MDN: String.prototype.replace(): Specifying a string as a parameter

$$ Inserts a "$".
$` Inserts the portion of the string that precedes the matched substring.

As long as the $ does not result in a combination that has a special meaning, then it will be just handled as a regular char. But you should still always write it as a $$ in the replacement because otherwise, it might fail in future if a new $x combination is added.