Unfortunately since Javascript's string replace()
function doesn't let you start from a particular index, and there is no way to do in-place modifications to strings it is really hard to do this as efficiently as you could in saner languages.
.split().join()
isn't a good solution because it involves the creation of a load of strings (although I suspect V8 does some dark magic to optimise this).
- Calling
replace()
in a loop is a terrible solution because replace starts its search from the beginning of the string every time. This is going to lead to O(N^2) behaviour! It also has issues with infinite loops as noted in the answers here.
- A regex is probably the best solution if your replacement string is a compile time constant, but if it isn't then you can't really use it. You should absolutely not try and convert an arbitrary string into a regex by escaping things.
One reasonable approach is to build up a new string with the appropriate replacements:
function replaceAll(input: string, from: string, to: string): string {
const fromLen = from.length;
let output = "";
let pos = 0;
for (;;) {
let matchPos = input.indexOf(from, pos);
if (matchPos === -1) {
output += input.slice(pos);
break;
}
output += input.slice(pos, matchPos);
output += to;
pos = matchPos + fromLen;
}
return output;
}
I benchmarked this against all the other solutions (except calling replace()
in a loop which is going to be terrible) and it came out slightly faster than a regex, and about twice as fast as split
/join
.
Edit: This is almost the same method as Stefan Steiger's answer which I totally missed for some reason. However his answer still uses .join()
for some reason which makes it 4 times slower than mine.