Hi,
Folgende Ausgangsstellung ich habe einen knoten mit mehreren kindknoten und möchte jetzt das alle diese kindknoten in einen wrapper div kommen, welcher nicht durch css verändert werden darf, soll heißen der wrapper darf an der Darstellung nichts ändern.
So ganz ist mir die Notwendigkeit noch nicht klar.
Warum muss #container durch einen Wrapper ersetzt werden, warum kannst du nicht #container wie gewünscht formatieren?
Soll das Script in fremden Seiten arbeiten, wo du die Formatierung von #container nicht unter Kontrolle hast? Da könnten aber auch für dein Wrapper-Div Formatierungen gelten, die du nicht unter Kontrolle hast (schon allein über den Element-Selektor div). Da würde ich mich fragen, ob es nicht generell performanter wäre, wenn du alle CSS-Eigenschaften, auf die du dabei Wert legst, für #container selber explizit per JavaScript setzt ...?
so meine Frage ist nun genauer definiert, wie groß ist der Unterschied zwischen appendChild() und insertBefore() bezüglich der Geschwindigkeit
Das dürfte generell erst Mal kaum einen Unterschied machen. Beide hängen einen Knoten "irgendwo" in einen DOM-(Teil-)Baum ein, lediglich die Position ist eine andere.
Bei deiner derzeit gewählten Form,
wrapper.insertBefore(knoten, wrapper.firstChild)
muss allerdings auch wrapper.firstChild jedes Mal neu ermittelt werden - da könnte appendChild ein Quentchen schneller sein, weil du die Position da nicht im Script selber angeben musst, sondern den Interpreter sich selber drum kümmern lässt.
und gibt es noch großen Optimierungsbedarf, ab der variable 'container' abwärts?
Hängt das wrapper-Element zu dem Zeitpunkt, wo du die Kindknoten einhängst, schon im Dokument? (Sieht nach deinem Beispielcode nicht so aus, aber ich frag trotzdem mal ...)
Es erst nach dem Einhängen aller Kindelemente ins Dokument einzufügen, sollte auf jeden Fall die schnellere Alternative sein.
Generell gilt: DOM-Manipulationen gehen idR. immer schneller, wenn sie "ausserhalb" des DOMs des aktuellen Dokumentes stattfinden.
#container auch erst aus dem Dokument herauszulösen (removeChild), bevor dessen Kindknoten "entnommen" werden, könnte ggf. noch etwas bringen. (Sofern vom Ablauf her möglich; kann ja auch danach wieder engefügt werden, wenn nötig.)
for(tmp = container.childsNodes, i = tmp.length; i--;)
wrapper.insertBefore(tmp[i], wrapper.firstChild);
Auch wenn das "Verschieben" von DOM-Knoten die Hauptbremse sein dürfte, kann man hier evtl. noch ein bisschen optimieren.
Dass in der Abbruchbedingung die Länge der childNodes immer wieder neu ermittelt werden muss, bremst auch ein bisschen. (Und wrapper.firstChild jedes Mal auf's neue bestimmen beim Einfügen eines Knotens auch, s.o.)
Ich würde es ohne eigenen Zähler mit einer While-Schleife probieren, und appendChild statt insertBefore nutzen:
var fChild;
while(fChild = container.firstChild) {
wrapper.appendChild(fChild);
}
So lange container noch ein firstChild hat, hänge dieses hinten an wrapper dran.
Die Hilfsvariable fChild deshalb, damit container.firstChild nicht beim Anhängen an wrapper noch ein zweites Mal ausgewertet werden muss - der Einsatz des .-Operators "kostet" relativ viel. Gerade im Bereich solcher Mirco-Optimierung kann sich auch das bemerkbar machen.
Ach ja, P.S.: So, wie du das ganze hier aufbereitet hast, gehe ich davon aus, dass ein "Umhängen" der Kindknoten per
wrapper.innerHTML = container.innerHTML;
container.innerHTML = "";
keine für dich ernsthaft in Betracht zu ziehende Alternative wäre?
Das könnte noch mal deutlich schneller sein, als "richtige" DOM-Manipulation; allerdings gehen dabei z.B. Eventhandler verloren - schliesslich werden damit die Elemente nicht wirklich umgehängt, sondern schlicht und einfach neu erzeugt (und die "alten" anschliessend weggeworfen).
MfG ChrisB
Light travels faster than sound - that's why most people appear bright until you hear them speak.