Optimizing Javascript for IE7

I’m working on a project that is JavaScript heavy. My code is running at a decent speed in most browsers. However, I notice a significant reduction in performance when running the application in IE7. Its important that I support IE7:

What general steps can I do to improve performance in IE7?
What JavaScript features create the most bottleneck in IE7?

All HTML/JavaScript/CSS are embedded into the application page for portability reasons. I’ve minified all JavaScript but managing the download of the scripts will not be an issue as they are all embedded by default.

This really depends on what the code is doing. For example if you’re doing string concatenation a very large amount of times, you’ll find that IE7 is quite slow.

Craig Buckler wrote an article about it a little while ago: http://blogs.sitepoint.com/2010/09/14/javascript-fast-string-concatenation/

This is of course but 1 tiny tip to improve performance, like I said, it depends on what the code does. One trick to find out how long things take is to create 2 date objects on either side of a piece of code and see how long it takes for it to complete.

e.g.:


var before = 0,
	after = 0,
	i = 0,
	n = 0,
	str = '';

	n = 100000; //magic number
	before = new Date().getTime();
	for (i=0; i<n; i++) {
		str.concat("a", "b");
	}
	after = new Date().getTime();

	window.alert(after-before + "ms");

I think one of my problems may be with traversing the DOM. Is this particularity slow in IE7?

My page has 14 tables. The number of rows in each table varies from 0-50 rows. Each table may have any where from 5-9 columns.

My application involves a lot of manipulation of these tables. Are there any tricks I can use to speed up DOM traversal? Are there any techniques or methods I want to avoid using?

DOM traversal does tend to be slow in IE7.

Are you using a JavaScript library by any chance? (quite often they have their selection / DOM methods optimized).

There is also a series of articles on the IEBlog about performance optimization, they are a few years old, but still relevant.
http://blogs.msdn.com/b/ie/archive/2006/08/28/728654.aspx

The article discusses some of the obvious optimizations such as variable caching and using local function pointer variables, but one of the more interesting methods is the caching of DOM accessors.

e.g. using document.getElementById(“someID”); in a for loop would be quite bad, so you should cache it whenever possible.

Unfortunately the article also describes some (surprise surprise) IE only methods of caching DOM methods, like “appendChild()”.

This will throw an error in non-IE browsers. I probably wouldn’t recommend using DOM method caching anyway after I just did a quick test I noticed that simply caching the DOM element accessor (i.e. getElementById) was much quicker in IE7/8, Fx and Chrome.

Hope this helped a little bit.

Oh, also, are you applying event handlers to table rows/cells?

I am using a combination of straight JavaScript and jQuery. Would you recommend I use JQuery for as many as the selections as possible?

Especially for selecting, jQuery is pretty hard to beat for optimization. It uses the Sizzle selector engine which is one of the fastest ones available at the moment.

One important thing to remember is that even though jQuery’s selector engine is optimized, multiple calls to a non-cached jQuery object would still slow things down. It is therefore important that you cache jQuery objects if you need to use them multiple times. (e.g. in a loop).

Consider:


/* Let's say you have a table with an id of mainTable ... 
  and you're doing operations on table cells in it. */

/* This is the BAD way, don't do this. 
  What happens is that jQuery needs to find #mainTable every time, 
  then it needs to find tr.even and td within those. */
for (var i = 0; i < someValue; i++) {
  $("#mainTable").find("tr.even td").append("<p>Hello</p>");
}

// This is a much better way:
var $evenCells = $("#mainTable tr.even td");
for (var i = 0; i < someValue; i++) {
  $evenCells.append("<p>Hello</p>");
}

If you’re adding events to your table cells / rows it would be best to use event delegation

on the topic of event delegation:
I have some events being defined dynamically and some declared statically in the HTML. From an optimization standpoint it seems to make sense to have simple events declared statically in the HTML, this way you avoid having to run potentially complex selectors. Or is there reasoning for declaring all events dynamically through a process such as “event delegation”.

Event delegation will help you in that you won’t have to apply many events to many DOM elements.

I think more than anything, a reason to take the statically declared events our of the HTML and into the JS is because it will improve the maintainability of your code by a fair bit.
If for some reason you wanted to add a parameter to an onclick that occurs 10 times in the HTML or only once in the JavaScript, you can quickly see which would be easier and quicker to change.

As far as complex selectors are concerned, that might not necessarily be a problem, and might also be solved if you’re using delegation. (Having said that, how complicated would such a selector be?)

From an optimization point of view I don’t think it would make a very big difference whether your events are declared inline in the HTML or in the JavaScript, but I have no basis for that, it’s purely speculation.

Using the table collection properties rather than getElementsByTagName is faster for accessing elements within tables in all browsers except Firefox.

See http://javascript.about.com/library/bldom15.htm for a reference to all the properties and methods available for table manipulation that will speed up table processing from what you have when using getElementsByTagName.

Let me give an example to make sure I understand. I have a selector here, obj is a table reference and the goal is to get all the th tags from the table.

obj.getElementsByTagName("th");

Your saying it would be more efficient to get all the th elements with a selector such as:

obj.thead.rows[0].cells;