IE8, совместимая с слабой картой для ссылок на узлы DOM

StackOverflow https://stackoverflow.com/questions/8346738

Вопрос

Я хочу буквально Dictionary<Node, Object>

Это в основном ES6 слабая карта Но мне нужно работать с IE8.

Основная особенность, которую я хочу, - это

  • Минимизируйте утечки памяти
  • O (1) поиск на объекте, данном узле.

Моя реализация:

var uuid = 0,
    domShimString = "__domShim__";

var dataManager = {
    _stores: {},
    getStore: function _getStore(el) {
        var id = el[domShimString];
        if (id === undefined) {
            return this._createStore(el);
        }
        return this._stores[domShimString + id];
    },
    _createStore: function _createStore(el) {
        var store = {};
        this._stores[domShimString + uuid] = store;
        el[domShimString] = uuid;
        uuid++;
        return store;
    }
};

Моя реализация - O (1), но утечки памяти.

Как правильно реализовать это, чтобы минимизировать утечки памяти?

Это было полезно?

Решение

В статье, которую я недавно написал, ES 6 - быстрый взгляд на слабые карты, Я объяснил, как jQuery может сделать data() Утечка бесплатно. Это в основном генерирует название свойства Expando, jQuery.expando. Анкет Когда вы прикрепляете данные к элементу, данные подталкиваются к внутренней массиве кэша, и элементу предоставляется свойство Expando со значением индекса данных в кэше. Что -то похожее на это:

element[jQuery.expando] = elementId;

Способ предотвращения круговых ссылок состоит в том, чтобы не прикреплять объекты непосредственно к элементам в качестве экспозиций. Если ссылка на элемент остается в коде, то этот элемент не может быть собран мусором, даже если он удален из DOM. Тем не менее, предотвращение круговых ссылок не полностью подключает утечку - в массиве все еще остаются данные, если элемент удален из собранного DOM и мусора. Таким образом, jQuery очищает массив на разгрузке страницы, а также удаление данных из массива, если элементы удаляются из DOM, используя свои собственные методы, такие как remove(). Анкет Он поддерживает данные для detach().

Причина, по которой JQUERY делает это, заключается в том, что нет слабых эквивалентных карт, это своего рода мерцание в ES 5, но не в ES 3. Как объяснено в моей статье, WeakMap создан именно для такой ситуации, но единственная доступная реализация в Firefox 6 и выше, и, при этом спецификация не была завершена, даже это не следует использовать в производственных средах.

Еще одна вещь, которую нужно взять из моей статьи, это то, что некоторые элементы не позволят вам прикреплять свойства Expando - <object> а также <embed> два виновника названы и стыдно в исходном коде jQuery. Для этих элементов вы в значительной степени облажались, и JQuery просто не позволит вам использовать data на них.


Основные утечки памяти круговой ссылки происходят в справочных реализациях, когда свойства двух объектов имеют прямые ссылки друг на друга. Так DomObject содержит ссылку на Jsobject наоборот. Предполагая, что нет других ссылок ни на один объект, у них обоих будут постоянные ссылки 1, и GC не будет отмечать их для сбора.

Старые браузеры (IE6) не будут нарушать эти круговые ссылки, даже на разгрузке страницы, в то время как новые браузеры смогут нарушить многие из этих круговых ссылок, распознавая закономерности, которые их вызывают. jQuery.cache и аналогичные паттерны частично пустот утечки памяти, потому что DomObject никогда не содержит ссылки на Jsobject Итак, даже когда Jsobject содержит ссылку на DomObject, GC все еще может отметить Jsobject Для сбора, когда на него больше нет ссылок. Как только GC собрал Jsobject, Ссылка на DomObject будет уменьшен, освобождая это для коллекции.

Несмотря на то, что IE 8+ и другие ссылки -подсчеты могут иметь возможность разбить многие круговые эталонные шаблоны (около 400 были зафиксированы для IE 8), вероятность утечек только уменьшается. Например, я видел огромную утечку в одном из моих собственных приложений в IE 8, когда работая с элементами сценариев и JSONP. Лучшее решение - планировать худшее и без WeakMap(), Лучшее, что вы можете сделать, это использовать шаблон данных jQuery. Конечно, вы можете рисковать иметь осиротевшие объекты, но это меньшее из двух зол.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top