Ten good practices for writing JavaScript in 2005

1. Make sure your JavaScript code is in balance with its environment

Web Standards are a three-legged stool, or without metaphors, a threesome of technologies that should live together in harmony. (X)HTML adds structure and semantics to your content, CSS is responsible for its presentation, and the DOM provides an interface to add behavior. You keep your Web pages flexible (or: easier to understand, maintain, restyle and update behavior) by separating all three layers; structure and content from presentation, structure and content from behavior and presentation from behavior. To accomplish this, try to avoid inline behavior and use unobtrusive techniques instead.

When you attach behavior on page load, you may have to work around some known issues. First, you may encounter differences in cross-browser event handling. Second, make sure you don't overwrite existing onload handlers. Last, but not least, you may encounter a delay in the attachment of your behavior. The underlying problem is that a window onload event will only execute after the whole document, including all page assets like images and objects, is loaded. If your script needs to respond immediately after an element has loaded or if you work with a lot of content, a series of images or a slow server, you may be forced to look for a solution. You can either hide your content until the behavior is attached or attach the behavior via a script call after your elements are loaded, like at the end of the body element.

Choose your markup wisely, so you can take full advantage of the power of the DOM. For example, when you use nested lists to build a navigation bar, you can use the structure of the DOM tree instead of a replicated structure in arrays. Scripting should be avoided in some cases where you can use markup or CSS to create behavior. This may sound a bit contradictory, however built-in behavior enabled by (X)HTML attributes (e.g. disabling a form field or setting a max length on an input field) and CSS pseudo-classes (e.g. when building rollovers or drop downs) are regarded to be wider supported and easier to implement than using JavaScript. ToughQuiz on Quirksmode illustrates the discussion and the fine line between the uses of CSS generated content and regular markup and behavior.

In those cases where CSS currently lacks cross-browser support or is missing features for adding presentation, DOM based scripting can supplement CSS. Presentational scripting will probably be replaced in a few years, when browsers have better CSS2.1 compliance and with the support of CSS3. Please realize that, because of the interrelationship of the different Web Standards and because both Web Standards and Web clients are constantly evolving, some good practices for using the DOM and JavaScript will change over time.

2. Create accessible JavaScript

JavaScript is accessible when a page's navigation, content and main functionality (e.g. submitting a form) is available to your whole target audience, independent of their Web client or input device. This includes:

  • People who use assistive technologies, like screen readers
  • People who don't use a mouse for navigation
  • People who have no JavaScript support (e.g. some mobile clients), have JavaScript disabled, or have partial DOM or JavaScript support
  • Machines, like search engines

The most common way to create accessible JavaScript is to use unobtrusive techniques that are mouse independent and enhance your already accessible markup with behavior. Progressive enhancement and its predecessor graceful degradation are good strategies to create Web pages that are accessible to the most common denominator, while providing a better user experience for a smaller group of people with more advanced devices or Web clients. No matter what strategy you use, make sure that you always design for multiple scenarios.

3. Create usable JavaScript

The usability of a Web page is often determined by a good information architecture, clear and intuitive visual design and well designed functionality. One of the main arguments to enhance your markup using unobtrusive JavaScript is to improve the usability of a Web page by supporting these usability attributes. If you add JavaScript and don't enhance the usability of a Web page, you should rethink if you should apply it at all.

4. Create easy applicable JavaScript

Unobtrusive scripting bridges the gap between 'designers' and 'coders'. There is a big group of people in today's industry that does know how to write (X)HTML and CSS but doesn't feel very comfortable with the DOM and JavaScript. Unobtrusive behavior introduced a mechanism to easily apply small portable scripts to a Web page: "Just make sure your markup looks like A, include this script B, and as a result you have a page that can do C".

Try to create small pieces of independent code. The disadvantages of a lot of existing JavaScript code libraries are that you often have to include a lot more code than you really need and that they are harder to understand and maintain if you didn't create them yourself. Because the functions in these libraries are often grouped and reused by other scripts, it often feels like they are spaghetti-coded. A library with small unobtrusive scripts has the advantage of being light-weight, easy to be understood and easy to be adjusted for more specific implementations.

Create reusable code. If you find yourself duplicating code snippets, create functions. If you find yourself duplicating similar code snippets, try to abstract your code to the level that you can reuse it for multiple purposes.

Document your code well. If you work together with other people, like to share your code with others, or still want to know why you did certain things one year from now, good documentation is key.

5. Create future-proof JavaScript

Avoid browser detection, because it is almost impossible to maintain in the future. Feature testing or object detection offers a browser independent and future-proof technique to test to what extent your Web client supports JavaScript.

XHTML (if not used in backwards-compatible mode) introduces media type application/xhtml+xml (currently unsupported by Internet Explorer), which has a huge impact on how we write JavaScript code:

  • The HTML DOM is case-insensitive, the XML DOM is case-sensitive
  • Elements need to be referenced in lowercase, e.g. document.getElementsByTagName("p")
  • document.body is deprecated, instead reference it by id or use document.getElementsByTagName("body").item(0)
  • Collections like document.images, document.applets, document.links, document.forms and document.anchors do not exist when serving XHTML as XML, instead use document.getElementsByTagName()
  • innerHTML and document.write cannot be used anymore, instead use DOM methods, e.g. document.createElementNS("http://www.w3.org/1999/xhtml", "div")

