Думаю, для многих не секрет, что при назначении обработчика события, в `jQuery.cache` добавляется ссылка на этот элемент. И если вовремя не снять слушателя, это приведет к утечке памяти.
Чаще всего, такая проблема возникает, если работать с DOM напрямую, минуя методы jQuery, например, используя innerHTML.
<div id=”layout”>
<button>click me</button>
</div>
<script>
// Вешаем обработчик
$(‘button’).click(function (){
// Загружаем какой-то html
$.get(‘/layout’, function (content){
// Заменяем текущие содержание на новое
$(‘#layout’).prop(‘innerHTML’, content );
});
Чаще всего, такая проблема возникает, если работать с DOM напрямую, минуя методы jQuery, например, используя innerHTML.
<div id=”layout”>
<button>click me</button>
</div>
<script>
// Вешаем обработчик
$(‘button’).click(function (){
// Загружаем какой-то html
$.get(‘/layout’, function (content){
// Заменяем текущие содержание на новое
$(‘#layout’).prop(‘innerHTML’, content );
});
});
</script>В примере содержимое `#layout` заменяется и ссылка на элемент `button` «застревает» в `jQuery.cache`. Если перед заменой, вызвать `$(‘#layout’).empty()`, то утечки не будет.
Причина использования `innerHTML` в медленной работе jQuery методов. Случается, что при вызове $.fn.html/append (и подобных), браузер подвисает намертво.
Однако использование методов jQuery, для работы с DOM, не гарантирует, что утечки не будет.
Проблемы можно получить даже в достаточно просто коде:
$(new Image)
.attr(“src”, “http://domain.com/fail.png”)
.one(“load”, function (){ /*__*/ })
На первый взгляд, код безопасен, но происходит ошибка и событие `load` не отрабатывает — код “потек”.
В полной мере, проблему можно прочувствовать при разработке одностраничного приложения, где даже незначительная утечка, со временем приводит к краху браузера.
Чтобы избежать таких ситуаций, я разработал маленькую утилиту, которая следит за объектом `jQuery.cache` и элементами, находящимися в нем. Если элемент не находиться в DOM, то он считается “утёкшим”.
Утилита содержит всего четыре метода:
- $.leaks.get() — получить список “утёкших” элементов;
- $.leaks.watch() — начать слежение за утечками, если они возникают в console будет выведено количество “утёкших” элементов (“jQuery leaks: XX”);
- $.leaks.unwatch() — остановить слежение;
- $.leaks.remove() — удалить “утечки” (вызов `$.clearData($.leaks.get())`).
Надеюсь данная утилита будет вам полезна.
Исходник — jquery.leaks.js
Вот поэтому я и использую
ОтветитьУдалить$('#layout').on('click', 'button', ...);
который не течет
Дело не в этом, даже в этот код может потечь. + повсеместное использование делегатов, чревато тормозами, всему своё место.
Удалить