When some people still focus on documentation, I tend to slip on saying that it’s not that important.
“Working software over comprehensive documentation”
Most of us already know about unobtrusive JavaScript and how good it is. Maybe also about event delegation and how many listeners you are sparing with that little technique (thanks to jQuery’s closest). I’ll be a bit more generalist here and talking about writing code that enable you to test them with unit tests (using QUnit, YUI, …).
Before you think about it, yes Test Driven Development or Behavioural Driven Development (which are very close if you do the first one right) will force to you do so. If you know those, go with them but the following pitfalls might still be interesting.
Don’t use the module pattern when you really mean class.
var Foo = { init: function(state) { this.state = state; } } Foo.init(42);
How many instances of Foo
can you have on your page once initialized ? The answer is one as this represent a kind of singleton. It also means that you won’t be able to test as many instances as you want representing tons of different cases. Stick with the good ol’ way.
function Foo(state) { this.state = state; } new Foo(42);
Stay away from id’s as well for the same reason and try to use classes instead. It means no document.getElementById
within Foo
’s constructor.
Separate the content from the logic, you JavaScript module/class should be about the logic only. Strings, translations, configuration, ... should be kept outside. Giving a JSON structure as only parameter of a constructor is common and readable.
new Foo({ class: "foo", quantity: 42 });
jQuery’s extend (YUI’s ..., Prototype ...) offer a good way to mix good default values with configuration.
Next one is loose coupling. Being sure that a module what work as well alone or when it has to interact with many other ones is key when building big and complexe systems.
The involved technique is to rely on an event mechanism. On a very safe web environment (like Opera widgets, Pre application, Apple dashboard, …), DOM3 events can be used. You only have be tied to a DOM node to fire them. YUI implements an easy to use Observer pattern (called CustomEvent in YUI2), jQuery offers something similar which integrates with how it manages DOM events (Prototype as well).
// b will send data to a var a = new A(); var b = new B(a); // or var a = new A(); var b = new B(); a.onChange(b.onChanged, b);
Those are very similar, thus it seems easier to adapt, test or reuse. Isn’t it?terminal
And last but not least, don’t put your init in the libraries/modules/… Anything that involves onload
, DOMContentReady
, … is tied to a particular usage already and shouldn’t live into a library or module imho.
function A(element) { // whatever } $(document).ready(function() { new A($("#a")[0]); });
It means that those two blocks of code should live separately. At last in your developement environment. Then, you’re totally free to join, compress and maybe obfuscate them as you won’t test or develop against that version.
And it’s more a personal taste issue here. I don’t like stuff that are automagically loaded because of a particular class name or id.
If you see more of them, feel free to contribute.