设置innerHTML属性会中断对子元素的引用

时间:2013-01-15 01:55:04

标签: javascript dom web-applications reference cross-browser

据我所知,问题类似于here所描述的问题。但是,我没有使用mootools,我的问题和结果是不同的。 这是一个用于演示此问题的测试页:http://jsfiddle.net/S7rtU/2/

我使用createElementappendChild向容器添加元素。当我添加每个时,我还在私有数组(elems)中存储对它的引用。

然后,我决定清空容器,并设置container.innerHTML = ''

(在我的示例中,我首先将其设置为待处理消息,然后3秒后使用setTimeout,我清除它。这是为了给时间观察DOM的更改。)

然后,我尝试从elems数组重新填充容器,为每个存储的元素调用container.appendChild

我已经测试了我手边的浏览器:Firefox 17.0.1,Chrome 23.0.1271.97,Safari 3.1.2,IE 6和IE 7.除了IE 6和IE之外的所有浏览器。 7 实际上将恢复这些元素。因此它们成功存储在内存中,并且引用未被破坏。此外,注册到这些元素的事件处理程序仍然有效。

在IE中,元素不再出现。

我读到的关于这个问题的内容,包括其他SO问题,似乎表明当您修改容器上的innerHTML时,引用应该被破坏。事件处理程序也应该被打破。然而,我测试的3个现代浏览器不会破坏引用,也不会破坏事件处理程序。

当然,为了在IE中完成这项工作,我可以使用类似的东西,但如果有很多元素,这是一个重要的额外处理:

function explicitClearContainer() {
    var e;
    // Explicitly remove all elements
    for (var i = 0; i < elems.length; ++i) {
        e = elems[i];
        // Update the reference to the removed Node
        elems[i] = e.parentNode.removeChild(e);
    }
}

我的问题是对这种行为的了解,在不同的环境中可以预期的是什么,使用这种技术的缺陷是什么?

我将不胜感激。

1 个答案:

答案 0 :(得分:0)

innerHTML属性在HTML5中只是“标准化”,它实际上只记录了许多功能的常见浏览器行为。像innerHTML这样的东西在不同的浏览器中实现的方式不同,并且会在一段时间内保持不同,所以如果它导致问题,最好避免使用它。

还有其他方法可以清除元素的子节点,例如:

function removeContent(element) {
  while (element.firstChild) {
    element.removeChild(element.firstChild);
  }
}

哪个应该避免你的innerHTML问题,并且代码比你的版本少一点。您也可以将element替换为自身的浅层克隆,但这可能会导致其他问题。