2016-08-09 91 views
0

我有這個簡單的JavaScript片段的JavaScript循環不退出和不斷更新的getElementsByTagName變量

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來被插入它不會退出循環,因爲它保持「更新」變量標籤(我在代碼片段中添加了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與嵌套標籤的變量。

感謝

回答

2

document.getElementsByTagName和它的兄弟DOM方法返回元素的現場的HTMLCollection,這意味着如果添加符合您查詢的新元素,包含參照的HTMLCollection的變量將被更新。你應該:

一)使用Array.from以 「分離」 的集合:

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