События JQuery автоматически освобождаются после уничтожения того, к чему они были привязаны? - PullRequest
3 голосов
/ 22 июня 2010

Если у меня есть следующий код в двух функциях объекта:

add: function()
{
    // create trip.
    var trip = new Trip();

    // add the trip using its id.
    this.trips[trip.id] = trip;
},

remove: function(tripId)
{
    // remove trip.
    delete this.trips[tripId];
}

ПРИМЕЧАНИЕ. Конструктор для объекта Trip связывает с собой несколько пользовательских обработчиков событий JQuery.

Будут ли обработчики событий, связанные с объектом Trip, автоматически уничтожаться / очищаться при удалении объекта Trip?

Произойдет ли то же самое для узла dom, если он будет удален и к нему будут привязаны обработчики событий?

Также я прочитал, что объекты не очищаются сборщиком мусора до тех пор, пока не исчезнут все ссылки на них, поэтому обработчики событий, связанные с самим объектом, считаются ссылками и предотвращают очистку объекта, даже когда Я больше не ссылаюсь на это?

Ответы [ 3 ]

5 голосов
/ 23 июня 2010

Событие не будет удалено, поскольку jQuery поддерживает центральный репозиторий всех связанных обработчиков событий и знает, удалили ли вы связанный объект с помощью delete или когда вы его удалили.Попробуйте этот маленький тест, чтобы подтвердить.(только для jQuery 1.4.2)

jsfiddle link :

// 1. a regular JS object
var root = {};
// Since we can't delete anything created with var (except on Chrome),
// we use an object property here. An array value works just as well,
// which is already the case in your example.
root.o = {};

// 2. at this point, jQuery creates an internal property
// jQuery<UNIQ_ID>, for example jQuery1277242840125 inside object o
$(root.o).bind("myEvent", function() { alert("here"); });

// 3. get the *internal* index jQuery assigned this object:
// there's only 1 property, so we just enumerate and fetch it.
var internalIndex;
for(var prop in root.o) {
    internalIndex = root.o[prop];
}

// 4. delete the object
delete root.o;

// 5. query jQuery internal cache with the internal index from step 3
console.log(jQuery.cache[internalIndex].events);
​

Шаг 5 должен регистрировать массив всех типов событий, которые были связаны с ex-o-объектом, включая «myEvent» и связанный с ним обработчик, поэтому никакие связанные обработчики событий не будут удаляться автоматически.Вот то, что я вижу, регистрируется (удаляются нерелевантные свойства):

▾ Object
  ▾ myEvent: Array (1)
    ▾ 0: Object
      ▸ handler: function () { alert("here"); }
        namespace: ""
        type: "myEvent"
      length: 1

Однако на удаление объекта это не влияет, и оно будет удалено, как и ожидалось.Тем не менее, это дыра в ситуации типа стены, так как где-то в кеше jQuery есть связанные данные, которые останутся там.

Кажется, что, хотя вы можете связывать события с простыми объектами JavaScript, вы не можете их связать,Похоже, что jQuery предполагает, что объект является узлом DOM при отмене привязки, и выдает следующую ошибку:

Uncaught TypeError: Object #<an Object> has no method 'removeEventListener'

Даже часть о способности связывать события с объектами, я считаю, недокументирована.Поэтому вы должны быть немного осторожны с этим, поскольку при попытке очистить ссылки на обработчики событий для этого объекта не будет работать следующее:

$(object).remove()
$(object).unbind(..)

В качестве обходного пути при очистке объекта Trip вы можете явно вызвать removeData, чтобы выполнить работу.

$(object).removeData();

Как я уже упоминал, он становится по коленоУглубившись во внутренности jQuery, вы можете захотеть взглянуть на альтернативное решение или опасаться, что обновления библиотеки могут легко сломать ваш код, что весьма вероятно.

0 голосов
/ 23 июня 2010

Произойдет ли то же самое для узла dom, если он был удален и к нему были привязаны обработчики событий?

this.handlerClick = function () { ... };

$(this.testDomNode).bind('click', this.handlerClick);

this.testDomNode.parentNode.removeChild(this.testDomNode);

Используя приведенный выше код и тестирование с FireQuery в FireFox, удалитеУзел dom не отменяет привязку обработчика к событию,

кажется, что перед удалением узла dom необходимо явно отменить привязку обработчика следующим образом:

$(this.testDomNode).unbind('click', this.handlerClick);

this.testDomNode.parentNode.removeChild(this.testDomNode);
0 голосов
/ 22 июня 2010

Насколько я знаю, вы можете привязывать только обработчики событий к узлам или, в особых случаях, к окну, документу и т. Д. Для узлов DOM обработчики событий будут удалены. Даже если бы они не были, они все равно не смогли бы сработать. Удаление объекта приведет к удалению связанных с ним обработчиков событий. Обработчики событий не должны препятствовать сборке мусора.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...