Точное объяснение проблемы циклической ссылки JavaScript <-> DOM

Одно из разрекламированных преимуществ jQuery.dataпо сравнению с необработанными свойствами расширения (произвольные атрибуты, которые вы можете назначать узлам DOM) это jQuery.data«защищен от циклических ссылок и, следовательно, не имеет утечек памяти». В статье Google под названием «Оптимизация кода JavaScript»приводится более подробная информация:

Наиболее распространенные утечки памяти для веб-приложений связаны с циклическим ссылки между механизмом сценариев JavaScript и C++ браузеров. объекты, реализующие DOM (например, между сценарием JavaScript движок и COM-инфраструктура Internet Explorer, или между Движок JavaScript и инфраструктура Firefox XPCOM).

В нем перечислены два примера шаблонов циклических ссылок:

  • Элемент DOM → обработчик событий → область замыкания → DOM

  • Элемент DOM → via Expando → промежуточный объект → элемент DOM

Однако, если цикл ссылок между Узел DOM и объект JavaScript вызывают утечку памяти, не означает ли это, что любой нетривиальный обработчик событий (например, onclick) приведет к такой утечке? Я не понимаю, как обработчик событий вообще может избежать цикла ссылок, потому что я это вижу следующим образом:

  • Элемент DOM ссылается на обработчик событий.

  • Обработчик событий ссылается на DOM (прямо или косвенно). В любом случае почти невозможно избежать ссылки windowв любом интересном обработчике событий, за исключением написания цикла setInterval, который считывает действия из глобальной очереди.

Может ли кто-нибудь дать точное объяснение проблемы циклической ссылки JavaScript ↔ DOM? Вещи, которые я хотел бы уточнить:

  • Какие браузеры действуют? В комментарии к источнику jQuery конкретно упоминается IE6-7, но в статье Google предполагается, что Firefox также затронут.

  • Отличаются ли свойства Expando и обработчики событий в отношении утечек памяти? Или оба этих фрагмента кода подвержены утечке памяти одного и того же типа?

    // Создаем расширение, которое ссылается на собственный элемент.
    var elem = document.getElementById('foo');
    элемент.моя = элемент;
    
    // Создаем обработчик событий, который ссылается на свой собственный элемент.
    var elem = document.getElementById('foo');
    элемент.onclick = функция () {
    elem.style.display = 'нет';
    };
    
  • Если на странице происходит утечка памяти из-за циклической ссылки, сохраняется ли утечка до тех пор, пока не будет закрыто все приложение браузера, или память освобождается при закрытии окна/вкладки?

10
задан Joey Adams 10 April 2012 в 16:25
поделиться