Почему garbage collector не очищает переменную в случае замыкания в JavaScript
Что проверяют
Понимаете ли вы, что сборщик работает по достижимости, и что удержание переменной замыканием это не баг, а прямое следствие определения. Заодно смотрят, отличаете ли вы «замыкание держит объект» от «в приложении утечка»: это далеко не одно и то же.
Как отвечать
Движок не считает ссылки, он обходит граф от корней: глобальный объект, стек вызовов, активные задачи. Всё, до чего дошли, живёт. Функция хранит внутреннюю ссылку на своё лексическое окружение, поэтому пока достижима функция, достижимы и захваченные ею переменные. Вопрос «почему не очистил» на самом деле звучит так: «кто ещё держит эту функцию».
Деталь, которая отличает подготовленного кандидата: удерживается не всё окружение подряд. На этапе компиляции движок определяет, какие переменные реально используются вложенными функциями, и только они попадают в контекст. Но у функций, созданных в одной и той же внешней, контекст общий, поэтому лёгкий колбэк может удерживать тяжёлый объект, захваченный его соседкой.
Освобождение всегда сводится к обрыву последней ссылки: снять обработчик, остановить интервал, отписаться, обнулить ссылку на функцию, не класть замыкание в долгоживущий кэш. Для кэшей с объектами в роли ключей подойдёт WeakMap.
const onScroll = () => use(bigData);
window.addEventListener("scroll", onScroll);
window.removeEventListener("scroll", onScroll); // иначе bigData живёт, пока жива страницаГде спотыкаются
Рассказывают про счётчик ссылок и «циклические ссылки текут». Современные движки помечают достижимость от корней, поэтому взаимная ссылка двух недостижимых объектов собирается спокойно.
Ищут держателя не там. Обнуляют переменную внутри, а память не падает, потому что настоящие держатели это слушатель на документе, таймер, подписка и узел, вынутый из документа, но захваченный колбэком.
Приравнивают удержание к утечке. Утечка это когда объект больше не нужен, а память растёт от снимка к снимку. Доказывается она сравнением снимков кучи, а не рассуждением о том, что замыкание что-то там держит.