Given that I need to insert several tags, it seems to make sense to use innerHTML.
Only ‘several’? Then speed is not an issue. It's when you're creating a hundred you have to think about what you're doing. It's not really the creating that's the problem, it's the child node list manipulation that gets slower and slower as you add each extra element.
As for appending, you don't really have any choice. You can't set the innerHTML without losing the existing content, so unless you're happy with serialising and re-parsing that (which wipes out any non-serialisable data like form contents, JavaScript properties/references and event handlers) you end up setting the innerHTML of another element and moving each child over one by one. This is what many frameworks do and it typically ends up even slower than manual create-and-appendChild.
Depending on your situation (specifically: how many child nodes are already in the target element, and how many are you going to add?) it can be faster to break down the operation into smaller manipulations on a DocumentFragment, whose children can be appended to an element's children all in one go instead of one-by-one. This is much faster. Unfortunately, it is not possible to set innerHTML
on a DocumentFragment.
There may also be faster hacks using Range objects to move a load of HTML at once, but unfortunately Ranges are highly cross-browser variable. It seems to me, though, that someone ought to be able to build a fast append-html out of IE's range.pasteHTML and W3's range.extractContents. Anyone up for it?
As far as I can tell, create/append node simply prevents you from creating invalid code
Potentially invalid markup doesn't just mean your application breaks in some browsers. When you're blindly splicing together HTML without escaping like an idiot:
element.innerHTML= '<a href="'+url+'">'+title+'</a>';
then you have a client-side cross-site-scripting security hole that is just as bad as a server-side one.
You can, of course, compromise, by creating the elements and setting their contents in separate steps. For example:
element.innerHTML= '<table>'+'<tr><td>X</td><td><a href="#">go</a></td></tr>'.repeated(urls.length)+'</table>';
for (var i= 0; i<urls.length; i++) {
var row= element.firstChild.rows[i];
row.cells[0].firstChild.data= urls[i];
row.cells[1].firstChild.href= urls[i];
}
(string.repeated is not standard JavaScript, but its use here is obvious.)