jQuery Tip #2 - Manipulating the DOM in a Loop

Interested in learning more about jQuery? Check out the jQuery Fundamentals course at Pluralsight.com.


One of jQuery's greatest strengths is its ability to manipulate the DOM with a minimal amount of code. It's so easy to change things that we often don't think about what's happening under the covers. For example, consider the following code that appends nodes to an object named parentDiv.


var parentDiv = $('#emailList');
for (var i = 0; i < 100; i++) {
    parentDiv.append('<div>' + i + '</div>');
}

This is one of the more common ways to append nodes into a given parent. Although it works fine, it's not optimal because jQuery has to constantly perform DOM operations in the loop. You may not notice a problem when looping through 100 items, but as that number increases to a larger number the performance can start to degrade. A more efficient (yet simple) approach from a performance standpoint is shown next:


var parentDiv = $('#emailList');
var divs = '';
for (var i = 0; i < 100; i++) {
  divs += '<div>' + i + '</div>';
}
parentDiv.html(divs);

The previous code only touches the DOM once after the loop has completed resulting in better overall performance. While a lot of string concatenation is occurring, it turns out that going that route is much more efficient than calling append() multiple times.

Keep in mind that you can always manipulate the DOM directly as well and increase performance even more in some cases by using things like document.createDocumentFragment() and other techniques. While I prefer to use jQuery functions whenever possible, sometimes it's necessary to step outside of jQuery’s API for a given task and use the native DOM API instead.

A test page available at http://jsperf.com/strings-vs-array-join-vs-doc-fragment/8 shows different techniques that can be used for updating the DOM while using a loop as well as their individual performance results. An example of the test results and the different techniques tested are shown next. You’ll notice that calling jQuery’s append() function in a loop doesn’t fare too well compared to some of the other more “native” DOM options.

Test Ops/sec
Strings
var str = '';
var c = '<li>' + d.first + ' ' + d.second + '</li>'
for (var i = 0; i < 100; i++) {
  str += c;
}
document.getElementById('list').innerHTML = str;
1,226±0.84%61% slower
Array (using push)
var arr = [];
var c = '<li>' + d.first + ' ' + d.second + '</li>'
for (var i = 0; i < 100; i++) {
  arr.push(c);
}
document.getElementById('list').innerHTML = arr.join('');
1,234±0.35%61% slower
Doc Fragment
var doc = document.createDocumentFragment();
var c = d.first + ' ' + d.second;

for (var i = 0; i < 100; i++) {
  var e = document.createElement("li");
  e.textContent = c;
  doc.appendChild(e);
}
document.getElementById('list').appendChild(doc);
3,020±3.24%fastest
Array (using index)
var arr = [];
var c = '<li>' + d.first + ' ' + d.second + '</li>'
for (var i = 0; i < 100; i++) {
  arr[i] = c;
}
document.getElementById('list').innerHTML = arr.join('');
1,223±0.46%61% slower
Array join then string concat
var arr = [];
var c = d.first + ' ' + d.second;

for (var i = 0; i < 100; i++) {
  arr[i] = c;
}
document.getElementById('list').innerHTML = '<li>' + arr.join('</li><li>') + '</li>';
1,252±0.37%60% slower
DOM List
var list = document.getElementById('list');
var c = d.first + ' ' + d.second;

for (var i = 0; i < 100; i++) {
  var e = document.createElement("li");
  e.textContent = c;
  list.appendChild(e);
}
3,144±0.00%fastest
jquery
var $list = $("#list");
var c = '<li>' + d.first + ' ' + d.second + '</li>';
for (var i = 0; i < 100; i++) {
  $list.append(c);
}
428±9.06%86% slower
doc fragment 2
var doc = document.createDocumentFragment();
var c = d.first + ' ' + d.second;
var e = document.createElement("li");
e.textContent = c;
for (var i = 0; i < 100; i++) {
  doc.appendChild(e.cloneNode(true));
}
document.getElementById('list').appendChild(doc);
3,241±11.16%fastest


Conclusion

As Peter Parker’s Uncle said in Spider-Man, “With great power comes great responsibility”. The same can be said about the power jQuery provides to developers. Take time to research sections of code that you know are critical for the performance of your application. Just because you can use a particular function doesn’t mean you should. Check out http://james.padolsey.com/jquery/ if you’d like an easy way to see what jQuery functions are doing behind the scenes.

If you’re interested in learning more about jQuery or JavaScript check out my jQuery Fundamentals or Structuring JavaScript Code courses from Pluralsight. We also offer onsite/online training options as well at http://www.thewahlingroup.com.


image

comments powered by Disqus

1 Comment

Comments have been disabled for this content.