加载页面后,我想为页面上的每个现有元素添加一个附加元素。
我试过这样的事情:
var divs=document.getElementsByTagName('div');
for(i=0;i<divs.length;i++){
newDiv=document.createElement('div');
divs[i].appendChild(newDiv);
}
只是警告这实际上会冻结浏览器,因为divs变量是动态的,每次循环时divs.length只会越来越大。
有没有办法在第一次正常加载DOM时确定标记的数量,并且有机会静态处理这些元素。
到目前为止我还没有其他解决方案。
非常感谢。 丹尼斯!
答案 0 :(得分:11)
问题是DOM集合是live,当底层文档结构发生变化时,它会自动反映在集合上,这就是为什么当访问length
属性时它会包含一个新长度,一种常见的方法是在开始循环之前缓存长度:
var divs=document.getElementsByTagName('div');
for(var i = 0, len = divs.length;i<len;i++){
var newDiv = document.createElement('div');
divs[i].appendChild(newDiv);
}
另请注意,您应使用var
语句声明所有变量,否则它可能会变为全局。
编辑:在这种情况下,由于您要附加相同tagName的子节点,因此将修改集合,并且索引将不再匹配,在第一次迭代中,索引1
将引用上一次迭代中的newDiv
对象,因为@Casey建议在遍历它之前将集合转换为普通数组会更安全。
我使用以下功能:
function toArray(obj) {
var array = [];
// iterate backwards ensuring that length is an UInt32
for (var i = obj.length >>> 0; i--;) {
array[i] = obj[i];
}
return array;
}
//...
var divs = toArray(document.getElementsByTagName('div'));
//...
答案 1 :(得分:3)
就像你说的那样,divs
变量是动态的,所以你必须在使用它之前将它转换成一个数组(它是静态的)。
var nodeList = document.getElementsByTagName('div');
var divs = [];
for (var i = 0; i < nodeList.length; i++)
divs.push(nodeList[i]);
// loop again and append the other divs
另一种(更优雅)的方法是:
var divs = Array.prototype.slice.call(document.getElementsByTagName('div'));
但是,这种方法在IE中不起作用。
答案 2 :(得分:0)
使用jQuery,这非常简单。您可以获得对页面上所有现有div或任何其他元素的引用,然后非常容易地追加新元素,而无需创建显式循环。希望这有帮助。
$('div').each(function(){
var newDiv = document.createElement('div');
$(this).append(newDiv);
});
答案 3 :(得分:0)
document.getElementsByTagName()
NOT 返回一个普通数组,但是HtmlCollection
的一个实例,其行为类似于数组,但实际上为所有元素提供某种视图文档中给定的元素名称。
因此,每当您向DOM中插入内容时,divs
的length属性也会更新 - 当然。
所以,除了这里的其他答案,这种行为现在应该有意义了; - )