[clipart]When I was fiddling with my JavaScript (sounds obscene) for the MIX 10k Challenge, I was obviously interested in shrinking the code as small as possible. I was also interested in learning some best practices that would produce tighter minified code but would not reduce the readability and integrity of the unminified source.

I came up with two simple practices that I intend to follow going forward to produce readable JavaScript that minifies better:

1. Reduce Early Returns

When I'm writing code, sometimes I think of error situations after I've written the main body of a function. This often results in me inserting a quick early return at the top of a function:

  function foo() {
    if (garbage > 0) return;
    // rest of function here

This gets the error condition "out of the way" and I don't have to think about it anymore. However, it is usually better practice to write this as:

  function foo() {
    if (garbage == 0) {
      // rest of function here

Early returns are sometimes debatable, but in general they make your code harder to read (particular if your return is embedded deeper in the function than at the top in my simple example). They also have the side effect of making your code larger: that extra 'return;' is 7 more characters compared to the two required for the braces.

In my experiments YUI Compressor does not rewrite my code to the second example, eliminating the early return. On the other hand, the Closure Compiler does.

2. Collapsing Variable Declarations

This one is pretty straightforward. Instead of writing this:

  var x = 5;
  var y = 2;
  var z = "foo";

write this:

  var x = 5,
      y = 2,
      z = "foo";

It looks just as readable and reduces the extra 'var' characters.

Again, as with the first case, YUI did not reduce my code while Closure Compiler did.

What Else?

By the way, I don't mean to imply that the Closure Compiler is an overall better minifier than YUI Compressor.

These are just two simple examples, but I'm interested in learning some more best practices that will keep my un-minified code readable but produce tighter JS when minified.

It may sound silly to worry about 3 characters here and 5 characters there, but I think about it this way: it doesn't hurt my code at all to follow the practices above and it has the potential to reduce size when minified (by even a very small amount), so why not follow it? This is similar to when I retrained myself to consistently use the pre-increment operator in C++ for-loops in case the loop variable is an iterator: doesn't reduce the readability of my code and has the potential to improve the efficiency (read more).

So what else?

§552 · January 18, 2010 · Uncategorized · Tags: · [Print]

6 Comments to “Tight JavaScript”

  1. Don’t know about whether it helps minified versions, but here are a few things I use:

    * for (;;) instead of while (true)

    * void 0 instead of undefined (OK that’s not actually helpful for readability :)), and so x === void 0 instead of typeof x == ‘undefined’

    * [a,b,c,d] instead of a + ‘,’ + b + ‘,’ + c + ‘,’ + d where you know that the value will be coerced to a string

    * “abc def ghi jkl”.split(” “) instead of [“abc”, “def”, “ghi”, “jkl”], where the gains are worth it. (It’s easier to type, too.)

    * +x instead of Number(x) or parseFloat(x)

    * a || b instead of a ? a : b or similar

    * x = a && a.b && a.b.c instead of first checking that a && a.b are truthy in an if statement and then getting a.b.c.

  2. All I can contribute offhand is what I posted on Twitter the other day; if you are seeing NaN when trying to concatenate a string change =+ to +=. Not really optimization though it might help someone out!

    I’ll have to spend some time doing some research on JavaScript garbage collecting. The var attribute with commas was pretty nifty and I applied that practice to the onload JavaScript file in new version of my site, thanks!

  3. Wait…I have to take that back about JavaScript var/comment, IE7 spits out errors; if it would work in IE6 I’d totally do it though. IE9 better bring some massive updates to JavaScript!

  4. Tobu says:

    I *like* early returns.

    They mean less nesting, which for me means greater readability.

  5. I dunno, those kind of things generally compress really well with gzip, so I would go for what is most intuitive.

    I think the most important size win can be found in renaming local variables (like both YUI and Closure do). Because you change function arguments to a, b, c, … instead of various different names, there will be more duplication and it will thus compresses really much better.

    However all the other stuff like avoiding a return statement here and there… If there is a return statement elsewhere in your code, gzip probably already made a token for it.

    Similarly, using object literals to initialise class members (var X = Class.create({a:function()})) like some frameworks support doesn’t really end up being smaller than using the X.prototype.a = function() {}-style.

    @John: I don’t know what you’re talking about there, multiple var variables separated by commas, with or without initialisation works in all browsers.

  6. @Laurens Turns out that it was an unrelated error that had not occurred until I tried this out. The vars trick works just fine in IE6+ for me now.