Donnerstag, Juni 4, 2020

Tiefes Klonen vs setzen von innerHTML: was ist schneller?

Ich versuche, herauszufinden, die meiste leistungsfähige Weise, von tief-Klonen ein DOM-Baum im browser.

Wenn ich beginnen mit

var div = document.getElementById("source");
var markup = div.innerHTML;

Was wird schneller sein,

var target = div.cloneNode(true);

oder

var target = document.cloneNode(false);
target.innerHTML = markup;

Verstehe ich die browser-Plattform können einen großen Unterschied machen hier, also keine Informationen darüber, wie diese zu vergleichen, in der realen Welt würde geschätzt.

  • Ich verstehe nicht, was Sie suchen. Sie möchten, um ein element zu Klonen? var target = div.cloneNode(true); genau das Tat. Was bedeutet Klonen zu tun haben, mit innerHTML?
  • Die konkreten Ergebnisse hängen von Ihrem browser, aber ich fand zwei relevanten tests bei jsPerf hier und hier.
  • innerHTML zerstört-Ereignis-Listener, verwenden Sie es nicht.
InformationsquelleAutor levik | 2009-03-24

2 Kommentare

  1. 50

    Let ‚ s test!

    Habe ich folgenden code Hinzugefügt, um eine Kopie der StackOverflow-Fragen-Seite (entfernen Sie vorhandene Skripts erste, und läuft von Grund auf mit einer der timeit()s auskommentiert jedes mal um, drei Läufe von 100 ops:

    function timeit(f) {
        var start= new Date();
        for (var i=100; i-->0;) {
            f();
        }
        return new Date()-start;
    }
    
    var c= document.getElementById('content');
    var clones= [];
    
    //alert('cloneNode: '+timeit(function() {
    //   clones.push(c.cloneNode(true));
    //}))
    
    //alert('innerHTML: '+timeit(function() {
    //   var d= document.createElement('div');
    //   d.innerHTML= c.innerHTML;
    //   clones.push(d);
    //}))

    Hier sind die Ergebnisse laufen auf eine VirtualBox auf einem Core 2 Q9300:

    IE7
    cloneNode: 3238, 3235, 3187
    innerHTML: 8442, 8468, 8552
    
    Firefox3
    cloneNode: 1294, 1315, 1289
    innerHTML: 3593, 3636, 3580
    
    Safari3
    cloneNode: 207, 273, 237
    innerHTML: 805, 818, 786
    
    Chrome1
    cloneNode: 329, 377, 426
    innerHTML: 2327, 2536, 2865
    
    Opera10
    cloneNode: 801, 791, 771
    innerHTML: 1852, 1732, 1672

    So cloneNode(true) ist viel schneller als das kopieren von innerHTML. Natürlich war es immer; serialising ein DOM text und dann re-Analyse es von HTML ist harte Arbeit. Der Grund, DOM-Kind-Operationen sind in der Regel langsam ist, dass Sie einfügen/verschieben von Ihnen ein-by-one, all-at-once-DOM-Operationen wie cloneNode nicht zu tun.

    Safari schafft die innerHTML-op erstaunlich schnell, aber immer noch nicht annähernd so schnell, wie es tut, cloneNode. Der IE ist, wie erwartet, ein Hund.

    So, auto -1s-rundum an alle, die gesagt innerHTML wäre Natürlich Schneller, ohne zu überlegen, was die Frage war eigentlich.

    Und ja, die jQuery nutzt innerHTML zu Klonen. Nicht weil es schneller ist, obwohl — Lesen Quelle:

    //IE copies events bound via attachEvent when
    //using cloneNode. Calling detachEvent on the
    //clone will also remove the events from the orignal
    //In order to get around this, we use innerHTML.

    jQuery-Element verwendet.attachEvent() implementieren eigene event-system, so natürlich muss es zu vermeiden, dass Fehler. Wenn Sie nicht benötigen, können Sie vermeiden, den Aufwand.

    [Off-topic beiseite: Dann wieder, ich denke holding jQuery als der Höhepunkt der Best-Practice-vielleicht ein bisschen Irre, vor allem angesichts der nächsten Zeile:

    html.replace(/jQuery\d+="(?:\d+|null)"/g, "")

    Das ist richtig — jQuery fügt seine eigene, beliebige Attribute zu HTML-Elementen, und dann muss Sie loswerden, wenn es Klone (oder die sonst Zugang zu Ihrem markup, wie durch die $().html () – Methode). Das ist hässlich genug, aber dann denkt, dass es der beste Weg, dies zu tun, ist die Verarbeitung von HTML mit regulären Ausdruck, der die Art der grundlegenden Fehler, den Sie erwarten mehr von naiven 1-Ruf der SO Fragende als der Autor des Zweiten Kommens Besten JS-Framework Evar.

    Hoffe, du hast nicht die Zeichenfolge „jQuery1=“2″ und“ anywhere in text-Inhalt, ‚cos, wenn so dass Sie nur auf mysteriöse Weise verloren. Dank jQuery! So endet der off-topic beiseite.]

    • Ausgezeichnete analisys. Der einzige kleine nit ist, dass ich war auf der Suche nach pre-serialisieren der Quelle innerHTML einmal, nicht jedes mal in der Schleife. Aber immer noch dreht sich langsamer. Danke.
    • Super Antwort, Bobince. Nur Frage mich, was würde der beste Weg, um drop off diese zusätzlichen Attribute? Suche nur innerhalb der Spitzen Klammern aus einer whitelist der HTML-Elemente, oder ein DOM-element und dann mithilfe von jQuery removeAttr() drauf??? Vielleicht ist es ein trade-off, es könnte sein, viel schneller auf Kosten der mangeln von Personen, die die Zeichenfolge. Obwohl es selten ist, es sollte eine gewisse Art der Warnung in der jQuery-Doku (ich habe es nicht gefunden falls es gibt)
    • Was ich tun würde, wäre, um eine JS-Eigenschaft für die ID, statt ein HTML-Attribut. IE hat einen bug, wo Eigenschaften sind serialisierte, als wären Sie Attribute, sondern nur Tritte in, wo der Wert der Eigenschaft ist ein primitiver Datentyp. Objekt-Typ-Eigenschaften nicht enthalten sind in der innerHTML. Also Einstellung elementnode.jQueryId45438= [1] (ein Array-Objekt) erlauben würde, jQuery, um seine eindeutige ID für das element, ohne in Unordnung zu den serialisieren und dass keine post-innerHTML Korrekturen.
    • (Eigentlich würde ich persönlich lieber nicht hinzufügen-IDS im element-Knoten, aber jQuery basiert auf der Fähigkeit ziemlich stark.)
    • Hey vielen Dank für immer zu mir zurück. Aus was für einen Grund hat jQuery fügen Sie diese zusätzlichen Attribute? Ich habe Sie bemerkt im Firebug vor.
    • Es geht im wesentlichen um die Entkopplung der Elementknoten von element-Daten. Dies ermöglicht die Daten (einschließlich der Funktions – /Objekt-Referenzen) werden im Zusammenhang mit Knoten, ohne das Risiko der Bildung-Referenz-Schleifen, die Speicherverlust, in IE6-7. jQuery setzt ein ID-Attribut auf das element, dann sieht die gleiche ID in einer mapping ( jQuery.cache ), um die zugehörigen Daten. Die Ereignisbehandlung beruht auf einer Art von zugehörigen Daten, so dass Sie so ziemlich jedes jQuery-Skript ist mit dieser.
    • Wow!!! Sie wirklich wissen, Ihre jQuery. Letzte mal sah ich an der Quelle (vor ein paar Jahren) wusste ich nicht viel von dem, was Los war!
    • In der Tat, es ist nicht der weltweit besten lesbaren source code.

  2. 1

    Hmmm… interessant, ich habe gerade einen test in Firefox 3 und eine Tiefe Klon zu sein scheint, etwa 3 mal schneller, als sich die innerHTML-route.

    Ich bin mir sicher, dass innerHTML ist immer noch schneller als die einzelnen DOM-Operationen, aber zumindest für tiefes Klonen, cloneNode(true) scheint besser optimiert.

Kostenlose Online-Tests