Глубокое клонирование против настройки innerHTML: что быстрее? - PullRequest
29 голосов
/ 24 марта 2009

Я пытаюсь найти наиболее эффективный способ глубокого клонирования дерева DOM в браузере.

Если я начну с

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

Что будет быстрее,

var target = div.cloneNode(true);

или

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

Я понимаю, что платформа браузера может иметь большое значение, поэтому любая информация о том, как они сравниваются в реальном мире, будет оценена.

Ответы [ 3 ]

50 голосов
/ 24 марта 2009

Давайте проверим!

Я добавил следующий код в копию страницы вопросов StackOverflow (сначала удаляя существующие сценарии и запуская его с нуля, когда один раз timeit () не комментируется, три запуска по 100 операций):

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);
//}))

Вот результаты работы VirtualBox на 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

Так что cloneNode (true) намного быстрее, чем копирование innerHTML. Конечно, так было всегда; сериализация DOM в текст, а затем повторный анализ его из HTML - тяжелая работа. Причина, по которой дочерние операции DOM обычно выполняются медленно, заключается в том, что вы вставляете / перемещаете их один за другим; все DOM-операции, такие как cloneNode, не должны делать это.

Safari удается выполнить операцию innerHTML удивительно быстро, но все же не так быстро, как это делает cloneNode. IE, как и ожидалось, собака.

Итак, auto -1s со всех сторон всем, кто сказал, что innerHTML, очевидно, будет быстрее, без учета того, что на самом деле делает вопрос.

И да, jQuery использует innerHTML для клонирования. Не потому, что это быстрее - читайте источник:

// 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.attachEvent () для реализации своей собственной системы событий, поэтому, естественно, нужно избегать этой ошибки. Если вам не нужно, вы можете избежать накладных расходов.

[Не по теме: опять же, я думаю, что удержание jQuery как вершины передового опыта может быть немного ошибочным, особенно учитывая следующую строку:

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

Это верно - jQuery добавляет свои собственные произвольные атрибуты к элементам HTML, а затем должен избавиться от них, когда клонирует их (или иным образом предоставляет доступ к их разметке, например, с помощью метода $ (). Html ()). , Это достаточно уродливо, но тогда он считает, что лучший способ сделать это - обработать HTML с использованием регулярных выражений, что является основной ошибкой, которую вы ожидаете от наивных респондентов с 1 репутацией больше, чем автора Second Coming Best JS. Рамки Evar.

Надеюсь, у вас не было строки «jQuery1 =" 2 "» в текстовом контенте, потому что если это так, вы просто загадочным образом ее потеряли. Спасибо jQuery! Так заканчивается не по теме.]

1 голос
/ 24 марта 2009

Хммм ... интересно, я только что провел тест в Firefox 3, и глубокий клон, кажется, примерно в 3 раза быстрее, чем идти по маршруту innerHTML.

Я уверен, что innerHTML по-прежнему быстрее, чем отдельные операции DOM, но, по крайней мере, для глубокого клонирования cloneNode (true), кажется, лучше оптимизирован.

0 голосов
/ 24 марта 2009

Вообще innerHTML быстрее. Проверьте это, тест на многих платформах :

...