Как jQuery data() разбивает циклическую ссылку

Я прочитал почему это лучше и как это реализовано. Но чего я действительно не понимаю, так это как это нарушает циклическую ссылку?.

как он ломает опорный круг?

$(div1).data('item', div2);
$(div2).data('item', div1);

например, приведенные выше элементы div указывают друг на друга, как это предотвратить? У меня есть догадка, но я просто хочу убедиться, что моя догадка верна.


person Joseph    schedule 04.04.2012    source источник


Ответы (1)


Проблема циклической ссылки возникает в некоторых браузерах, когда вы помещаете ссылку на объект 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
comment
Не могли бы вы проиллюстрировать свое объяснение пункта 5 примером? - person techloris_109; 06.10.2016
comment
@techloris_109 — добавлен пример. - person jfriend00; 06.10.2016