Software by Steven
Sometimes a square peg is a round hole
InnerHTML vs. DOM Manipulation
Posted by on December 7, 2010
In working on pushing out my 0.3 Release for the BBB Player, I’ve had to look a great deal into element generation and the best ways to do it. But how exactly do you measure “best”? Is best the best performance, the least lines of code, or the most compatible? And if we go by all three, what’s the answer then?
Usage and Support
Turns out, this has been a long-lasting debate on the interwebs. Internet Explorer’s handy but non-standard innerHTML property lets you do things quick and painlessly by specifying the HTML code as a string right in the Javascript. You can build this dynamically then via simple string concatenation. It’s short and quick, but not guaranteed to be supported everywhere (though it happens to be by just about every browser out there). Seems to be a carry over from IE5.5 when IE had 95% of the market. What were other browser makers to do to have their browser work with a web site but to implement innerHTML? Besides though, watch how friendly it is to use.
var mySpanId = "spanID";
var myDiv = document.getElementById("myDivId");
myDiv.innerHTML = '<span id="'+mySpanId+'">Embedded Content</span>';
A quirk about it though is that as simple as it is, it will not work with tables. A price to pay for simplicity, but unfortunately quirks happens when the specifications are not standardized. Now lets compare DOM Manipulation:
var mySpanId = "spanID";
var myDiv = document.getElementById("myDivId");
var mySpan = document.createElement('span');
var spanContent = document.createTextNode('Embedded Content');
mySpan.id = mySpanId;
mySpan.appendChild(spanContent);
myDiv.appendChild(mySpan);
Longer code, that’s for sure. But this is guaranteed to work on every browser, now and forever (well, almost). Though there are still a few cross-browser quirks. Turns out you can create input elements both ways, but IE does not support the DOM methods outlined above; it balks if you try and set the type of the newly created input element like so:
var myInput = document.createElement('input');
myInput.type = 'text';
And there is no pure DOM way around this. No using myInput["type"] = ‘text’, no nothing. In IE, you simply can’t change the type of an input element once it’s been created. As John Resig notes, not even jQuery is immune, and so he had to implement a work around in his API. Turns out you must specify the entire element in HTML markup for it to work:
var myInput = document.createElement('<input type="text" />');
So there are compatibility concerns on both sides of the fence, but one thing DOM does which innerHTML doesn’t is allow for easy mixing and merging of Document Fragments: collections of nodes outside of the main document structure which can be built, appended and removed as children in any order desired. Contrast this with innerHTML where you need to know what you’re concatenating as strings before doing it, unless you want to worry about complicated substringing later on.
While in the end it’s personal preference, the standard compliance and dynamic changing nature of Document fragments gives DOM the nod in my book.
Performance
So with that being that, how do things compare in performance? Turns out there’s been a lot of benchmarking done on this. John Resig has done some studies comparing the performance of appending Document fragments as opposed to appending many individual nodes. Testing on a wide variety of browsers, he showed that it can vary from two-four times faster using Document Fragments. So lesson learned: Favour Document Fragment usage. They result in only a single redraw operation for the browser, since there is only one modification of the displayed nodes.
Before going on to other studies though, another interesting difference between document fragments and individual nodes: changes to individual nodes after appending them as children persist to the appended-to node, but modifying a document fragment after appending will not. In fact, appending a document fragment as a child will result in clearing the nodes from it in the process of appending to the parent. Clearly, this is the result of pointers and linked lists being worked with, but it’s still good to know that upon appending a document fragment, the parent element is considered the sole owner of the child nodes.
On to other studies! Several years ago Peter Paul Koch conducted his own comparing IE5.5, 6 and 7 to FF 2 and 3 beta, Opera 9.5 Safari 3. At that time, innerHTML won. It makes sense in a way, IE was the monster browser of the time, why not optimize a browser to use IE’s innerHTML well? Well, a little bit later, once a full iteration of browser development had occurred (including the emergence of Google Chrome), Andrew Hedges conducted his own studies. Turns out he was able to show DOM pulling much closer, to the point that the difference was negligible. Perhaps this was the document fragment factor or the result of other optimizations not included in PPK’s method?
In the end, they are now almost interchangeable in speed. So which to use? Andrew Hedges clearly prefers DOM, but as for you and I, pick your pony. I’ll be sticking with DOM, it’s a bit more code but a lot less compatibility to worry about in years to come.
myDiv
Pingback: InnerHTML vs. DOM Manipulation Part 2 (IE9 Edition) « Software by Steven