Какова цель $.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;
}
}
}