If you want to keep yourself up-to-date with the latest developments, there are a lot of initiatives from different organisations that will impact the ways we use JavaScript and the DOM in the near future:

  • W3C
    • DOM 3 provides further XML and XPath integration
    • XHTML 2 includes XML Events, which introduces a declarative way to hook up event observers via markup, and XForms, which will change the way how we add behavior to forms
    • CSS3 introduces new pseudo-elements
  • ECMA
  • Browser vendors
    • Standards support, e.g. at the moment it is still a big question if Microsoft will ever fully support existing Web Standards and is going to support future standards
    • The addition of proprietary methods and attributes, e.g. innerHTML, Microsoft.XMLHTTP and XMLHttpRequest
    • Collaborations like the WHAT WG aimed to create new standards in shorter timeframes, e.g. the submission of Web Forms 2 to become a W3C recommendation and Web Applications, which in the future may standardise XMLHttpRequest

6. Know JavaScript's weaknesses, limitations and bugs

Although JavaScript is generally well supported by most modern Web clients, support still remains its biggest weakness. Because from the first days of the Web users were often harassed by all kinds of annoying behavior, browser makers decided to make it easy to switch JavaScript off (Windows XP Service Pack 2 even disables some JavaScript by default, because it regards it as active scripting). If you compare JavaScript with its little stepbrother ActionScript (which is supported when the Flash plug-in is installed and cannot be switched off), you will find that the main difference is that you can rely on its behavior to accomplish certain tasks. Because it is just too easy to switch JavaScript off, simple tasks like form validation always need to be duplicated at the server side. It will be for this reason that in the future most client-side form validation will be replaced by markup and 'built-in behavior'.

As mentioned earlier, the onload event handler is insufficient to get the best out of unobtrusive techniques. I hope that the people of the W3C will respond to this feedback from the JavaScript community and add new handlers like onElementLoad and onDOMLoad to future DOM specifications.

The JavaScript implementations of Internet Explorer and Safari suffer from memory leaks when using circular references like closures. When using circular references, make sure you remove event handlers when a page is unloaded.

7. Often there is more than one good solution

JavaScript is a very flexible language and as a result you often have multiple ways of doing things. You could choose for either a procedural or an object oriented way of coding. For your unobtrusive behavior you can either use custom attributes or use class attributes as triggers to fully control the behavior of your site. Flexibility implies that you have to make certain choices, however often one solution is not necessarily better or worse than another. Base your decisions on the context in which you have to use your scripts and your own philosophy or taste and try to use a consistent coding style.

8. Write your own scripts or reuse code from trusted places

Currently a lot of outdated and badly written code is available on the Internet. Many scripts are plagued by browser detection, are using proprietary features that don't work cross-browser, are inaccessible or are not separating behavior from structure, because they rely on inline event handlers and scripts. It seems that Web Standards, Web clients and the practice of writing good JavaScript have evolved so quickly in the past two years, that it is hard to keep up with the latest good practices. This on its turn makes it hard to reuse code from others or reuse code you wrote yourself a year ago. Because some parts of older scripts may still contain valid code constructs, it is best to review them and rewrite the parts that don't suffice anymore. You will probably often find that a complete rewrite will do best.

So how do less experienced DOM and JavaScript users tell the difference between good and bad code on the Internet? There are some experts on the Internet that advocate modern ways of scripting and there are communities that discuss and rate new scripts and techniques. Some examples are:

DHTML Utopia: Modern Web Design Using JavaScript & DOM is the first title of a new range of books focusing on the application of modern JavaScript and unobtrusive scripting techniques.

9. Optimize your JavaScript code for performance

Optimize your scripts for both download speed and execution speed. Some tips:

  • Avoid fat code libraries and make sure your scripts stay lean and mean (or: small, independent and straightforward)
  • Write efficient code and avoid constructs that execute slow
  • Keep developer versions of your scripts that include full comments and use a compression tool (like JavaScript cruncher or JavaScript Crunchinator) to strip out all comments and white-spaces to create a version for deployment.

10. Use tools to optimize your work process

A selection of tools that make life much easier:

  • Mozilla or Firefox browser
    • Includes the good old Netscape JavaScript console by default (Tools > Web Development > JavaScript Console for Mozilla and Tools > JavaScript Console for Firefox), e.g. to view errors and warnings that make sense
    • The Web Developer Toolbar extension, e.g. to quickly enable or disable your scripts
    • The Mozilla DOM Inspector and the Firefox DOM Inspector extension, to inspect and edit the live DOM of any Web document
    • Venkman, the JavaScript debugger (the Venkman extension for Firefox)
  • JSDoc, a tool that parses inline documentation in JavaScript source files, and produces an HTML summary
  • JSLint, a JavaScript verifier to check for syntax and programming errors.