Javascript for循环不会退出并不断更新getElementsByTagName变量

时间:2016-08-09 16:48:24

标签: javascript

我有这个简单的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。

由于

1 个答案:

答案 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');
   ...
}