13.07.2008, 12:34
|
Интересующийся
|
|
Регистрация: 17.06.2008
Сообщений: 13
|
|
Сборщик мусора в JavaScript
Ребята, просветите пожалуйста! Если я создал некий элемент, добавил его в DOM, повесил на него слушателя события, а затем удалил этот элемент из DOM вообще, то что будет со слушателем события? Удаляется ли он вместе с элементом сборщиком мусора или продолжает висеть в памяти?
Последний раз редактировалось freebit, 13.07.2008 в 12:37.
|
|
16.07.2008, 02:09
|
|
Может вопрос сформулирован неверно?
Или ответ настолько очевиден, что каждый прочитавший, ухмыльнувшись встает и идет кормить рыбок
|
|
16.07.2008, 14:53
|
|
Матрос
|
|
Регистрация: 04.04.2008
Сообщений: 6,246
|
|
ИМХО, получить однозначный ответ на этот вопрос нелегко.
мне кажется все зависит от конкретного браузера, и реализации интепретатора в нем.
по хорошему делу, должен убиратся, если конечно не учтаивать замыкания, и прочие изыски, которые однозначно должны оставатся в памяти
|
|
19.07.2008, 21:17
|
Интересующийся
|
|
Регистрация: 17.06.2008
Сообщений: 13
|
|
И на этом спасибо!
И на этом спасибо!
|
|
21.07.2008, 15:12
|
|
Матрос
|
|
Регистрация: 04.04.2008
Сообщений: 6,246
|
|
и на том, пожалуйста)
|
|
21.11.2008, 18:23
|
Кандидат Javascript-наук
|
|
Регистрация: 21.11.2008
Сообщений: 114
|
|
Интересная тема, кстати. Надо бы ее развить.
Если верить этому, то в осле циклические связи между элементами и жскрипт-объектами (в т.ч. функциями) мемори-менеджерами (их там два) не резруливаются, по той причине, что за очистку элементов отвечает один, а за очистку жскриптовых объектов другой, договориться друг с другом они не умеют, и висят в памяти элементы со своими эвент-хэндлерами аж пока жив процесс осла. Во избежание этого во многих джаваскрипт-фрэймворках все аттачи эвент-хэндлеров (и другие связи с дом-объектами) кэшируются, чтобы на момент анлоада странички их очищать.
Теперь вопрос: почему эти связи некоторыми товарищами (напр. в Ext) кэшируются и чистятся даже для неослов?
Последний раз редактировалось vk65535, 21.11.2008 в 20:05.
|
|
27.11.2008, 00:21
|
Аспирант
|
|
Регистрация: 20.08.2008
Сообщений: 56
|
|
За Осла судить не берусь, а вот есть у меня один "скриптец" которой я активно юзаю в "3-й лисе".
Я несколько раз специально наблюдал: в процессе работы этого скрипта у меня в течение часа создавалось/убивалось несколько сот объектов с кучей подписок на различные события. При этом объем памяти используемый "лисой" практически не изменялся. Я не уверен насколько это объективно показывает работу "мусорщика"?
Есть какие-нибудь плагины/утилиты которые позволяют все это точно оценивать?
|
|
27.11.2008, 04:09
|
|
Матрос
|
|
Регистрация: 04.04.2008
Сообщений: 6,246
|
|
ну, если вас так интересует этот вопрос, то составьте сркипт, с созданием больших объектов(чтоб утечка памяти на глаз была заметна), слушателячми и прочим, и последующим удалением
выложите его тут, пускай в разных протестят, и оформят здесь результаты.
а мне влом писать скрипт, я пошел спать.
всем спокойной ночи
|
|
28.11.2008, 01:49
|
Аспирант
|
|
Регистрация: 20.08.2008
Сообщений: 56
|
|
Вот такой код для тестирования пойдет:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Test</title>
</head>
<body>
<form action="#" id="test"></form>
<script type="text/javascript">
<!--//--><![CDATA[//><!--
var p, d, f, a, ie, n, i;
p = 50; // Set period of modifying
d = document;
f = d.getElementById("test");
a = [];
ie = /msie/i.test(navigator.userAgent);
n = 0;
window.setInterval(doInput, p);
function doInput()
{
i = a.length;
if (!i || Math.random() < 0.5) {
a[i] = d.createElement("input");
a[i].setAttribute("value", n++);
if (ie) {
a[i].attachEvent('onclick', e1);
a[i].attachEvent('onmousedown', e2);
a[i].attachEvent('onmouseup', e3);
} else {
a[i].addEventListener("click", e1, false);
a[i].addEventListener("mousedown", e2, false);
a[i].addEventListener("mouseup", e3, false);
}
f.appendChild(a[i]);
} else {
f.removeChild(a.shift());
}
}
function e1()
{
//alert("Event 1");
}
function e2()
{
alert("Event 2");
}
function e3()
{
alert("Event 3");
}
//--><!]]>
</script>
</body></html>
Вот только хотелось бы понять методику для тестирования - что надо проверять окромя "съеденной" браузером памяти?
Или "измеренной памяти" достаточно для объективных выводов?
|
|
28.11.2008, 03:21
|
|
|
Регистрация: 10.07.2008
Сообщений: 3,873
|
|
И что этим кодом можно увидеть? Скачки в несколько килобайт используемой памяти, связаны с работой сборщика мусора. Не в одном браузере утечек памяти не наблюдается.
Вот во время написания фреймворка, я столкнулся с проблемой: при удалении узла через removeChild, в памяти остаются все дочерние узлы, на которые где-либо хранятся ссылки:
<!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>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title></title>
<script type="text/javascript">
window.onload = function() {
// Test 1
var div = document.getElementById('test1');
document.body.removeChild(document.getElementById('conteiner1'));
alert(div.id);
// Test 2
var div = document.getElementById('test2'), cont = document.getElementById('conteiner2');
while(cont.firstChild) cont.removeChild(cont.firstChild);
document.body.removeChild(cont);
alert(div.id);
// Test 3
document.body.removeChild(document.getElementById('conteiner3'));
alert(document.getElementById('test3'));
};
</script>
</head>
<body>
<div id="conteiner1">
<div id="test1">Test</div>
</div>
<div id="conteiner2">
<div id="test2">Test</div>
</div>
<div id="conteiner3">
<div id="test3">Test</div>
</div>
</body>
</html>
Это проблема стала еще более существенной из-за использования кэша по идентификаторам. Решить смог только удалением кэша после операций, связанных с удалением узлов и изменением идентификатора, хотя до сих пор остаются моменты, когда можно попасть в такую ситуацию.
Это конечно не баг, а особенность, но даже метод removeNode в IE, который принимает параметр булевского типа, для явного указания того, что дочерние узлы должны быть удалены, в случае наличия ссылки на элемент, не делает этого
Впрочем, так ведет себя любой объект — остается в памяти, пока есть хоть одна ссылка на него
var obj = {a: 'aa'}, c = obj;
obj = null;
alert(c.a);
Кстати, чтобы оставить в памяти удаляемый узел, нужно написать так
var removedNode = parent.removeChild(node);
Последний раз редактировалось Octane, 28.11.2008 в 03:50.
|
|
|
|