Глубокое клонирование против настройки innerHTML: что быстрее?

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

Если я начну с

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

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

var target = div.cloneNode(true);

или

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

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

3 ответов


давайте!

Я добавил следующий код на копию страницы вопросов StackOverflow (сначала удалив существующие скрипты и запустив с нуля один из timeit () s uncommented каждый раз, три запуска 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);
//}))

вот результаты, запущенные на 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 op удивительно быстро, но все же не так быстро, как cloneNode. Т. е. это, как и ожидалось, собака.

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

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

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

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

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


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

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


В общем innerHTML быстрее. Зацени это, а бенчмарк на многих платформах: