0

While going through string.replace() in Eloquent JavaSript 3rd Ed, p.154:

console.log("hello".replace(/l/, "X"));
console.log("hello".replace(/l/g, "X"));

This looks reasonable. But the book also stated:

It would have been sensible if the choice between replacing one match or all matches was made through an additional argument to replace or by providing a different method, replaceAll. But for some unfortunate reason, the choice relies on a property of the regular expression instead.

Why would relying on the g flag not a good choice? I also found that Ruby really does use a different method gsub vs sub, and Python uses re.sub without count to mean all and a count of 1 to mean once.

What is/are the reason(s) using a replaceAll() is better than using the g flag?

nonopolarity
  • 146,324
  • 131
  • 460
  • 740
  • 4
    This is really a question of personal preference. Or put differently: a matter of opinion. And as such per definition off-topic on this site. – Joachim Sauer Jan 29 '20 at 12:44
  • 1
    Neither one has any objective advantage, so it's all just a matter of design preference. – ruohola Jan 29 '20 at 12:44
  • 1
    I imagine one reason to be of that opinion is that it binds _how many times you're matching something_ to _what you're trying to match_. For instance, I may have some pattern which I want to identify once, and I define that pattern. But later on I need to match _all_ instances of this pattern instead. I can't use the same pattern (or at least, I don't think I can?). I'm not saying this is correct but it's perhaps one option. – OliverRadini Jan 29 '20 at 12:46
  • The reasoning is probably that this for example means you can not global replace with a simple string. – Lux Jan 29 '20 at 12:47
  • 2
    `replace` also works with a string as the first parameter, having a `replaceAll` will be an improvement if you only want to use strings. – Titus Jan 29 '20 at 12:47
  • It really seem to have a valid and concrete reason why that is... I don't know what it is and maybe somebody who happen to land on this page in the future can tell why – nonopolarity Jan 29 '20 at 13:06
  • Having a replaceAll, that doesn't use a regex, would be most usefull when the search string comes from user input. Since one doesn't know if the user adds characters that have meaning in the regex syntax. `.*+()[]{}\-` – LukStorms Jan 29 '20 at 13:31
  • ok, this really is not opinion related... i later found out. the simple one line explanation: to replace all occurrences of a simple string with another simple string, now you can't. You now have to somehow escape that simple string into a regex in order to use the `g` flag – nonopolarity Jan 29 '20 at 14:39
  • So write your own method to do it. It is like 3 lines' – epascarello Jan 29 '20 at 14:39
  • And there is/was a proposal.... https://github.com/tc39/proposal-string-replaceall and there are polyfills – epascarello Jan 29 '20 at 14:41

1 Answers1

1

To replace all occurrences of a substring, you must use a regex with the g flag. This makes it very hard if the substring you want to replace is coming from user input or other variable values. While you can trivially construct a regex from user input using new Regexp(input, 'g'), the input here must be a valid regex and special symbols within it will be interpreted by the regex engine. E.g.:

new RegExp('[abc', 'g')  // poof

So, it would have been nice to have a str.replaceAll(input, 'X') for this purpose. Instead you need weird workarounds.

deceze
  • 510,633
  • 85
  • 743
  • 889
  • so that means "being able to replace all" even when the first argument is not a regular expression? To use the `g` flag that means now the first argument has to be a regular expression – nonopolarity Jan 29 '20 at 14:15
  • Yes, I thought I said as much. – deceze Jan 29 '20 at 14:16
  • ok I thought at first why user input has anything to do with it... turns out it is because if the intention is to replace all simple strings with another one, but now to replace all, that simple string will be interpreted as regex... got it – nonopolarity Jan 29 '20 at 14:30