Проблема циклической ссылки возникает в некоторых браузерах, когда вы помещаете ссылку на объект DOM в объект DOM в качестве свойства этого объекта DOM. Затем у вас есть два объекта DOM, указывающих друг на друга. Удаление объекта DOM с настраиваемым свойством не очищает это настраиваемое свойство. Сборщик мусора, который не настолько умен, не понимает, что эта ссылка DOM не считается, поэтому он застревает, и есть несколько способов, которыми это может привести к утечкам.
.data()
решает эту проблему, потому что .data()
данные НЕ находятся в объекте DOM. Это просто структура данных javascript, которую можно связать с объектом DOM с помощью уникального идентификатора строки.
Одна запутанная часть этого заключается в том, что когда вы читаете с .data("key")
, а key
не найдено в структуре данных .data()
javascript, тогда и только тогда jQuery будет искать атрибут в объекте DOM с именем "data-key"
. Но всякий раз, когда вы пишете с помощью .data("key", "myData")
, он никогда не записывает в объект DOM, а только в структуру данных javascript.
Таким образом, поскольку .data()
никогда не записывает данные в объект DOM, не может быть ни одного из этих типов циклических ссылок, с которыми у некоторых браузеров возникают проблемы.
Есть еще несколько полезных вещей, которые нужно знать о структуре данных .data()
. Когда вы используете .remove()
jQuery для удаления элементов из DOM или когда вы вызываете $(elem).html("new html")
, jQuery очищает данные .data()
для любых удаленных элементов. Это тот случай, когда хорошо не смешивать jQuery с простым javascript. Если вы используете .data()
, вы всегда должны удалять элементы из DOM с помощью функций jQuery, чтобы .data()
очищался соответствующим образом. В противном случае вы можете получить утечку памяти таким образом (могут утечь как данные .data()
, так и любые удаленные объекты DOM, на которые есть ссылки в .data()
. Но если вы используете только методы jQuery для удаления элементов из DOM (включая замену innerHTML ), тогда jQuery все исправит и утечек не будет.
Так, например, это создаст утечку памяти:
// suppose elem is a DOM element reference
// store some data in jQuery's data storage on behalf of a DOM element
$(elem).data("someKey", "someValue");
// remove DOM element with plain Javascript
elem.parentNode.removeChild(elem);
Поскольку вы удалили элемент DOM с помощью простого Javascript, у jQuery не было возможности очистить ранее сохраненные данные. Сам элемент DOM будет удален сборщиком мусора, но значение .data()
, которое вы ранее сохранили, теперь потеряно в хранилище jQuery и, по сути, является «утечкой», поскольку оно, вероятно, никогда не будет очищено. С другой стороны, если вы сделаете это:
$(elem).data("someKey", "someValue");
$(elem).remove();
Затем jQuery увидит, что вы удаляете элемент DOM, а также очистит данные, которые вы сохранили с помощью .data()
.
Достаточно простой способ увидеть, как это работает, — создать скрипт из пары строк с неминимизированной версией jQuery, а затем просто выполнить вызов $(elem).data("key", "whatever")
в отладчике и посмотреть, как это работает.
person
jfriend00
schedule
04.04.2012