Lifecycle сцены15 / 19

Утечка: объект всё ещё нужен по графу

Завершение работы сцены не делает её listener недостижимым автоматически.

Игрок закрыл сцену, но глобальный event target всё ещё хранит callback, который использует её данные. Для разработчика сцена «закончилась». Для сборщика она остаётся достижимой.

function mount(scene) {
  const onResize = () => scene.resize();
  window.addEventListener('resize', onResize);
  return () => window.removeEventListener('resize', onResize);
}

mount(scene) возвращает функцию очистки. Когда сцена больше не нужна, эту функцию нужно вызвать: она удалит обработчик onResize из window. В removeEventListener нужно передать тот же обработчик, который был добавлен.

Для поиска утечки в приложении можно сравнить снимки памяти после нескольких открытий и закрытий сцены и проверить, что продолжает её удерживать.

Очистка подписки

Вызовем функцию очистки и посмотрим, что изменится.

windowСписок обработчиковresize: onResize
→
onResizeОбработчик события() => scene.resize()
sceneДоступна через обработчик
Подписка удерживает сцену

window хранит обработчик onResize. Обработчик обращается к scene, поэтому сцена остаётся доступной через подписку.

Интерактивная схема показывает удаление подписки. Функция очистки и другие ссылки на сцену также должны быть освобождены; момент сборки выбирает движок.

Основной вывод

dispose должен разрывать долгоживущие связи, принадлежащие сцене.

Проверить по первоисточнику ↗

Chrome DevTools · Memory↗Официальные инструменты диагностики памяти, утечек и частых сборок.DOM Standard · removeEventListener↗Нормативный контракт удаления listener: type, callback и capture должны совпасть.