Во-первых, я много читал и исследовал эту проблему. Уже есть билет с jquery UI , за которым я следую. И я знаю способ обойти эту ошибку, но мне очень любопытно, почему это происходит. Я полагаю, что ошибка связана с закрытием, но мой javascript-fu не эксперт.
Я полагаю, что у команды jquery UI есть дела поважнее, чем тратить энергию на ошибку IE6. Поэтому я хотел донести это до широкой публики javascript.
Ниже приведен тестовый пример:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>jquery ui memory leak test</title>
<script type="text/javascript" src="jquery-1.5.js"></script>
<script type="text/javascript" src="jquery.ui.widget.js"></script>
<script type="text/javascript">
(function($) {
$.widget("ui.test", {
_create: function() {
}
});
$(document).ready(function() {
for (var i = 0; i < 1; i++) {
$("#container").append("<div id='inner'></div>");
$("#inner").test();
$("#inner").test("destroy");
$("#container").empty();
};
});
})(jQuery);
</script>
</head>
<body>
<div id="container">
</div>
</body>
</html>
Я тестировал, используя все комбинации jquery 1.4.4 и 1.5 и jquery-ui-1.8.9 и jquery-ui master (на момент написания статьи), но все они дают одинаковый результат.
Мой тестовый виджет, я считаю, самый простой, который вы можете получить.
Если вы тестируете, используя sIEve , вы можете обнаружить утечку. В противном случае увеличьте счетчик до 1000, и вы увидите, что объем памяти увеличится довольно легко. Существует еще один инструмент от Microsoft, который вы также можете использовать для обнаружения утечек.
Таким образом, утечка связана с пользовательской привязкой события в методе _createWidget
виджета:
var self = this;
this.element.bind( "remove." + this.widgetName, function() {
self.destroy();
});
Так что, если я это прокомментирую, утечки нет. Я использую 1.8.9, а не master, так как код виджета 1.8.9 кажется проще (master немного изменился).
Теперь, если я связываю одно и то же событие за пределами виджета, утечки тоже нет. Например, я бы вставил следующий код после создания виджета, но перед уничтожением:
$("#inner").bind("remove.test", function() {});
Я специально добавил функцию no-op, но не имеет значения, что находится внутри функции обратного вызова. Вы можете поспорить, так как впоследствии я делаю уничтожение вручную, привязка не нужна. Но дело не в этом.
Итак, мой вопрос: почему происходит утечка исходного кода, вызова привязки из кода виджета? Я подозреваю, что это из-за закрытия, но я не могу это объяснить.
Может кто-нибудь объяснить это?