Introduction

Hey there, so this is the first article about things I've been putting to good use code-wise. Like a lot of developers I learn by doing, but I also learn from other, more experienced developers where I can. Over the past few months I've been spending more time than ever with the Canvas tag, WebGL and JavaScript in general and I thought it would be fun to compile some of the things I've learned recently as well as a few tricks I've known for some time. Some of them are very specific, some of them are broad and they range in how complex they are so hopefully everyone will find something they like!

1. Prototype it

Let's start with an easy one. So you have a great idea for an experiment. Do a quick prototype of the most complex part of it to see whether the tech can stand up to it. WebGL, for example, is really powerful since it hooks straight into the GPU, but don't forget it's being accessed from the JavaScript engine which will be much slower than your graphics card. Your great idea might be undermined by something as simple as that

2. Use three.js for 3D

Like my good friend Hakim, I'm all for understanding the underlying technology that you're using. I think it's important to know how the layer underneath what you're doing is going about things. With that said, however, for 3D, three.js takes away so many headaches for you so use it! It can be used with a Canvas renderer, a WebGL renderer and an SVG renderer so you should be able to find something that suits your requirements.

3. Avoid setInterval

This is a really important point for anyone doing any animation in their JavaScript. Why is it a problem? If you're calling something every 20ms with setInterval, but what you're calling takes longer the browser doesn't care, it's going to start the next call before your first one is complete. Instead you should use, at least, setTimeout to call your function. At the end of it you set the timeout for the next call and so on.

In reality there's a new-but-half-implemented function called requestAnimationFrame which is just brilliant. It acts pretty much like the setTimeout save for the fact that it doesn't run for tabs out of focus (saving battery life, for example, on mobile devices) and it is native to the browser so it can schedule it when it's best. For more info and a super useful snippet check out Paul Irish's blog.

4. Go backwards

This is a pretty basic optimization you can make to your loops if you're not doing so already. Go backwards, and use while loops. So this: for(var a = 0; a < arr.length; a++) {
  // do something
}
is slower than // assumes arr exists ;)
var aLength = arr.length;

while(aLength--) {
  // do something
}
Now admittedly you might not save much, it really depends what you're doing inside of those loops, but if you're trying to squeeze out the last bit of performance from a Canvas / WebGL experiment it can be an easy win.

To be honest the main speed increase in the above is likely due to the caching of the array length. You could (and really should) actually take a look at JSPerf to really get an understanding of this and other JavaScript performance factors.

5. Use images

It's really tempting to draw things in Canvas particularly using the built in drawing methods. Where possible, however, you should really look to see if you can use images because it can drastically improve performance. For certain effects like shadows and blurs you may well have to do it in any case, but keep an eye for anything else you can do.

6. Cache me if you can

This is something I've been doing a lot of in my WebGL experiments. You really want to avoid getting references to variables, objects or, in fact, anything you can during your main loops. For that reason it's totally worth caching up your objects or vertices so you can access them really quickly when you're animating.

7. Stop selection

I love this little snippet for anything involving the Canvas or WebGL: // stop the user getting a
// text cursor
document.onselectstart = function() {
  return false;
};
You might want to do that on your Canvas rather than the document. I've just included the one I use for my WebGL ones that take up most of the screen.

8. Avoid JavaScript based CSS

It's super easy to start stacking up CSS calls in your JavaScript, especially if you use jQuery: $("#someid").css({
  position: 'relative',
  height: '30px',
  width: '300px',
  backgroundColor: '#A020F0'
});
The problem is that after a while your JavaScript is awash with all these random chunks of CSS, but you're also applying your CSS via the .css files and potentially things can be difficult to debug. It's much better, where you can, to use classes and only use JavaScript to manipulate the values you can't determine ahead of time.

9. Callbacks in an object

I love this one, and I definitely didn't think it up myself, but it's so neat and tidy. If you have a load of callbacks going on you may be used to doing them inline like this: $("#someid").click(function() {

  // guts of the callback

  /* returning false
   * in a jQuery callback stops
   * propagation and prevents
   * the default behaviour
   */

  return false;

});
or alternatively just hooking a loose function from your code like this: $("#someid").click(mySuperFunction);

function mySuperFunction(event) {
  // more epic things happen here
  return false;
}
There are a couple of problems with these approaches. With the first type it becomes difficult to unbind the function later on if you need to. Sure you can unbind all click handlers, for example, but you may have a few attached and really you just want to drop that one. With the second it's just a maintainability issue - it's harder if that function is hidden away amongst the rest of your code. Instead consider doing this kind of thing: $("#someid")
  .click(callbacks.mySuperFunction);

// all my callbacks are
// in this object
var callbacks = {

  mySuperFunction:function(event) {
    // more epic things happen here
    return false;
  }
}

// and later on...
$("#someid").unbind('click',
  callbacks.mySuperFunction);
It's neat and tidy and it avoids both of the above issues.

10. The long ternary if-statement

I totally learned this one from Paul Irish in his 11 More Things I Learned From the jQuery Source video. And it's super handy if, like me, you like the ternary if-statement. So I'm used to something like this: // depending on a's value
// numberBasedOnA will be 200
// or 38. Lovely.
var numberBasedOnA =
  a > 5 ? 200 : 38;
But what if you need to be, like, do this if the value is this, and this if it's more, and this if it's even more. You know the kind of thing? Yes, well in that case the long ternary is amazing: // now check this out...
var numberBasedOnA =
  a < 5 ? 200 :
  a < 7 ? 38 :
  a < 11 ? 15 :
  a < 15 ? 49 :
  64;

// effectively 64 is like a default case
// when a >=15