В свое время читал много статей о documentFragment, но долго не мог понять, что в нем реально крутого.
Через некоторое время осознал, что ничего, но кое-что есть. Об этом и поговорим 
documentFragment ?documentFragment - "фрагмент документа" наиболее близок по смыслу к обычному DOM-элементу.
То есть, его можно создать:
var fragment = document.createDocumentFragment()
в него можно добавлять другие узлы.
fragment.appendChild(node)
Фишка заключается в том, что когда documentFragment вставляется в DOM - то он исчезает, а вместо него вставляются его дети. Это единственное и основное свойство documentFragment по сравнению со всеми остальными сущностями DOM.
То есть, можно добавить в него много TD, и потом append к TR. При этом фрагмент растворится и вставятся именно TD как прямые потомки.
documentFragment?Первый случай, когда documentFragment применим - это возврат множества узлов из функции. Можно это сделать возвращением массива, а можно вернуть documentFragment:
function makeRow() {
var fragment = document.createDocumentFragment()
var td_1 = document.createElement('TD')
fragment.appendChild(td_1)
...
fragment.appendChild(td_n)
return fragment
}
Затем внешняя функция может вставить его в DOM или использовать далее без промежуточных массивов.
Это, пожалуй, самый важный случай.
Допустим, нам нужно создать пачку элементов TR и вставить их в DOM.
Первый способ - создавать их и вставлять. И так n раз.
Но операция вставки в "живой" DOM дорогая. И тут на помощь приходит как раз documentFragment. Можно вставлять в него, а уже потом его добавить в DOM.
При этом скорость будет отличаться.
Совершенно не важно, используете ли вы в качестве оторванного от DOM контейнера
documentFragmentили что-то другое.Важно, что промежуточные вставки идут в оторванный от живого документа DOM.
Например, вот два бенчмарка.
Оба они создают таблицу 10x10, наполняя TBODY элементами TR/TD.
При этом первый вставляет все в документ тут же, второй - задерживает вставку TBODY в документ до конца процесса.
Кликните, чтобы запустить.
/* appends elements right after creation */
appendFirst = new function() {
var benchTable
this.setup = function() {
benchTable = document.getElementById('bench-table')
while(benchTable.firstChild) { benchTable.removeChild(benchTable.firstChild) }
}
this.work = function() {
var tbody = document.createElement('TBODY')
benchTable.appendChild(tbody)
for(var i=0; i<10; i++) {
var tr = document.createElement('TR')
tbody.appendChild(tr)
for(var j=0; j<10; j++) {
var td = document.createElement('td')
td.appendChild(document.createTextNode(''+i+j))
tr.appendChild(td)
}
}
}
}
/* appends elements right after creation
BUT wrapping tbody appended late */
appendLast = new function() {
var benchTable
this.setup = function() {
benchTable = document.getElementById('bench-table')
while(benchTable.firstChild) { benchTable.removeChild(benchTable.firstChild) }
}
this.work = function() {
var tbody = document.createElement('TBODY')
for(var i=0; i<10; i++) {
var tr = document.createElement('TR')
tbody.appendChild(tr)
for(var j=0; j<10; j++) {
var td = document.createElement('td')
tr.appendChild(td)
td.appendChild(document.createTextNode(''+i+j))
}
}
benchTable.appendChild(tbody)
}
}
При чем же здесь documentFragment? А не при чем! Вместо него может быть любой узел, но иногда удобен именно documentFragment из-за своего свойства растворяться при вставке.
То есть, когда неудобно делать промежуточный узел-контейнер, например при добавлении множества TR, подгруженных с сервера. Вместо n вызовов appendChild в живой DOM имеем только 1 вызов, это может дать экономию такую же как в бенчмарках выше.
У documentFragment есть метод cloneNode, т.е. его можно клонировать вместе со всеми узлами.
Это также бывает удобно (1 вызов вместо n), но опять же - нет разницы, что клонировать - обычный узел вне DOM или documentFragment.
Удобство documentFragment лишь в том, что при вставке в документ он исчезнет. Как правило, это полезно в таблицах, гридах и т.п.
Фрагмент документа ничего не оптимизирует сам по себе, он не быстрее обычного документа.
Оптимизация заключается именно в том, что все действия делаются вне DOM.
Но благодаря свойству растворяться при вставке, documentFragment уникален, и его стоит иметь в виду. Не всегда можно и удобно создавать настоящий контейнер, а такой, временный - может очень даже пригодиться.