JavaScript DocumentFragment
One of the lessor known but incredibly useful gems within JavaScript is the DocumentFragment. DocumentFragments allow developers to place child elements onto an arbitrary node-like parent, allowing for node-like interactions without a true root node. Doing so allows developers to produce structure without doing so within the visible DOM -- an increase of speed is the true advantage. Let me show you how DocumentFragments are used!
DocumentFragment Example
Let's start with a UL with which we'll inject LI's to:
<ul id="list"></ul>
DOM injections and modifications are taxing, so the fewer the interactions the better; that's where the DocumentFragment comes in. The first step is creating the DocumentFragment:
// Create the fragment var frag = document.createDocumentFragment();
This DocumentFragment act like a pseudo-DOM node -- think of it as a virtual UL element, in this case. Now it's time to add elements:
// Create numerous list items, add to fragment
for(var x = 0; x < 10; x++) {
var li = document.createElement("li");
li.innerHTML = "List item " + x;
frag.appendChild(li);
}
Elements can be added to the DocumentFragment just as you could a normal DOM node. Once the tree of DOM nodes is ready to hit the page, simply place the DocumentFragement into its parent (or other DOM placement functions):
// Mass-add the fragment nodes to the list listNode.appendChild(frag);
Using DocumentFragments is faster than repeated single DOM node injection and allows developers to perform DOM node operations (like adding events) on new elements instead of mass-injection via innerHTML. Keep DocumentFragment close by when performing lots of DOM operations -- it could speed up your app considerably!
But test (http://jsperf.com/out-of-dom-vs-documentfragment/3) do not show “an increase of speed” …
@sergey: Probably depends on your browser, I got about 5-6 % speed gain with your test. http://imgur.com/SjHWF
I ran that test too, and documentFragment was slower on all my browsers.
I’m on a Mac… documentFragment was always slower on Firefox 16.0.2 and Safari 6.0.1 (3-4 tests); and mixed results (slower and faster) on Chrome 23.
David
I’ve created revision 7 to show the improvement of using docfragments. As for differences in creating a temp element using createElement vs createDocumentFragment,
http://stackoverflow.com/questions/3397161/should-i-use-document-createdocumentfragment-or-document-createelement
has some explanation.
wouldn’t you want to just concat a string and append that once at the end?
Not if you want to add events or work with nodes DOM structure.
I “fixed” the jsperf test and had a better performance with Fx 17 Mac, Chrome did not show any significant performance difference between the two options.
http://jsperf.com/out-of-dom-vs-documentfragment/10
As long as some browsers profit from documentFragment, everybody should use it (well, at least if you do it correctly).
I updated the speed test http://jsperf.com/out-of-dom-vs-documentfragment/11 by adding test without documentFragment, but still outside of DOM. documentFragment have a limitations and sometimes can not be used.
But why do so?
I can do something like:
var ul = document.createElement('ul');
var li;
for (...) {
li = document.createElement('li');
ul.appendChild(li);
}
smth.appendChild(ul);
What is the difference?
I too use the same method as @seelts, and am wondering the same about performance.