Какова цель $.cache в jQuery?

Я вижу, что обработчики событий, зарегистрированные через .on(), хранятся в $.cache. Я также вижу, что обработчики событий также хранятся в $(elem).data().

Объекты, находящиеся в $.cache, относятся к узлам DOM, на которых регистрируются события. Это приводит к утечке памяти при отсоединении узлов DOM, что делает обязательными .off().

У меня есть ситуация, когда я не знаю, когда DOM node (к которому я привязал обработчик события) отделяется. Хотя я могу хранить ссылку на этот DOM node в своем коде и вызывать .off() для очистки, это не кажется приятным, потому что не просто знать, когда DOM node удаляется.

Каков наилучший способ сделать это?

Ответы

Ответ 1

"Каков наилучший способ сделать это?"

Если вы собираетесь использовать jQuery, вы должны использовать его API для удаления элементов, и вы должны использовать соответствующие методы, иначе, как вы сказали, у вас будут утечки памяти.

Если вы не знаете, когда DOM node удаляется, и если это вызывает утечку, я предполагаю, что это означает, что вы используете другую библиотеку вместе с jQuery. Это просто не очень хорошая идея именно по этой причине.

Вы должны убедиться, что все элементы, затронутые jQuery, удалены jQuery. Также есть некоторые данные, хранящиеся в $.cache, которые вы явно не задали. Это означает, что все элементы должны быть удалены с помощью jQuery, а не только те, которые, по вашему мнению, могут иметь данные.


"Какова цель $.cache в jQuery?"

Связать обработчики и другие данные с элементами. Связь между данными и элементами в основном представляет собой серийный номер, хранящийся в свойстве expando на элементе.

Если вы удалите элемент без jQuery, связанные данные в $.cache потеряются.

Целью этого подхода было предотвращение потенциальных утечек. К сожалению, это потенциально создает более серьезные утечки.

Ответ 2

Я столкнулся с аналогичной ситуацией, когда Knockout используется для добавления и удаления dom-деревьев из документа. Однако jquery используется для подключения прослушивателей событий к этим деревьям. Когда нокаут удаляет элементы dom из документа, слушатели не отключаются, поэтому дерево доминирования никогда не имеет права на сбор мусора. Мы добавили функцию очистки, которая тратит через jquery $.cache каждый раз при изменении хеша и находит даже обработчиков, которые привязаны к деревьям, которые не находятся в документе. Затем он отталкивает слушателей, тем самым делая дерево домиков подходящим для сбора мусора и фиксируя большую часть утечек, которые мы наблюдаем, то есть круглые поездки вокруг приложения, используемого для утечки 13 МБ, теперь он протекает только с 3 МБ с этими изменениями на месте.

for (var i in $.cache) {
            if ($.cache.hasOwnProperty(i)) {

                if ($.cache[i].handle && $.cache[i].handle.elem && document !== $.cache[i].handle.elem && !jQuery.contains(document, $.cache[i].handle.elem)) {
                    //we have an event handler pointing to a detached dom element!
                    //this is a memory leak as this detached dom element cannot be garbage collected until
                    //all references to it are removed. So lets delete the event handler to get memory back!
                    var orphan = $($.cache[i].handle.elem);
                    $('body').append(orphan);
                    orphan.off();
                    orphan.remove();
                    orphan = null;
                }
            }
        }