Reputation: 312
I am wondering how to make the loop below more efficient. On my page it has more iterations than 100, that is why, as you can imagine it is troublesome.
for (var i = 0; i < 1000; i += 1) {
var el = document.createElement('div');
el.appendChild(document.createTextNode('Node ' + (i + 1)));
document.getElementById('nodeHolder').appendChild(el);
}
Thanx for help in advance.
Upvotes: 1
Views: 332
Reputation: 263
You definitely need to use DocumentFragment as suggested by @David Thomas.
The most efficient version as I see is this... cloneNode
is always better than createElement
, switching between shallow or deep copy (still faster than createEl) as required.
Not that it gives a significant gain but you should shy away from assignments when you can. Store data in variables only when you need to. Of course when it comes to readability it's a different thing.
var fragment = document.createDocumentFragment();
var tplEl = document.createElement('div');
var contentTpl = document.createTextNode('Node ');
for (var i = 1; i <= 1000; i++) {
var curNode = contentTpl.cloneNode(false);
curNode.nodeValue = curNode.nodeValue + i;
tplEl.cloneNode(false).appendChild(curNode);
fragment.appendChild(tplEl);
}
document.getElementById('nodeHolder').appendChild(fragment);
Note that adding the fragment
to the nodeHolder
adds all childs of fragment
as childs to nodeHolder
triggering only 1 flow as opposed to 1000 flows in your earlier code.
Reference: Speeding up JavaScript
Upvotes: 1
Reputation: 1482
jQuery way...
var d = '';
for(var i=0;i<1000;i++) d += '<div>Node ' + (i + 1) + '</div>';
$('#nodeHolder').append(d);
Or javascript inside html...
<div id="nodeHolder">
<script>(function() { for(var i=0;i<1000;i++) document.write('<div>Node ' + (i + 1) + '</div>'); })();</script>
</div>
Upvotes: 2
Reputation: 253318
All I can really suggest is getting a reference to the nodeHolder
element outside of the for:
var nodeHolder = document.getElementById('nodeHolder');
for (var i = 0; i < 1000; i += 1) {
var el = document.createElement('div');
el.appendChild(document.createTextNode('Node ' + (i + 1)));
nodeHolder.appendChild(el);
}
Or perhaps using a document fragment to hold the interim changes/appends and then add that to to the nodeHolder after the loop:
var fragment = document.createDocumentFragment();
for (var i = 0; i < 1000; i += 1) {
var el = document.createElement('div');
el.appendChild(document.createTextNode('Node ' + (i + 1)));
fragment.appendChild(el);
}
document.getElementById('nodeHolder').appendChild(fragment.cloneNode(true));
JS Fiddle showing both approaches (with timing if the console is available).
Upvotes: 3
Reputation: 8301
In summary:
In this pattern, you can take advantage of a reverse loop:
//Cache the DOM element
var node = document.getElementById('nodeHolder'),
markup = [];
//Run the loop backwards for additional speed
var i = 10000;
while(i--){
markup.push('<div>Node ' + (i + 1) + '</div>');
}
//Reverse the array, join it, then set the innerHTML
node.innerHTML = markup.reverse().join('');
Working example: http://jsfiddle.net/ZAkMZ/3/
Reverse while loop speed reference: https://blogs.oracle.com/greimer/entry/best_way_to_code_a
jQuery version:
//Cache the DOM element
var node = $('#nodeHolder'),
markup = [];
//Run the loop backwards for additional speed
var i = 10000;
while(i--){
markup.push('<div>Node ' + (i + 1) + '</div>');
}
//Reverse the array, join it, then set the innerHTML
node.append(markup.reverse().join(''));
Upvotes: 1
Reputation: 74738
May be this way:
for (var i = 0; i < 100; i+=1) {
$("<div/>").appendTo("body").attr({"class":'txtHolder'});
$(".txtHolder").append(i+1);
}
Upvotes: 0
Reputation: 6878
Maybe: You could generate a HTML String in the for loop like:
<div>Node 1</div><div>Node 2</div>
and then set the .innerHTML property of nodeHolder to this string after the whole loop is completed.
(... and let the DOM renderer figure out how to best optimize the action)
Upvotes: 1