0

今天,我在 Javascript 中发现了一些对我来说看起来像“奇怪行为”的东西。让我们假设以下最小示例:

HTML:

<div id="test">
    <span>1</span>
    <span>2</span>
</div>

JS:

var div   = document.getElementById('test');
var spans = div.getElementsByTagName('span');
div.removeChild(spans[0]);
div.removeChild(spans[1]);

(小提琴:http: //jsfiddle.net/SkYJg/

现在,在运行脚本时,出现错误:

TypeError:Node.removeChild 的参数 1 不是对象。

仔细一看,发现第一个被删除后spans[1]是 null 。事实上,下面的代码

var div   = document.getElementById('test');
var spans = div.getElementsByTagName('span');
console.log(spans.length);
div.removeChild(spans[0]);
console.log(spans.length);
div.removeChild(spans[1]);

2在第一次日志操作时产生,但1在第二次。

现在,很清楚这里发生了什么:在第一个 ?span? 已从 DOM 中删除,它也不再是HTMLCollection存储在内部的一部分spans

我一直认为HTMLCollection-Object 包含对其包含的所有对象的引用。创建集合后,我没有在任何地方修改集合。所以我认为(但显然这是错误的)该集合的行为就像一个数组:引用一直保留在那里,直到我手动删除/修改它们。

我查看了MDN 的规范。而且,确实,它在顶部说:HTMLCollections in the HTML DOM are live; they are automatically updated when the underlying document is changed.

我能想到的防止这种情况的唯一方法是在对它进行任何操作之前循环遍历collectino,复制对数组的所有引用,然后使用数组访问它们。但这对我来说看起来非常笨重......有更好的解决方案吗?像某种使集合静态或不循环复制它的方法吗?

(当然,在最小的示例中,我可以只删除spans[0]两次,但实际上并不是那么简单)。

[编辑]:在看到@Teemu 的回答后,我重复一遍:在我的真实代码中并不是那么简单(那个代码太复杂,无法在此处完全显示)。我向你保证,我真的需要随机访问该集合中的所有元素,无论是否删除。

4

2 回答 2

4

后门将使用querySelectorAll()而不是getElementsByTagName(),它返回一个非活动的NodeList

于 2014-02-17T17:20:45.583 回答
-1

尝试删除标签时,您没有使用“引用”,只是指向集合的第一个或第二个元素。要使用参考,您应该创建带有 ID 的标签,然后按 ID 指向它。数组的键是第三部分,这就是它会被更新的原因。

另一方面,JavaScript 有时是面向对象的,有时它只是一个脚本,这是一个事实。

于 2014-02-17T17:26:19.610 回答