А теперь давайте запустим в NodeJS такой код:
const arr = [];
for (let i = 0; i < 1200200; i++) {
arr.push('0123456789'.repeat(1000 * 1000));
}
while (true) {
}
После запуска смотриим программой top потребление ресурсов:
39858 dima 20 0 2026180 1,0g 37824 R 100,0 3,2 0:21.44 node
На моей Кубунте сожрано 1 Гб оперативки. Ух ты.
Теперь изменим немного код:
const arr = [];
const text = '0123456789'.repeat(1000 * 1000);
for (let i = 0; i < 1200200; i++) {
arr.push(text);
}
while (true) {
}
Смотрим ещё раз через top:
40267 dima 20 0 1066148 73796 37440 R 99,7 0,2 0:12.27 node
Программа потребила всего 73 Мб вместо 1 Гб. Согласно популярной теории о копировании примитивов такого быть не должно. ;)
В чем разница между двумя примерами кода? В первом случае мы всякий раз создаём новую строку, а а во втором - пихаем в массив ту же самую строку из созданной переменной. Если вы вдруг подумали, что во втором случае надо предварительно поместить значение в переменную-посредник, а потом уже пушить в массив, то нет - это не поможет, оперативка жраться всё равно не будет.
Кстати, на ноде в Windows 10 аналогичное поведение - около 1 Гб потребление против менее 100.
Ну, а теперь главный секрет! :)
В JavaScript всё передаётся/копируется по ссылке!