User:Avarma/Coding Style
Contents
Introduction
My JavaScript coding style is generally a compromise between the Mozilla JavaScript Style Guide, the vagaries of what js2-mode happens to be compatible with, and my own personal tastes. It's intended for use with any kind of JS code, whether it be in a Firefox extension, Web content, or something else.
Because I started the Jetpack and Ubiquity projects, much of their code happens to conform to this style.
Comments
Comments are always C++-style, starting with a //. This is partly because:
- It's hard to remember how to format C-style (/* */) lines consistently,
- Emacs constantly gets confused with C-style comments because there's so many different styles of using them,
- Virtually all other programming languages use a minor variation on C-style comments, e.g. using # as the comment prefix instead of //, making it easy to convert common comment code (e.g. license blocks) from one language to another,
- C++-style comments can easily be nested, while C-style comments cannot.
Furthermore, the comments before functions or sections of code are usually commented using WikiCreole syntax, so as to be compatible with Code Illuminated.
Whitespace, Line Length, and Indentation
I follow the conventions laid out in the Mozilla JS style guide.
In particular, I am pretty hardcore about making sure that lines are never longer than 79 characters, and I never use tabs.
Annoyances
Ideally, I'd like to indent code like this:
setInterval(function() { doThing() }, 1000);
But js2-mode doesn't like it, so I do this:
setInterval( function() { doThing() }, 1000);
Similarly, I can't do this with js2-mode:
jQuery.ajax({ url: "blah.txt", method: "GET" });
So I have to settle with this:
jQuery.ajax( {url: "blah.txt" method: "GET" });
There's a number of other such indentation annoyances that I have to navigate around because I use js2-mode, but in general I find that the editing mode solves a lot more problems for me than it creates, so I live with it.
If and when either js2-mode changes to support better indentation or I switch to a different editor, these annoyances should go away.
Brackets
Being a fan of Python, I feel that brackets detract from readability so I don't use them when I don't have to, e.g.:
if (x > 1) doThing();
A decent editor that supports auto-indentation will help ensure that you don't accidentally modify the code such that the semantics deviate from what the indentation implies:
if (x > 1) doThing(); doOtherThing();
Variable Naming
I do prefix all global variables with g.
I don't prefix all function parameters with a.
Private Variables, Methods, and Closures
It's up to the discretion of the author regarding whether to make private variables/methods "publicly visible" but prefixed with an underscore (_) character, or to contain them in closures. Both have different runtime characteristics, so neither strategy should be followed blindly. Here's some things to keep in mind:
- Data contained in closures is actually private, which is used by some frameworks like Google Caja to enforce privacy when trusted code interoperates with untrusted code.
- Code written using closures tends to be more concise and involve less breakage of DRY than code that doesn't use closures.
- It's very easy to accidentally create memory leaks when using closures.
- When there's several levels of lexical scope involved in a block of code, reading the code can become confusing.
- It becomes easier to accidentally introduce bugs into code when the lifetime of a scoped variable is misunderstood. This becomes particularly easy when the code in question uses var instead of let.
- It's either very difficult or impossible to write unit tests for code that lives inside a closure, or introspect into data contained within a closure when debugging.
- Code living in a closure is usually duplicated for each instance of the closure that exists, so objects whose private methods are contained in closures often use more memory than objects whose private methods are prefixed with _ and attached to their prototype.
- Public methods that are contained in closures are usually "detachable" from their parent object in ways that prototype methods aren't, due to the semantics of this.