Подтвердить что ты не робот

Закрытие утечки памяти неиспользуемых переменных

Я хотел бы понять, при каких обстоятельствах переменные, которые больше не используются, сохраняются в закрытии и приводят к утечкам памяти. Моим самым предпочтительным результатом было бы "нет", но это, похоже, не так.

Из того, что я понимаю, как только функция объявлена ​​внутри другой функции, ее внутренней [[scope]] присваивается LexicalEnvironment своей инкапсулирующей функции. Эта LexicalEnvironment имеет ссылочные локальные переменные и всю цепочку цепей в этой точке. Это в основном включает в себя все свободные переменные, к которым может обращаться функция (из того, что я понял из lostechies, объяснения javascript).

Здесь возникает первый вопрос: это должно означать all, что эти переменные могут быть достигнуты до тех пор, пока функция будет работать. Например. следующее должно уже протекать:

function a() {
    let big = new Array(1000000).join('*'); //never accessed
    //function unused() { big; }
    return () => void 0;
}
 
let fstore = [];
function doesThisLeak() {
  for(let i = 0; i < 100; i++) fstore.push(a());
}

doesThisLeak();
4b9b3361

Ответ 1

Компилятор может проверить код возвращаемой функции, чтобы увидеть, какие свободные переменные он ссылается, и только эти переменные должны быть сохранены в закрытии, а не всей LexicalEnvironment. Вы можете это увидеть, изучив закрытие в отладчике Javascript.

function a() {
  let big = new Array(1000000).join('*');
  let small = "abc"; // is accessed
  return (x) => small + x;
}

fun = a();
console.dir(fun);

function b() {
    let big = "pretend this is a really long string";
    function unused() { big; }
    return () => void 0;
}

fun = b();
console.dir(fun);

Ответ 2

После вызова a() ваш fstore имеет ссылку только на созданную функцию () => void. После того, как a() вернется, его рамки будут удалены. Это означает, что никакие вары не имеют ссылки на ваш new Array(1000000).join('*'), и это будет сбор мусора. Он будет собран таким же образом, если вы раскомментируете функцию unused, потому что она тоже будет удалена. В вашем коде нет утечек.