Our javascript style conventions inherit from our Java style conventions in spirit, but vary in several key places because javascript is not Java.
Table of Contents | ||||||
---|---|---|---|---|---|---|
|
for in loops
Always include hasOwnProperty tests. You may deviate from the bracing rules for this one case, as in:
Code Block | ||||
---|---|---|---|---|
| ||||
for (var name in object) if (object.hasOwnProperty(name)) { // code goes here } |
Reasoning: Any modifications to Object.prototype will result in those properties showing up as iterable properties.
Dictionaries / Maps / Associative Arrays.
Always use raw primitive objects ({}).
Reasoning: Memory consumption, clarity, consistency.
Arrays
Always use the array literal constructor [], unless creating an empty array with pre-allocated size for some reason.
Reasoning: The array constructor is overloaded, and passing a single argument yields an empty array of length n rather than a single-element array containing n.
Blocks
Javascript does not support any block scope other than function level. Because of this, you should actually declare variables as close to the top of the function as possible rather than within the block.
Consider this:
Code Block | ||||
---|---|---|---|---|
| ||||
for (var i = 0; i < 10; ++i) { var foo; if (i === 1) { foo = "hello"; } document.write(foo); } |
This actually produces "hello" 9 times rather than just once as you might expect.
Reasoning: Subtle bugs, performance.
Closures
Use them liberally, especially when designing public interfaces.
Reasoning: Closures are the best mechanism available to enforce API contracts within javascript
Beware of memory leaks. Avoid referencing dom elements in short-lived closures.
Instead of this:
Code Block | ||||
---|---|---|---|---|
| ||||
var obj = document.getElementById("foo"); obj.onclick = function(){}; |
Use this:
Code Block | ||||
---|---|---|---|---|
| ||||
document.getElementById("foo").onclick = function(){}; |
Reasoning: Internet explorer 6 does a poor job of resolving dom references in closures when doing garbage collection, so this will almost always yield a memory leak.
Naming
Package names all in lower case.
Reasoning: Consistency, readability.
Constructors and "Enums" with leading caps (ClassName, EnumName)
Reasoning: Consistency, readability.
Local, closure, and public variable names camel cased, with leading lower case (variableName, variable)
Reasoning: Consistency, readability.
"private" members that are publicly visible: Use a trailing underscore (foo.prototype.privateFunction_ = function())
Reasoning: Consistency, Readability, clearly specifies API contract.
for loops
Avoid tests in the second conditional. Acceptable styles are as follows:
Code Block | ||||
---|---|---|---|---|
| ||||
for (var i = 0, j = obj.length; i < j; ++i) for (var i = 0, data; data = obj[i]; ++i) for (var i = obj.length - 1; i >=0; --i) |
Unacceptable:
Code Block | ||||
---|---|---|---|---|
| ||||
for (var i = 0; i < obj.length; i++) |
Reasoning: Performance
Prototype
Don't break the existing prototype if you can avoid it. Generally, augment your objects as follows:
Code Block | ||||
---|---|---|---|---|
| ||||
MyObject.prototype = { }; |
or
Code Block | ||||
---|---|---|---|---|
| ||||
MyObject.prototype.someFunction = function() { }; |
Semicolons
Always required in assignment (including return statements). For example:
Code Block | ||||
---|---|---|---|---|
| ||||
return foo; return function(){}; myObj.prototype.foo = function(){}; |
Reasoning: Compiler / minifier compatibility, subtle bugs.
Property access
Prefer dot notation when possible.
Reasoning: Clarity, code size.
Comments
We follow JSDoc commenting guidelines, which in turn inherit from Javadoc. Adhere to the Java Style guide for your javascript code.
Reasoning: Consistency, Readability.
Variable number of arguments
Functions that take a variable number of arguments should specify that this is the case by declaring a final, unused argument named var_args.
Reasoning: Consistency, Readability.
Optional arguments
Prefix with opt_.
Reasoning: Consistency, Readability.
Never use global scope
Always declare variables with var.
Reasoning: global pollution, subtle bugs.
Never use wrapper objects.
This includes String, Object, Array, Boolean, and Number
Reasoning: Performance, Consistency, Subtle bugs (see array comments)
Eval
Never use it. For JSON, use gadgets.json.parse
Reasoning: security vulnerabilities, performance, bugs.
Long strings.
Always concatenate using arrays.
Code Block | ||||
---|---|---|---|---|
| ||||
var myLongString = ["Hello, ", userId, ". How are you?"].join(""); |
instead of
Code Block | ||||
---|---|---|---|---|
| ||||
var myLongString = "Hello, " + userId + ". How are you?"; |
Reasoning: Performance.
Note: Certain future JS compilation tools might eliminate this requirement, but for now stick with it.
Never use slash notation for continuations. This means you should not do this:
Code Block | ||||
---|---|---|---|---|
| ||||
var myString = "Hello, this is a long string \ isn't it cool?"; |
Reasoning: Minification will break this.
Alternative: Use array concatenation, or violate the 80-column rule if the string is only a little over the limit.