Nicholas C. Zakas delivers the seventh Web
Exponents tech talk at Google. Nicholas is a JavaScript guru
and author
working at Yahoo!. Most recently we worked together on my next book, Even Faster
Web Sites. Nicholas contributed the chapter on Writing Efficient JavaScript,
containing much of the sage advice found in this talk. Check out his slides and watch
the video.
Nicholas
starts by asserting that users have a greater expectation that sites will be fast. Web
developers need to do most of the heavy lifting to meet these expectations. Much of the
slowness in today's web sites comes from JavaScript. In this talk, Nicholas gives advice in
four main areas: scope management, data access, loops, and DOM.
Scope Management: When a symbol is
accessed, the JavaScript engine has to walk the scope chain to find that symbol. The scope
chain starts with local variables, and ends with global variables. Using more local variables
and fewer global variables results in better performance. One way to move in this direction is
to store a global as a local variable when it's referenced multiple times within a function.
Avoiding with also helps, because
that adds more layers to the scope chain. And make sure to use var when declaring local variables, otherwise
they'll end up in the global space which means longer access times.
Data Access: In JavaScript, data is
accessed four ways: as literals, variables, object properties, and array items. Literals and
variables are the fastest to access, although the relative performance can vary across
browsers. Similar to global variables, performance can be improved by creating local variables
to hold object properties and array items that are referenced multiple times. Also, keep in
mind that deeper object property and array item lookup (e.g., obj.name1.name2.name3) is
slower.
Loops:
Nicholas points out that for-in and for each loops should generally be avoided. Although they
provide convenience, they perform poorly. The choices when it comes to loops are for,
do-while, and while. All three perform about the same. The key to loops is optimizing what is
performed at each iteration in the loop, and the number of iterations, especially paying
attention to the previous two performance recommendations. The classic example here is storing
an array's length as a local variable, as opposed to querying the array's length property on each iteration through a
loop.
DOM: One of
the primary areas for optimizing your web application's interaction with the DOM is how you
handle HTMLCollection objects: document.images, document.forms, etc., as well as the results
of calling getElementsByTagName() and getElementsByClassName(). As noted in the HTML spec,
HTMLCollections "are assumed to be live
meaning that they are automatically updated when the underlying document is changed." Any idea
how long this code takes to execute?
var divs = document.getElementsByTagName("div"); for (var
i=0; i < divs.length; i++) { var div = document.createElement("div"); document.body.appendChild(div); }
This
code results in an infinite loop! Each time a div is appended to the document, the divs array is updated, incrementing the
length so that the termination condition is never reached. It's best to think of
HTMLCollections as live queries instead of arrays. Minimizing the number of times you access
HTMLCollection properties (hint: copy length to a local variable) is a win. It can also be
faster to copy the HTMLCollection into a regular array when the contents are accessed
frequently (see the slides for a code sample).
Another area for
improving DOM performance is reflow -
when the browser computes the page's layout. This happens more frequently than you might
think, especially for web applications with heavy use of DHTML. If you have code that makes
significant layout changes, consider making the changes within a DocumentFragment
or setting the className property to
alter styles.
There is hope for a faster web as browsers come equipped
with JIT compilers and native code generation. But the legacy of previous, slower browsers
will be with us for quite a while longer. So hang in there. With evangelists like Nicholas in
the lead, it's still possible to find your way to a fast, efficient web page.
By Steve
Souders, Performance Evangelist
Check out
other blog posts and videos in the Web
Exponents speaker series: