IE8-совместимая слабая карта для ссылок на узлы DOM - PullRequest
2 голосов
/ 01 декабря 2011

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

Это в основном ES6 WeakMap , но мне нужно работать с 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), но имеет утечки памяти.

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

1 Ответ

4 голосов
/ 01 декабря 2011

В статье, которую я недавно написал, 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.Конечно, вы рискуете получить осиротевшие предметы, но это меньшее из двух зол.

...