1

我编写的用于“清理”的函数有问题,请参阅下面的代码,我将解释它在下面是如何工作的。

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 个输入,没有类“keep”,但变量 i 只达到 2 并且循环停止(它应该达到 4 并删除所有四个元素)

任何帮助将不胜感激。

/* 更新 */

感谢@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;
},
4

1 回答 1

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

正如 Brett Walker 指出的那样,您也可以向后迭代,如下所示:

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更新(即变少),但这并不重要,因为您只在开始时使用它,而不是在迭代期间使用它。因此,您不会受到这种“怪癖”的影响。

于 2011-08-20T12:39:40.350 回答