我有这个简单的javascript片段
function foo() {
bar();
}
function bar() {
var tags = document.getElementsByTagName('example');
for (var i = 0; i < tags.length; i++) {
console.log(tags.length);
tags[i].innerHTML = '<example2>Inserted</example2>';
}
}
foo();
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.2/lodash.min.js"></script>
<example></example>
我没有得到的是,当我将插入的innerHTML更改为Inserted时,它不会退出循环,因为它会“更新”变量标记(我在代码段中添加了2以避免它,如果你跑吧);
作为旁注,如果我使用lodash forEach它会执行我对for循环的预期,只需运行一次循环代码。
function foo() {
bar();
}
function bar() {
var tags = document.getElementsByTagName('example');
_.forEach(tags, function(value) {
console.log(tags.length);
value.innerHTML = '<example>Inserted</example>';
});
}
foo();
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.14.2/lodash.min.js"></script>
<example></example>
我无法理解为什么循环会使用嵌套标记对变量进行udpdating。
由于
答案 0 :(得分:2)
document.getElementsByTagName
及其兄弟DOM方法返回实时HTMLCollection元素,这意味着如果添加了与您的查询匹配的新元素,则包含对HTMLCollection的引用的变量将是更新。你应该:
a)使用Array.from
来&#34;分离&#34;集合:
var tags = Array.from(document.getElementsByTagName('element'));
或者,如果您没有Array.from
可用,则可以使用Array.prototype.slice
:
var tags = Array.prototype.slice.call(document.getElementsByTagName('a'), 0)
b)不添加与您正在迭代的查询匹配的元素(这会创建一个无限循环)
这也是为什么它建议如果你在for
循环中迭代一组元素,你在迭代之前捕获列表的长度并将其用作循环边界:
var tags = document.getElementsByTagName('example');
var length = tags.length;
for (var i = 0; i < length; i++) {
// won't be infinite
document.createElement('example');
...
}