Петля через всех потомков div-JS - программирование

Петля через всех потомков div-JS

Я использую jQuery для этого:

$element.find("*").each(function() {
    var $this = $(this);

    $this.removeAttr("style width align");

    if ($this.is("embed")) {
        $element.append("<div class='video'></div>");
        $this.attr("width", 640).attr("height", 360).parent().appendTo("#" + element + " .video");
    };
});

Но я читал, что метод jQuery .each() довольно медленный по сравнению с простым циклом цикла (jsPerf). Мой вопрос: как я могу имитировать это с помощью чистого JS? Найдите все элементы внутри div, затем прокрутите узлы.

Я пытался найти это, но все, что я могу найти, это ответы jQuery - везде.

Я пробовал другие вещи, но это было как можно ближе к выбору всех потомков:

var children = document.getElementById('id').getElementsByTagName('*');

for( var i = 0; i<children.lengtth; i++){
    children[i].removeAttribute("style");
    console.log(children[i]);
}
4b9b3361

Ответ 1

Вы уже делаете это правильно

var ancestor = document.getElementById('id'),
    descendents = ancestor.getElementsByTagName('*');
    // gets all descendent of ancestor

Теперь вам нужно только перебрать children

var i, e, d;
for (i = 0; i < descendents.length; ++i) {
    e = descendents[i];
    e.removeAttribute('style');
    e.removeAttribute('width');
    e.removeAttribute('align');
    if (e.tagName === 'EMBED') {
        d = document.createElement('div');
        d.setAttribute('class', 'video');
        ancestor.appendChild(d);
    }
}

В зависимости от того, что вы делаете, потому что вы используете getElementsByTagName для получения descendents, descendents является live NodeList, поэтому длина будет изменяться по мере добавления дополнительных узлов до ancestor. Если вам нужно избегать этого, преобразуйте его в массив до цикла

decendents = Array.prototype.slice.call(decendents);

См. этот метод для функции многократного использования.

Ответ 2

Вы могли бы просто использовать что-то столь же простое, как это?

    // get a handle to the div you want.
var div = document.getElementById('someID'),
    // get an array of child nodes
    divChildren = div.childNodes;

for (var i=0; i<divChildren.length; i++) {
    divChildren[i].style.width = null;
    divChildren[i].style.textAlign = null;
}

Ответ 3

Я прокомментировал в @Paul S. ответ, что вы также можете клонировать node и использовать фрагмент документа для добавления новых вложений. Вот пример:

HTML:

<div>
    <div id="container">
        <div align="right">child</div>
        <div align="center">child</div>
        <embed src="" width="0" height="0" />
        <div align="center">child</div>
        <div style="width: 40px">child</div>
        <div style="font-size: 100px">child</div>
        <div width="60%">child</div>
        <embed src="" width="0" height="0"/>
        <div width="60%">child</div>
    </div>
</div>

JS:

var elm,
    clone,
    doc,
    next,
    fragment,
    live = document.getElementById("container");

if (live !== null) {
    fragment = document.createDocumentFragment();
    clone = live.cloneNode(true);
    next = clone.firstChild;
    while(next !== null) {
        if (next.nodeName !== "#text") {
            next.removeAttribute('style');
            next.removeAttribute('width');
            next.removeAttribute('align');

            if (next.tagName === 'EMBED') {
                doc = document.createElement('div');
                doc.setAttribute('class', 'video');
                doc.innerHTML = "EMBED detected, adding div...";
                fragment.appendChild(doc);
            }
        }
        next = next.nextSibling;
    }
    clone.appendChild(fragment);
    live.parentNode.replaceChild(clone, live);
}

Здесь вы можете увидеть демо .

Клонирование node предотвращает живое изменение DOM, поскольку атрибут стиля может иметь свойства, которые заставляют браузер перекрашивать много раз.

Ответ 4

Вы можете использовать функцию querySelectorAll forEach.

document.querySelectorAll('li').forEach(function(element) {
    console.log(element);
});