Javascript: «свисающие» ссылки на элемент DOM? - PullRequest
2 голосов
/ 01 мая 2010

Кажется, что в Javascript, если у вас есть ссылка на некоторый элемент DOM, а затем измените DOM, добавив дополнительные элементы в document.body, ваша ссылка на DOM станет недействительной.

Рассмотрим следующий код:

<html>
<head>
<script type = "text/javascript">
function work()
{
 var foo = document.getElementById("foo");
 alert(foo == document.getElementById("foo"));

 document.body.innerHTML += "<div>blah blah</div>";
 alert(foo == document.getElementById("foo"));
}

</script>
</head>

<body>
<div id = "foo" onclick='work()'>Foo</div>
</body>
</html>

Когда вы нажимаете на DIV, появляется предупреждение «true», а затем «false». Другими словами, после изменения document.body ссылка на элемент DIV больше не действительна. Это поведение одинаково в Firefox и MSIE.

Некоторые вопросы:

Почему это происходит? Это поведение определяется стандартом ECMAScript или это проблема, специфичная для браузера?

Примечание: есть другой вопрос , опубликованный в stackoverflow, который, похоже, относится к той же проблеме, но ни вопрос, ни ответы не очень ясны.

Ответы [ 2 ]

5 голосов
/ 01 мая 2010

Когда вы добавляете к document.body.innerHTML, это эквивалентно

document.body.innerHTML = document.body.innerHTML + "<div>blah blah</div>";

Когда вы назначаете innerHTML таким образом, браузер должен выполнить повторный анализ и, следовательно, воссоздать эту часть DOM. Элемент div в foo по-прежнему действует , но больше не является частью документа. Затем, конечно, когда вы звоните document.getElementById, он получает новый div, который заменил foo.

Поведение DOM специфично, поэтому оно не определено в стандарте ECMAScript. Он не определен ни в одном текущем стандарте W3C, поскольку innerHTML изначально был нестандартным свойством, но в конечном итоге он стандартизирован в HTML5.

Решение состоит в том, чтобы либо позвонить document.getElementById, чтобы вернуть ссылку, либо использовать document.createElement, <element>.appendChild и т. Д. Вместо установки innerHTML.

1 голос
/ 01 мая 2010

Ссылка снова не будет действительной до тех пор, пока функция не завершится и DOM не обновится, а весь innerHTML фактически не преобразуется. Попробуйте вызвать функцию еще раз с помощью setInterval, и вы увидите, что первое предупреждение снова становится истинным.

Edit: я только что заметил, что в вашей HTML-строке нет id = "foo". Вставьте это и попробуйте снова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...