Javascript for循环不能正常工作?

时间:2011-08-20 12:37:02

标签: javascript dom loops getelementsbytagname

我遇到的问题是我写的“清理”,看下面的代码,我会解释它是如何工作的。

clean: function (e) {
    var
            els = null,
        i = 0;

    if (e === undefined) {
        e = this.cont;
    }

    els = e.getElementsByTagName('*');

    for (i=0;i<els.length;i++) {
        if (els[i].className.search('keep') === -1) {
            e.removeChild(els[i]);
        }
    }
    return this;
},

参数e是一个dom元素,如果没有提供this.cont也是早期存储在整个函数中的dom元素,e默认为它。

该函数循环遍历所有子元素并检查它没有类保持(相当明显的是这样做)并删除任何不匹配的元素。

这一切似乎都有效但我有一个元素有2个图像和2个输入没有类'保持'但变量我只到2并且循环停止(它应该达到4并删除所有四个元素)

任何帮助将不胜感激。

/ * UPDATE * /

感谢@pimvb和@Brett Walker,最终的代码很有效。

clean: function (e) {
    var
        els = null,
        i = 0;

    if (e === undefined) {
        e = this.cont;
    }

    els = e.getElementsByTagName('*');

    i = els.length;

    while (i--) {
        if (els[i].className.search('keep') === -1) {
            els[i].parentNode.removeChild(els[i]);
        }
    }

    return this;
},

1 个答案:

答案 0 :(得分:6)

.getElementsByTagName函数返回一个NodeList,它基本上是一个数组但是“实时”,这意味着它会自动更新,例如:删除一个孩子。因此,在进行迭代时,els.length正在发生变化,当您删除2个子项时(剩下2),结果为4 - 2 = 2。移除了2个孩子时i == 2,所以循环会过早地结束你的期望。

为了避免这种情况并使其成为“静态”数组,您可以将其转换为这样的数组,更新自身:

els = [].slice.call(e.getElementsByTagName('*')); // [].slice.call is a trick to
                                                  // convert something like a NodeList
                                                  // into a static, real array

正如布雷特沃克指出的那样,你也可以向后迭代,如下:

http://jsfiddle.net/pimvdb/cYKxU/1/

var elements = document.getElementsByTagName("a"),
    i = elements.length;

while(i--) { // this will stop as soon as i == 0 because 0 is treated as false
    var elem = elements[i]; // current element

    if(elem.className == "test") // remove if it should be removed
        elem.parentNode.removeChild(elem);
}

这将从最后一个元素开始。 .length仍然会更新(即变得更少),但这并不重要,因为您只在开始时使用它,而不是在迭代期间使用它。因此,您不会受到这种'怪癖'的困扰。