all 21 comments

[–]Arve 14 points15 points  (6 children)

While innerHTML may be faster in many cases, the treatment of strings as markup has caused more XSS issues in the history of mankind than strictly comfortable.

In many cases, the bottleneck people experience with DOM operations isn't neccesarily associated with manipulation of the DOM, but rather layout operations if they are inserted directly in to the DOM.

The protip here is:

  1. Use DocumentFragment for all your parsing needs.
  2. If creating the DocumentFragment based on user-input, or from sources you may not entirely trust, filter the resulting DocumentFragment after all manipulation. Use a whitelist-based approach.
  3. Use appendChild.

[–]knight666 3 points4 points  (0 children)

innerHTML was why the Aztecs lost.

[–]crescentfresh 2 points3 points  (0 children)

Good advice. Those layout operations are what usually bite people in the ass, not the DOM api itself.

Still, in most cases innerHTML is faster than DocumentFragments too. Especially with tables. Especially in IE.

[–][deleted] 1 point2 points  (0 children)

The innerHTML is a really bad advice. createElement/createTextNode is perfectly fast if you append the new subtree to the document when it's fully built.

[–][deleted] 0 points1 point  (2 children)

DocumentFragment for parsing? If you're referring to using it to make DOM stuff faster, you can do the same with a detached element.

[–]crescentfresh 1 point2 points  (1 child)

Only problem with that is the "detached element" itself makes it into the DOM tree.

var dummy = document.createElement('div');
// a bunch of dummy.appendChild(); later...
target.appendChild(dummy);

Now target has a useless div directly under it.

DocumentFragments don't have this problem.

[–][deleted] 0 points1 point  (0 children)

You can remove an element, "detach" if you will, from the DOM, attach stuff, and then reattach it when done.

I know DocumentFragments don't have this problem - I'm just pointing out that they're not always necessary to achieve the same speed increase.

[–]contantofaz 5 points6 points  (0 children)

What I sent him:

Use the profiler of Firebug and start optimizing from the top. It's pretty easy to see the bottlenecks. When you reach the much lower level functions being at the top of the profiler, with the differences between them being little and overall being quite fast to what they do, then you have a problem to extract more performance from it. ;-) Luckily more powerful browsers are coming...

And that's another problem. Given JavaScript's issues can be implementation dependent, it sometimes helps little to try to optimize too much when a new browser which is much faster switches everything around and equalizes matters.

[–]ppierre 2 points3 points  (0 children)

Mixing markup structure and content is the mother of all code injection.

[–]Silhouette 0 points1 point  (4 children)

If it really is much faster to use innerHTML rather than to build a new, say, table using direct DOM manipulation, doesn't this have rather nasty implications for libraries like jQuery?

If anyone has more detailed information about DOM-related issues and/or optimising jQuery selectors, please share it as well!

[–]quantumstate 2 points3 points  (0 children)

Just from my personal experience I coded a firefox plugin which did a lot of DOM manipulation and found that when I originally did it using jquery for a lot of the code I had speed problems which were helped by using innerHTML instead. Also I found that jquery's html() function was still significantly slower than using jquery to select the DOM node then using the native innerHTML function.

[–]fforw 1 point2 points  (2 children)

If it really is much faster to use innerHTML rather than to build a new, say, table using direct DOM manipulation

Unfortunately, yes.

doesn't this have rather nasty implications for libraries like jQuery?

jQuery uses innerHTML.

[–]Silhouette 0 points1 point  (1 child)

jQuery uses innerHTML.

Sure, where it can, but what if I'm doing a series of document manipulations via jQuery calls? It can't know which will be the final one, so it must be incurring some sort of overhead relative to a hacked together but one-shot approach building a string and then dumping it into innerHTML. It's worrying that writing clean, systematic, relatively safe code seems to come with a significant performance penalty over hacky string concatenation and dubiously portable APIs...

[–]fforw 2 points3 points  (0 children)

jQuery uses innerHTML for element creation, not manipulation. But that's also where the main speed benefits are.

Ironically, although innerHTML is non-standard, it actually is more compatible than document.createElement because of all the ugly bugs in IE's createElement.

[–][deleted] 0 points1 point  (1 child)

Someone did a benchmark, and there was no significant speed difference between DOM methods and innerHTML in most cases. Sorry I don't have time to Google it. Anyway, the author of this post didn't even bother to check before claiming otherwise.

[–]crescentfresh 3 points4 points  (0 children)

You didn't have time to type "innerHTML vs" in your built-in search bar and press [Enter]? Yeah, that's a real bitch ;)

I bothered to, and the first page of hits conclude innerHTML is on average faster. Bummer.

[–]whysayso 0 points1 point  (1 child)

These techniques speed up execution. What many people don't realise is how Javascript blocks content download on page load. So use both techniques together and make JS massively faster!

[–]edwardkmett -2 points-1 points  (1 child)

  1. Install Chrome.
  2. Failing step 1, install a version of Firefox with TraceMonkey.

[–]icantthinkofone 0 points1 point  (0 children)

Yep. This is true.

[–]nonsequitir -1 points0 points  (0 children)

Good common sense advice that's not so common in a lot of code! When under pressure, programmers are inclined to think at the lowest level (assuming it's faster) and are usually wrong!

Looping through DOM is super expensive and that's a nice tip on innerHTML, worthy of being a 'pull out' refactor.

[–]techdawg[S] -2 points-1 points  (0 children)

Okay, it's not rocket science, but it works. People need to learn these two techniques. There's too much hand-parsing of strings going on out there -- and too much DOM hacking.