How do I efficiently make changes to a string in Javascript without creating a new string every time I make a change? The attached code illustrates this as each "result +=" operation will generate a new string.
The idea of using a Unit8Array as a work area appears to fail because converting to a string is just as inefficient.
; Use mask to change characters in string to a
; '-' if mask dictates that.
function maskOutput(input, mask) {
let result = '';
for (let i=0; i < input.length; i++){
if (mask.charAt(i) === 'X') {
result += '-';
} else {
result += input.charAt(i);
}
}
return result;
}
The first thing I'd do is check whether the temporary strings were actually causing a problem for my page/app, because JavaScript engines are extremely good at optimizing common issues like lots of temporary strings, especially in cases like your maskOutput where the string is the result of string concatenation. (V8, the engine in Chrome and elsewhere, does it when necessary by combining partial strings into a linked list.) It seems unlikely that the string concatenation in your maskOutput function is a bottleneck for your page/app. It used to be fairly standard practice that you'd see code building up a large string by using an array and then .join("") at the end, because it was faster circa 2009, but JavaScript engines have moved on a lot since then and I remember it became faster to just use += on a string several years ago.
If there were some use case (memory pressure, whatever) where the temporary strings were a problem, you could use a plain array¹ of individual characters, converting once (from string to array) at the outset if needed (not in your case) and at the end (from array to string). But for a short string like the ones I imagine maskOutput handles, as you say, the overhead wouldn't be worth it.
But just for completeness:
function maskOutput(input, mask) {
const len = input.length;
let result = Array(len); // Some engines actually do optimize this
for (let i = 0; i < len; i++) {
if (mask[i] === 'X') { // No need for a method call
result[i] = "-";
} else {
result[i] = input[i];
}
}
return result.join("");
}
¹ Uint8Array would be a poor choice, because:
Uint16Array would be more appropriate.Uint8Array/Uint16Array requires converting it from JavaScript's number type to an 8-bit/16-bit unsigned integer (and the converse on reading), which is really cheap but isn't free. And presumably you'd have to use charCodeAt to get the value to store.