<html>
<body>
<script>
function createString() {
return "0".repeat(25 * 1024 * 1024).substring(0, 12);
}
var arr = [];
setInterval(function() {
let str = createString();
arr.push(str);
}, 500);
</script>
</body>
</html>
run it in your browser and open the task manager you could notice that the browser takes some limited amount of memory ~200Mb. But what if we update one single digit in our code
return "0".repeat(25 * 1024 * 1024).substring(0, 13);i.e. replace 12 with 13, run it into a browser and have a look at the process memory. It grows unstoppable and makes the browser crash in a half a minute! Why does it happen?
Every time we call String.prototype.substring function it returns new string instance that keeps .. a link to the original string! That's how V8 organizes memory for strings for permamance reason. Exception is when a new instance string length is less than 13 - in that case no link to original string preserved. So in our example arr contains no just short strings(13), but actually the huge ones (25 * 1024 * 1024). How to avoid it? Unfortunatelly, there is no documemnted method to 'cut' parents from strings, that's because we can do the following (update line 11):
<html>
<body>
<script>
function createString() {
return "0".repeat(25 * 1024 * 1024).substring(0, 12);
}
var arr = [];
setInterval(function() {
let str = createString().split('').join('');
arr.push(str);
}, 500);
</script>
</body>
</html>
That manoeuvre breaks the link with the original string and prevents memory leak.