styleguide/javascriptguide.xml

3167 lines
114 KiB
XML
Raw Normal View History

2010-07-13 06:02:20 +08:00
<?xml version = '1.0'?>
<?xml-stylesheet type="text/xsl" href="styleguide.xsl"?>
<GUIDE title="Google JavaScript Style Guide">
<p class="revision">
Revision 2.9
2010-07-13 06:02:20 +08:00
</p>
<address>
Aaron Whyte<br/>
Bob Jervis<br/>
Dan Pupius<br/>
Eric Arvidsson<br/>
Fritz Schneider<br/>
Robby Walker<br/>
</address>
<OVERVIEW>
<CATEGORY title="Important Note">
<STYLEPOINT title="Displaying Hidden Details in this Guide">
<SUMMARY>
This style guide contains many details that are initially
hidden from view. They are marked by the triangle icon, which you
see here on your left. Click it now.
You should see "Hooray" appear below.
</SUMMARY>
<BODY>
<p>
Hooray! Now you know you can expand points to get more
details. Alternatively, there's a "toggle all" at the
top of this document.
</p>
</BODY>
</STYLEPOINT>
</CATEGORY>
<CATEGORY title="Background">
<p>
JavaScript is the main client-side scripting language used
by many of Google's open-source
projects.
This style guide is a list of <em>do</em>s and <em>don't</em>s for
JavaScript programs.
</p>
</CATEGORY>
</OVERVIEW>
<CATEGORY title="JavaScript Language Rules">
<STYLEPOINT title="var">
<SUMMARY>
Declarations with <code>var</code>: Always
</SUMMARY>
<BODY>
<DECISION>
When you fail to specify <code>var</code>,
the variable gets placed in the global context, potentially clobbering
existing values. Also, if there's no declaration, it's hard to tell in
what scope a variable lives (e.g., it could be in the Document or
Window just as easily as in the local scope). So always declare with
<code>var</code>.
</DECISION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Constants">
<SUMMARY>
&gt;Use <code>NAMES_LIKE_THIS</code> for constants.
Use <code>@const</code> where appropriate.
Never use the <code>const</code> keyword.
</SUMMARY>
<BODY>
<DECISION>
<p>For simple primitive value constants, the naming convention is
enough.</p>
<CODE_SNIPPET>
/**
* The number of seconds in a minute.
* @type {number}
*/
goog.example.SECONDS_IN_A_MINUTE = 60;
</CODE_SNIPPET>
<p>For non-primitives, use the <code>@const</code> annotation.</p>
<CODE_SNIPPET>
/**
* The number of seconds in each of the given units.
* @type {Object.&lt;number&gt;}
* @const
*/
goog.example.SECONDS_TABLE = {
minute: 60,
hour: 60 * 60
day: 60 * 60 * 24
}
</CODE_SNIPPET>
<p>This allows the compiler to enforce constant-ness.</p>
<p>As for the <code>const</code> keyword, Internet Explorer doesn't
parse it, so don't use it.</p>
</DECISION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Semicolons">
<SUMMARY>
Always use semicolons.
</SUMMARY>
<BODY>
<p>Relying on implicit insertion can cause subtle, hard to debug
problems. Don't do it. You're better than that.</p>
<p>There are a couple places where missing semicolons are particularly
dangerous:</p>
<BAD_CODE_SNIPPET>
// 1.
MyClass.prototype.myMethod = function() {
return 42;
} // No semicolon here.
(function() {
// Some initialization code wrapped in a function to create a scope for locals.
})();
var x = {
'i': 1,
'j': 2
} // No semicolon here.
// 2. Trying to do one thing on Internet Explorer and another on Firefox.
// I know you'd never write code like this, but throw me a bone.
[normalVersion, ffVersion][isIE]();
var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // No semicolon here.
// 3. conditional execution a la bash
-1 == resultOfOperation() || die();
</BAD_CODE_SNIPPET>
<SUBSECTION title="So what happens?">
<ol>
<li>JavaScript error - first the function returning 42 is called
with the second function as a parameter, then the number 42 is
"called" resulting in an error.</li>
<li>You will most likely get a 'no such property in undefined'
error at runtime as it tries to call
<code>x[ffVersion][isIE]()</code>.</li>
<li><code>die</code> is called unless
<code>resultOfOperation()</code> is <code>NaN</code> and
<code>THINGS_TO_EAT</code> gets assigned the result of
<code>die()</code>.</li>
</ol>
</SUBSECTION>
<SUBSECTION title="Why?">
<p>JavaScript requires statements to end with a semicolon,
except when it thinks it can safely infer their existence. In each
of these examples, a function declaration or object or array literal
is used inside a statement. The closing brackets are not enough to
signal the end of the statement. Javascript never ends a statement
if the next token is an infix or bracket operator.</p>
<p>This has really surprised people, so make sure your assignments end
with semicolons.</p>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Nested functions">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>Nested functions can be very useful, for example in the creation of
continuations and for the task of hiding helper functions. Feel free
to use them.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Function Declarations Within Blocks">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Do not do this:</p>
<BAD_CODE_SNIPPET>
if (x) {
function foo() {}
}
</BAD_CODE_SNIPPET>
<p>While most script engines support Function Declarations within blocks
it is not part of ECMAScript (see
<a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262</a>,
clause 13 and 14). Worse implementations are inconsistent with each
other and with future EcmaScript proposals. ECMAScript only allows for
Function Declarations in the root statement list of a script or
function. Instead use a variable initialized with a Function
Expression to define a function within a block:</p>
<CODE_SNIPPET>
if (x) {
var foo = function() {}
}
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
2010-07-13 06:02:20 +08:00
<STYLEPOINT title="Exceptions">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>You basically can't avoid exceptions if you're doing something
non-trivial (using an application development framework, etc.).
Go for it.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Custom exceptions">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>Without custom exceptions, returning error information from a
function that also returns a value can be tricky, not to mention
inelegant. Bad solutions include passing in a reference type to hold
error information or always returning Objects with a potential
error member. These basically amount to a primitive exception
handling hack. Feel free to use custom exceptions when
appropriate.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Standards features">
<SUMMARY>Always preferred over non-standards features</SUMMARY>
<BODY>
<p>For maximum portability and compatibility, always prefer standards
features over non-standards features (e.g.,
<code>string.charAt(3)</code> over <code>string[3]</code> and element
access with DOM functions instead of using an application-specific
shorthand).</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Wrapper objects for primitive types">
<SUMMARY>No</SUMMARY>
<BODY>
<p>There's no reason to use wrapper objects for primitive types, plus
they're dangerous:</p>
<BAD_CODE_SNIPPET>
var x = new Boolean(false);
if (x) {
alert('hi'); // Shows 'hi'.
}
</BAD_CODE_SNIPPET>
<p>Don't do it!</p>
<p>However type casting is fine.</p>
<CODE_SNIPPET>
var x = Boolean(0);
if (x) {
alert('hi'); // This will never be alerted.
}
typeof Boolean(0) == 'boolean';
typeof new Boolean(0) == 'object';
</CODE_SNIPPET>
<p>This is very useful for casting things to
<code>number</code>, <code>string</code> and <code>boolean</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Multi-level prototype hierarchies">
<SUMMARY>Not preferred</SUMMARY>
<BODY>
<p>Multi-level prototype hierarchies are how JavaScript implements
inheritance. You have a multi-level hierarchy if you have a
user-defined class D with another user-defined class B as its
prototype. These hierarchies are much harder to get right than they
first appear! </p>
<p>For that reason, it is best to use <code>goog.inherits()</code> from
<a href="http://code.google.com/closure/library/">
the Closure Library
</a>
or something similar.
</p>
<CODE_SNIPPET>
function D() {
goog.base(this)
}
goog.inherits(D, B);
D.prototype.method = function() {
...
};
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Method definitions">
<SUMMARY><code>Foo.prototype.bar = function() { ... };</code></SUMMARY>
<BODY>
<p>While there are several methods for attaching methods and
properties to a constructor, the preferred style is:</p>
<CODE_SNIPPET>
Foo.prototype.bar = function() {
/* ... */
};
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Closures">
<SUMMARY>Yes, but be careful.</SUMMARY>
<BODY>
<p>The ability to create closures is perhaps the most useful and often
overlooked feature of JS. Here is
<a href="http://jibbering.com/faq/faq_notes/closures.html">
a good description of how closures work
</a>.</p>
<p>One thing to keep in mind, however, is that a closure keeps a pointer
to its enclosing scope. As a result, attaching a closure to a DOM
element can create a circular reference and thus, a memory leak. For
example, in the following code:</p>
<BAD_CODE_SNIPPET>
function foo(element, a, b) {
element.onclick = function() { /* uses a and b */ };
}
</BAD_CODE_SNIPPET>
<p>the function closure keeps a reference to <code>element</code>,
<code>a</code>, and <code>b</code> even if it never uses
<code>element</code>. Since <code>element</code> also keeps a
reference to the closure, we have a cycle that won't be cleaned up by
garbage collection. In these situations, the code can be structured
as follows:</p>
<CODE_SNIPPET>
function foo(element, a, b) {
element.onclick = bar(a, b);
}
function bar(a, b) {
return function() { /* uses a and b */ }
}
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="eval()">
<SUMMARY>
Only for deserialization (e.g. evaluating RPC responses)
</SUMMARY>
<BODY>
<p><code>eval()</code> makes for confusing semantics and is dangerous
to use if the string being <code>eval()</code>'d contains user input.
There's usually a better, more clear, safer way to write your code, so
its used is generally not permitted. However <code>eval</code> makes
deserialization considerably easier than the non-<code>eval</code>
alternatives, so its use is acceptable for this task (for example, to
evaluate RPC responses).</p>
<p>Deserialization is the process of transforming a series of bytes into
an in-memory data structure. For example, you might write objects out
to a file as:</p>
<CODE_SNIPPET>
users = [
{
name: 'Eric',
id: 37824,
email: 'jellyvore@myway.com'
},
{
name: 'xtof',
id: 31337,
email: 'b4d455h4x0r@google.com'
},
...
];
</CODE_SNIPPET>
<p>Reading these data back into memory is as simple as
<code>eval</code>ing the string representation of the file.</p>
<p>Similarly, <code>eval()</code> can simplify decoding RPC return
values. For example, you might use an <code>XMLHttpRequest</code>
to make an RPC, and in its response the server can return
JavaScript:</p>
<CODE_SNIPPET>
var userOnline = false;
var user = 'nusrat';
var xmlhttp = new XMLHttpRequest();
xmlhttp.open('GET', 'http://chat.google.com/isUserOnline?user=' + user, false);
xmlhttp.send('');
// Server returns:
// userOnline = true;
if (xmlhttp.status == 200) {
eval(xmlhttp.responseText);
}
// userOnline is now true.
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="with() {}">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Using <code>with</code> clouds the semantics of your program.
Because the object of the <code>with</code> can have properties that
collide with local variables, it can drastically change the meaning
of your program. For example, what does this do?</p>
<BAD_CODE_SNIPPET>
with (foo) {
var x = 3;
return x;
}
</BAD_CODE_SNIPPET>
<p>Answer: anything. The local variable <code>x</code> could be
clobbered by a property of <code>foo</code> and perhaps it even has
a setter, in which case assigning <code>3</code> could cause lots of
other code to execute. Don't use <code>with</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="this">
<SUMMARY>
Only in object constructors, methods, and in setting up closures
</SUMMARY>
<BODY>
<p>The semantics of <code>this</code> can be tricky. At times it refers
to the global object (in most places), the scope of the caller (in
<code>eval</code>), a node in the DOM tree (when attached using an
event handler HTML attribute), a newly created object (in a
constructor), or some other object (if function was
<code>call()</code>ed or <code>apply()</code>ed).</p>
<p>Because this is so easy to get wrong, limit its use to those places
where it is required:</p>
<ul>
<li>in constructors</li>
<li>in methods of objects (including in the creation of closures)</li>
</ul>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="for-in loop">
<SUMMARY>
Only for iterating over keys in an object/map/hash
</SUMMARY>
<BODY>
<p><code>for-in</code> loops are often incorrectly used to loop over
the elements in an <code>Array</code>. This is however very error
prone because it does not loop from <code>0</code> to
<code>length - 1</code> but over all the present keys in the object
and its prototype chain. Here are a few cases where it fails:</p>
<BAD_CODE_SNIPPET>
function printArray(arr) {
for (var key in arr) {
print(arr[key]);
}
}
printArray([0,1,2,3]); // This works.
var a = new Array(10);
printArray(a); // This is wrong.
a = document.getElementsByTagName('*');
printArray(a); // This is wrong.
a = [0,1,2,3];
a.buhu = 'wine';
printArray(a); // This is wrong again.
a = new Array;
a[3] = 3;
printArray(a); // This is wrong again.
</BAD_CODE_SNIPPET>
<p>Always use normal for loops when using arrays.</p>
<CODE_SNIPPET>
function printArray(arr) {
var l = arr.length;
for (var i = 0; i &lt; l; i++) {
print(arr[i]);
}
}
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Associative Arrays">
<SUMMARY>
Never use <code>Array</code> as a map/hash/associative array
</SUMMARY>
<BODY>
<p>Associative <code>Array</code>s are not allowed... or more precisely
you are not allowed to use non number indexes for arrays. If you need
a map/hash use <code>Object</code> instead of <code>Array</code> in
these cases because the features that you want are actually features
of <code>Object</code> and not of <code>Array</code>.
<code>Array</code> just happens to extend <code>Object</code> (like
any other object in JS and therefore you might as well have used
<code>Date</code>, <code>RegExp</code> or <code>String</code>).</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Multiline string literals">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Do not do this:</p>
<BAD_CODE_SNIPPET>
var myString = 'A rather long string of English text, an error message \
actually that just keeps going and going -- an error \
message to make the Energizer bunny blush (right through \
those Schwarzenegger shades)! Where was I? Oh yes, \
you\'ve got an error and all the extraneous whitespace is \
just gravy. Have a nice day.';
</BAD_CODE_SNIPPET>
<p>The whitespace at the beginning of each line can't be safely stripped
at compile time; whitespace after the slash will result in tricky
errors; and while most script engines support this, it is not part
of ECMAScript. </p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Array and Object literals">
<SUMMARY>Yes</SUMMARY>
<BODY>
<p>Use <code>Array</code> and <code>Object</code> literals instead of
<code>Array</code> and <code>Object</code> constructors.</p>
<p>Array constructors are error-prone due to their arguments.</p>
<BAD_CODE_SNIPPET>
// Length is 3.
var a1 = new Array(x1, x2, x3);
// Length is 2.
var a2 = new Array(x1, x2);
// If x1 is a number and it is a natural number the length will be x1.
// If x1 is a number but not a natural number this will throw an exception.
// Otherwise the array will have one element with x1 as its value.
var a3 = new Array(x1);
// Length is 0.
var a4 = new Array();
</BAD_CODE_SNIPPET>
<p>Because of this, if someone changes the code to pass 1 argument
instead of 2 arguments, the array might not have the expected
length.</p>
<p>To avoid these kinds of weird cases, always use the more readable
array literal.</p>
<CODE_SNIPPET>
var a = [x1, x2, x3];
var a2 = [x1, x2];
var a3 = [x1];
var a4 = [];
</CODE_SNIPPET>
<p>Object constructors don't have the same problems, but for readability
and consistency object literals should be used.</p>
<BAD_CODE_SNIPPET>
var o = new Object();
var o2 = new Object();
o2.a = 0;
o2.b = 1;
o2.c = 2;
o2['strange key'] = 3;
</BAD_CODE_SNIPPET>
<p>Should be written as:</p>
<CODE_SNIPPET>
var o = {};
var o2 = {
a: 0,
b: 1,
c: 2,
'strange key': 3
};
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Modifying prototypes of builtin objects">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Modifying builtins like <code>Object.prototype</code> and
<code>Array.prototype</code> are strictly forbidden. Modifying other
builtins like <code>Function.prototype</code> is less dangerous but
still leads to hard to debug issues in production and should be
avoided.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Internet Explorer's Conditional Comments">
<SUMMARY>No</SUMMARY>
<BODY>
<p>Don't do this:</p>
<CODE_SNIPPET>
var f = function () {
/*@cc_on if (@_jscript) { return 2* @*/ 3; /*@ } @*/
};
</CODE_SNIPPET>
<p>Conditional Comments hinder automated tools as they can vary the
JavaScript syntax tree at runtime.</p>
</BODY>
</STYLEPOINT>
2010-07-13 06:02:20 +08:00
</CATEGORY>
<CATEGORY title="JavaScript Style Rules">
<STYLEPOINT title="Naming">
<SUMMARY>
<p>In general, use <code>functionNamesLikeThis</code>,
<code>variableNamesLikeThis</code>, <code>ClassNamesLikeThis</code>,
<code>EnumNamesLikeThis</code>, <code>methodNamesLikeThis</code>,
and <code>SYMBOLIC_CONSTANTS_LIKE_THIS</code>.</p>
<p>Expand for more information.</p>
</SUMMARY>
<BODY>
<SUBSECTION title="Properties and methods">
<ul>
<li><em>Private</em> properties, variables, and methods (in files
or classes) should be named with a trailing
underscore.
</li>
<li><em>Protected</em> properties, variables, and methods should be
named without a trailing underscore (like public ones).</li>
</ul>
<p>For more information on <em>private</em> and <em>protected</em>,
read the section on
<a href="#Visibility__private_and_protected_fields_">
visibility
</a>.</p>
</SUBSECTION>
<SUBSECTION title="Method and function parameter">
<p>Optional function arguments start with <code>opt_</code>.</p>
<p>Functions that take a variable number of arguments should have the
last argument named <code>var_args</code>. You may not refer to
<code>var_args</code> in the code; use the <code>arguments</code>
array.</p>
<p>Optional and variable arguments can also be specified in
<code>@param</code> annotations. Although either convention is
acceptable to the compiler, using both together is preferred.</p>
</SUBSECTION>
<SUBSECTION title="Getters and Setters">
<p>Getters and setters for properties are not required. However, if
they are used, then getters must be named <code>getFoo()</code> and
setters must be named <code>setFoo(value)</code>. (For boolean
getters, <code>isFoo()</code> is also acceptable, and often sounds
more natural.)</p>
</SUBSECTION>
<SUBSECTION title="Namespaces">
<p>JavaScript has no inherent packaging or namespacing support.</p>
<p>Global name conflicts are difficult to debug, and can cause
intractable problems when two projects try to integrate. In order
to make it possible to share common JavaScript code, we've adopted
conventions to prevent collisions. </p>
<SUBSUBSECTION title="Use namespaces for global code">
<p><em>ALWAYS</em> prefix identifiers in the global scope with a
unique pseudo namespace related to the project or library. If you
are working on "Project Sloth", a reasonable pseudo namespace
would be <code>sloth.*</code>.</p>
<CODE_SNIPPET>
var sloth = {};
sloth.sleep = function() {
...
};
</CODE_SNIPPET>
<p>Many JavaScript libraries, including
<a href="http://code.google.com/closure/library/">
the Closure Library
</a>
and
<a href="http://www.dojotoolkit.org/">
Dojo toolkit
</a>
give you high-level functions for declaring your namespaces.
Be consistent about how you declare your namespaces.</p>
<CODE_SNIPPET>
goog.provide('sloth');
sloth.sleep = function() {
...
};
</CODE_SNIPPET>
</SUBSUBSECTION>
<SUBSUBSECTION title="Respect namespace ownership">
<p>When choosing a child-namespace, make sure that the owners of the
parent namespace know what you are doing. If you start a project
that creates hats for sloths, make sure that the Sloth team knows
that you're using <code>sloth.hats</code>.</p>
</SUBSUBSECTION>
<SUBSUBSECTION title="Use different namespaces for external code and internal code">
<p>"External code" is code that comes from outside your codebase,
and is compiled independently. Internal and external names should
be kept strictly separate. If you're using an external library
that makes things available in <code>foo.hats.*</code>, your
internal code should not define all its symbols in
<code>foo.hats.*</code>, because it will break if the other
team defines new symbols.</p>
<BAD_CODE_SNIPPET>
foo.require('foo.hats');
/**
* WRONG -- Do NOT do this.
* @constructor
* @extend {foo.hats.RoundHat}
*/
foo.hats.BowlerHat = function() {
};
</BAD_CODE_SNIPPET>
<p>If you need to define new APIs on an external namespace, then you
should explicitly export the public API functions, and only those
functions. Your internal code should call the internal APIs by
their internal names, for consistency and so that the compiler
can optimize them better.</p>
<CODE_SNIPPET>
foo.provide('googleyhats.BowlerHat');
foo.require('foo.hats');
/**
* @constructor
* @extend {foo.hats.RoundHat}
*/
googleyhats.BowlerHat = function() {
...
};
goog.exportSymbol('foo.hats.BowlerHat', googleyhats.BowlerHat);
</CODE_SNIPPET>
</SUBSUBSECTION>
<SUBSUBSECTION title="Alias long type names to improve readability">
<p>Use local aliases for fully-qualified types if doing so improves
readability. The name of a local alias should match the last part
of the type.</p>
<CODE_SNIPPET>
/**
* @constructor
*/
some.long.namespace.MyClass = function() {
};
/**
* @param {some.long.namespace.MyClass} a
*/
some.long.namespace.MyClass.staticHelper = function(a) {
...
};
myapp.main = function() {
var MyClass = some.long.namespace.MyClass;
var staticHelper = some.long.namespace.MyClass.staticHelper;
staticHelper(new MyClass());
};
</CODE_SNIPPET>
<p>Do not alias namespaces.</p>
<BAD_CODE_SNIPPET>
myapp.main = function() {
var namespace = some.long.namespace;
namespace.MyClass.staticHelper(new namespace.MyClass());
};
</BAD_CODE_SNIPPET>
<p>Avoid accessing properties of an aliased type, unless it is an
enum.</p>
<CODE_SNIPPET>
/** @enum {string} */
some.long.namespace.Fruit = {
APPLE: 'a',
BANANA: 'b'
};
myapp.main = function() {
var Fruit = some.long.namespace.Fruit;
switch (fruit) {
case Fruit.APPLE:
...
case Fruit.BANANA:
...
}
};
</CODE_SNIPPET>
<BAD_CODE_SNIPPET>
myapp.main = function() {
var MyClass = some.long.namespace.MyClass;
MyClass.staticHelper(null);
};
</BAD_CODE_SNIPPET>
<p>Never create aliases in the global scope. Use them only in
function blocks.</p>
</SUBSUBSECTION>
2010-07-13 06:02:20 +08:00
</SUBSECTION>
<SUBSECTION title="Filenames">
<p>Filenames should be all lowercase in order to avoid confusion on
case-sensitive platforms. Filenames should end in <code>.js</code>,
and should contain no punctuation except for <code>-</code> or
<code>_</code> (prefer <code>-</code> to <code>_</code>).</p>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Custom toString() methods">
<SUMMARY>
Must always succeed without side effects.
</SUMMARY>
<BODY>
<p>You can control how your objects string-ify themselves by defining a
custom <code>toString()</code> method. This is fine, but you need
to ensure that your method (1) always succeeds and (2) does not have
side-effects. If your method doesn't meet these criteria, it's very
easy to run into serious problems. For example, if
<code>toString()</code> calls a method that does an
<code>assert</code>, <code>assert</code> might try to output the name
of the object in which it failed, which of course requires calling
<code>toString()</code>.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Deferred initialization">
<SUMMARY>OK</SUMMARY>
<BODY>
<p>It isn't always possible to initialize variables at the point of
declaration, so deferred initialization is fine.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Explicit scope">
<SUMMARY>Always</SUMMARY>
<BODY>
<p>Always use explicit scope - doing so increases portability and
clarity. For example, don't rely on <code>window</code> being in the
scope chain. You might want to use your function in another
application for which <code>window</code> is not the content
window.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Code formatting">
<SUMMARY>Expand for more info.</SUMMARY>
<BODY>
<p>We follow the <a href="cppguide.xml#Formatting">C++ formatting
rules</a> in spirit, with the following additional clarifications.</p>
<SUBSECTION title="Curly Braces">
<p>Because of implicit semicolon insertion, always start your curly
braces on the same line as whatever they're opening. For
example:</p>
<CODE_SNIPPET>
if (something) {
// ...
} else {
// ...
}
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Array and Object Initializers">
<p>Single-line array and object initializers are allowed when they
fit on a line:</p>
<CODE_SNIPPET>
var arr = [1, 2, 3]; // No space after [ or before ].
var obj = {a: 1, b: 2, c: 3}; // No space after { or before }.
</CODE_SNIPPET>
<p>Multiline array initializers and object initializers are indented
2 spaces, just like blocks.</p>
<CODE_SNIPPET>
// Object initializer.
var inset = {
top: 10,
right: 20,
bottom: 15,
left: 12
};
// Array initializer.
this.rows_ = [
'"Slartibartfast" &lt;fjordmaster@magrathea.com&gt;',
'"Zaphod Beeblebrox" &lt;theprez@universe.gov&gt;',
'"Ford Prefect" &lt;ford@theguide.com&gt;',
'"Arthur Dent" &lt;has.no.tea@gmail.com&gt;',
'"Marvin the Paranoid Android" &lt;marv@googlemail.com&gt;',
'the.mice@magrathea.com'
];
// Used in a method call.
goog.dom.createDom(goog.dom.TagName.DIV, {
id: 'foo',
className: 'some-css-class',
style: 'display:none'
}, 'Hello, world!');
</CODE_SNIPPET>
<p>Long identifiers or values present problems for aligned
initialization lists, so always prefer non-aligned initialization.
For example:</p>
<CODE_SNIPPET>
CORRECT_Object.prototype = {
a: 0,
b: 1,
lengthyName: 2
};
</CODE_SNIPPET>
<p>Not like this:</p>
<BAD_CODE_SNIPPET>
WRONG_Object.prototype = {
a : 0,
b : 1,
lengthyName: 2
};
</BAD_CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Function Arguments">
<p>When possible, all function arguments should be listed on the same
line. If doing so would exceed the 80-column limit, the arguments
must be line-wrapped in a readable way. To save space, you may wrap
as close to 80 as possible, or put each argument on its own line to
enhance readability. The indentation may be either four spaces, or
aligned to the parenthesis. Below are the most common patterns for
argument wrapping:</p>
<CODE_SNIPPET>
// Four-space, wrap at 80. Works with very long function names, survives
// renaming without reindenting, low on space.
goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// ...
};
// Four-space, one argument per line. Works with long function names,
// survives renaming, and emphasizes each argument.
goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
veryDescriptiveArgumentNumberOne,
veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy,
artichokeDescriptorAdapterIterator) {
// ...
};
// Parenthesis-aligned indentation, wrap at 80. Visually groups arguments,
// low on space.
function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
// ...
}
// Parenthesis-aligned, one argument per line. Visually groups and
// emphasizes each individual argument.
function bar(veryDescriptiveArgumentNumberOne,
veryDescriptiveArgumentTwo,
tableModelEventHandlerProxy,
artichokeDescriptorAdapterIterator) {
// ...
}
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Passing Anonymous Functions">
<p>When declaring an anonymous function in the list of arguments for
a function call, the body of the function is indented two spaces
from the left edge of the function call or the statement, not two
spaces from the left edge of the function keyword. This is to make
the body of the anonymous function easier to read (i.e. not be all
squished up into the right half of the screen).</p>
<CODE_SNIPPET>
var names = items.map(function(item) {
return item.name;
});
prefix.something.reallyLongFunctionName('whatever', function(a1, a2) {
if (a1.equals(a2)) {
someOtherLongFunctionName(a1);
} else {
andNowForSomethingCompletelyDifferent(a2.parrot);
}
});
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="More Indentation">
<p>In fact, except for
<a href="#Array_and_Object_literals">
array and object initializers
</a>, and passing anonymous functions, all wrapped lines
should be indented either left-aligned to the expression above, or
indented four spaces, not indented two spaces.</p>
<CODE_SNIPPET>
someWonderfulHtml = '<div class="' + getClassesForWonderfulHtml()'">' +
getEvenMoreHtml(someReallyInterestingValues, moreValues,
evenMoreParams, 'a duck', true, 72,
slightlyMoreMonkeys(0xfff)) +
'</div>';
thisIsAVeryLongVariableName =
hereIsAnEvenLongerOtherFunctionNameThatWillNotFitOnPrevLine();
thisIsAVeryLongVariableName = 'expressionPartOne' + someMethodThatIsLong() +
thisIsAnEvenLongerOtherFunctionNameThatCannotBeIndentedMore();
someValue = this.foo(
shortArg,
'Some really long string arg - this is a pretty common case, actually.',
shorty2,
this.bar());
if (searchableCollection(allYourStuff).contains(theStuffYouWant) &amp;&amp;
!ambientNotification.isActive() &amp;&amp; (client.isAmbientSupported() ||
client.alwaysTryAmbientAnyways())) {
2010-07-13 06:02:20 +08:00
ambientNotification.activate();
}
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Blank lines">
<p>Use newlines to group logically related pieces of code.
For example:</p>
<CODE_SNIPPET>
doSomethingTo(x);
doSomethingElseTo(x);
andThen(x);
nowDoSomethingWith(y);
andNowWith(z);
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Binary and Ternary Operators">
<p>Always put the operator on the preceding line, so that you don't
have to think about implicit semi-colon insertion issues. Otherwise,
line breaks and indentation follow the same rules as in other
Google style guides.</p>
<CODE_SNIPPET>
var x = a ? b : c; // All on one line if it will fit.
// Indentation +4 is OK.
var y = a ?
longButSimpleOperandB : longButSimpleOperandC;
// Indenting to the line position of the first operand is also OK.
var z = a ?
moreComplicatedB :
moreComplicatedC;
</CODE_SNIPPET>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Parentheses">
<SUMMARY>Only where required</SUMMARY>
<BODY>
<p>Use sparingly and in general only where required by the syntax
and semantics.</p>
<p>Never use parentheses for unary operators such as
<code>delete</code>, <code>typeof</code> and <code>void</code> or
after keywords such as <code>return</code>, <code>throw</code> as
well as others (<code>case</code>, in or <code>new</code>).</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Strings">
<SUMMARY>Prefer ' over "</SUMMARY>
<BODY>
<p>For consistency single-quotes (') are preferred to double-quotes (").
This is helpful when creating strings that include HTML:</p>
<CODE_SNIPPET>
var msg = 'This is <a href="http://foo">some HTML</a>';
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Visibility (private and protected fields)">
<SUMMARY>Encouraged, use JSDoc annotations <code>@private</code> and
<code>@protected</code></SUMMARY>
<BODY>
<p>We recommend the use of the JSDoc annotations <code>@private</code> and
<code>@protected</code> to indicate visibility levels for classes,
functions, and properties.</p>
<p><code>@private</code> global variables and functions are only
accessible to code in the same file.</p>
<p>Constructors marked <code>@private</code> may only be instantiated by
code in the same file and by their static and instance members.
<code>@private</code> constructors may also be accessed anywhere in the
same file for their public static properties and by the
<code>instanceof</code> operator.</p>
<p>Global variables, functions, and constructors should never be
annotated <code>@protected</code>.</p>
<CODE_SNIPPET>
// File 1.
// AA_PrivateClass_ and AA_init_ are accessible because they are global
// and in the same file.
/**
* @private
* @constructor
*/
AA_PrivateClass_ = function() {
};
/** @private */
function AA_init_() {
return new AA_PrivateClass_();
}
AA_init_();
</CODE_SNIPPET>
<p><code>@private</code> properties are accessible to all code in the
same file, plus all static methods and instance methods of that class
that "owns" the property, if the property belongs to a class. They
cannot be accessed or overridden from a subclass in a different file.</p>
2010-07-13 06:02:20 +08:00
<p><code>@protected</code> properties are accessible to all code in the
same file, plus any static methods and instance methods of any subclass
of a class that "owns" the property.</p>
<p>Note that these semantics differ from those of C++ and Java, in that
they grant private and protected access to all code in the same file,
not just in the same class or class hierarchy. Also, unlike in C++,
private properties cannot be overriden by a subclass.
</p>
2010-07-13 06:02:20 +08:00
<CODE_SNIPPET>
// File 1.
/** @constructor */
AA_PublicClass = function() {
};
/** @private */
AA_PublicClass.staticPrivateProp_ = 1;
/** @private */
AA_PublicClass.prototype.privateProp_ = 2;
/** @protected */
AA_PublicClass.staticProtectedProp = 31;
/** @protected */
AA_PublicClass.prototype.protectedProp = 4;
// File 2.
/**
* @return {number} The number of ducks we've arranged in a row.
*/
AA_PublicClass.prototype.method = function() {
// Legal accesses of these two properties.
return this.privateProp_ + AA_PublicClass.staticPrivateProp_;
};
// File 3.
/**
* @constructor
* @extends {AA_PublicClass}
*/
AA_SubClass = function() {
// Legal access of a protected static property.
AA_PublicClass.staticProtectedProp = this.method();
};
goog.inherits(AA_SubClass, AA_PublicClass);
/**
* @return {number} The number of ducks we've arranged in a row.
*/
AA_SubClass.prototype.method = function() {
// Legal access of a protected instance property.
return this.protectedProp;
};
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="JavaScript Types">
<SUMMARY>Encouraged and enforced by the compiler.</SUMMARY>
<BODY>
<p>When documenting a type in JSDoc, be as specific and accurate as
possible. The types we support are
<a href="http://wiki.ecmascript.org/doku.php?id=spec:spec">
JS2
</a>
style types and JS1.x types.</p>
<SUBSECTION title="The JavaScript Type Language">
<p>The JS2 proposal contained a language for specifying JavaScript
types. We use this language in JsDoc to express the types of
function parameters and return values.</p>
<p>As the JS2 proposal has evolved, this language has changed. The
compiler still supports old syntaxes for types, but those syntaxes
are deprecated.</p>
<table border="1" style="border-collapse:collapse" cellpadding="4">
<thead>
<tr>
<th>Operator Name</th>
<th>Syntax</th>
<th>Description</th>
<th>Deprecated Syntaxes</th>
</tr>
</thead>
<tbody>
<tr>
<td>Type Name</td>
<td>
<code>{boolean}</code>, <code>{Window}</code>,
<code>{goog.ui.Menu}</code>
</td>
<td>Simply the name of a type.</td>
<td/>
</tr>
<tr>
<td>Type Application</td>
<td>
<code>{Array.&lt;string&gt;}</code><br/>An array of strings.<p/>
<code>{Object.&lt;string, number&gt;}</code>
<br/>An object in which the keys are strings and the values
are numbers.
</td>
<td>Patameterizes a type, by applying a set of type arguments
to that type. The idea is analogous to generics in Java.
</td>
<td/>
</tr>
<tr>
<td>Type Union</td>
<td>
<code>{(number|boolean)}</code><br/>A number or a boolean.
</td>
<td>Indicates that a value might have type A OR type B.</td>
<td>
<code>{(number,boolean)}</code>,
<code>{number|boolean}</code>,
<code>{(number||boolean)}</code>
</td>
</tr>
<tr>
<td>Record Type</td>
<td>
<code>{{myNum: number, myObject}}</code>
<br/>An anonymous type with the given type members.
</td>
<td>
<p>Indicates that the value has the specified members with the
specified types. In this case, <code>myNum</code> with a
type <code>number</code> and <code>myObject</code> with any
type.</p>
<p>Notice that the braces are part of the type syntax. For
example, to denote an <code>Array</code> of objects that
have a <code>length</code> property, you might write
<code>Array.&lt;{length}&gt;</code>.</p>
</td>
<td/>
</tr>
<tr>
<td>Nullable type</td>
<td>
<code>{?number}</code><br/> A number or NULL.
</td>
<td>Indicates that a value is type A or <code>null</code>.
By default, all object types are nullable.
NOTE: Function types are not nullable.
</td>
<td>
<code>{number?}</code>
</td>
</tr>
<tr>
<td>Non-nullable type</td>
<td>
<code>{!Object}</code><br/> An Object, but never the
<code>null</code> value.
</td>
<td>Indicates that a value is type A and not null. By default,
all value types (boolean, number, string, and undefined) are
not nullable.
</td>
<td>
<code>{Object!}</code>
</td>
</tr>
<tr>
<td>Function Type</td>
<td>
<code>{function(string, boolean)}</code><br/>
A function that takes two arguments (a string and a boolean),
and has an unknown return value.<br/>
</td>
<td>Specifies a function.</td>
<td/>
</tr>
<tr>
<td>Function Return Type</td>
<td>
<code>{function(): number}</code><br/>
A function that takes no arguments and returns a number.<br/>
</td>
<td>Specifies a function return type.</td>
<td/>
</tr>
<tr>
<td>Function <code>this</code> Type</td>
<td>
<code>{function(this:goog.ui.Menu, string)}</code><br/>
A function that takes one argument (a string), and executes
in the context of a goog.ui.Menu.
</td>
<td>Specifies the context type of a function type.</td>
<td/>
</tr>
<tr>
<td>Variable arguments</td>
<td>
<code>{function(string, ...[number]): number}</code><br/>
A function that takes one argument (a string), and then a
variable number of arguments that must be numbers.
</td>
<td>Specifies variable arguments to a function.</td>
<td/>
</tr>
<tr>
<td>
<a name="var-args-annotation"/>
Variable arguments (in <code>@param</code> annotations)
</td>
<td>
<code>@param {...number} var_args</code><br/>
A variable number of arguments to an annotated function.
</td>
<td>
Specifies that the annotated function accepts a variable
number of arguments.
</td>
<td/>
</tr>
<tr>
<td>Function <a href="optional">optional arguments</a></td>
<td>
<code>{function(?string=, number=)}</code><br/>
A function that takes one optional, nullable string and one
optional number as arguments. The <code>=</code> syntax is
only for <code>function</code> type declarations.
</td>
<td>Specifies optional arguments to a function.</td>
<td/>
</tr>
<tr>
<td>
<a name="optional-arg-annotation"/>
Function <a href="optional">optional arguments</a>
(in <code>@param</code> annotations)
</td>
<td>
<code>@param {number=} opt_argument</code><br/>
An optional parameter of type <code>number</code>.
</td>
<td>Specifies that the annotated function accepts an optional
argument.</td>
<td/>
</tr>
<tr>
<td>The ALL type</td>
<td><code>{*}</code></td>
<td>Indicates that the variable can take on any type.</td>
<td/>
</tr>
</tbody>
</table>
</SUBSECTION>
<SUBSECTION title="Types in JavaScript">
<p/>
<table border="1" style="border-collapse:collapse" cellpadding="4">
<thead>
<tr>
<th>Type Example</th>
<th>Value Examples</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>number</td>
<td>
<CODE_SNIPPET>
1
1.0
-5
1e5
Math.PI
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>Number</td>
<td>
<CODE_SNIPPET>
new Number(true)
</CODE_SNIPPET>
</td>
<td>
<a href="#Wrapper_objects_for_primitive_types">
Number object
</a>
</td>
</tr>
<tr>
<td>string</td>
<td>
<CODE_SNIPPET>
'Hello'
"World"
String(42)
</CODE_SNIPPET>
</td>
<td>
String value
</td>
</tr>
<tr>
<td>String</td>
<td>
<CODE_SNIPPET>
new String('Hello')
new String(42)
</CODE_SNIPPET>
</td>
<td>
<a href="#Wrapper_objects_for_primitive_types">
String object
</a>
</td>
</tr>
<tr>
<td>boolean</td>
<td>
<CODE_SNIPPET>
true
false
Boolean(0)
</CODE_SNIPPET>
</td>
<td>
Boolean value
</td>
</tr>
<tr>
<td>Boolean</td>
<td>
<CODE_SNIPPET>
new Boolean(true)
</CODE_SNIPPET>
</td>
<td>
<a href="#Wrapper_objects_for_primitive_types">
Boolean object
</a>
</td>
</tr>
<tr>
<td>RegExp</td>
<td>
<CODE_SNIPPET>
new RegExp('hello')
/world/g
</CODE_SNIPPET></td><td>
</td>
</tr>
<tr>
<td>Date</td>
<td>
<CODE_SNIPPET>
new Date
new Date()
</CODE_SNIPPET></td>
<td/>
</tr>
<tr>
<td>
null
</td>
<td>
<CODE_SNIPPET>
null
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>
undefined
</td>
<td>
<CODE_SNIPPET>
undefined
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>void</td>
<td>
<CODE_SNIPPET>
function f() {
return;
}
</CODE_SNIPPET>
</td>
<td>No return value</td>
</tr>
<tr>
<td>Array</td>
<td>
<CODE_SNIPPET>
['foo', 0.3, null]
[]
</CODE_SNIPPET>
</td>
<td>Untyped Array</td>
</tr>
<tr>
<td>Array.&lt;number&gt;</td>
<td>
<CODE_SNIPPET>
[11, 22, 33]
</CODE_SNIPPET>
</td>
<td>
An Array of numbers
</td>
</tr>
<tr>
<td>Array.&lt;Array.&lt;string&gt;&gt;</td>
<td>
<CODE_SNIPPET>
[['one', 'two', 'three'], ['foo', 'bar']]
</CODE_SNIPPET>
</td>
<td>Array of Arrays of strings</td>
</tr>
<tr>
<td>Object</td>
<td>
<CODE_SNIPPET>
{}
{foo: 'abc', bar: 123, baz: null}
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>Object.&lt;string&gt;</td>
<td>
<CODE_SNIPPET>
{'foo': 'bar'}
</CODE_SNIPPET>
</td>
<td>
An Object in which the values are strings.
</td>
</tr>
<tr>
<td>Object.&lt;number, string&gt;</td>
<td>
<CODE_SNIPPET>
var obj = {};
obj[1] = 'bar';
</CODE_SNIPPET>
</td>
<td>
An Object in which the keys are numbers and the values
are strings. <p/>Note that in JavaScript, the keys are always
implicitly coverted to strings, so
<code>obj['1'] == obj[1]</code>.
So the key wil always be a string in for...in loops. But the
compiler will verify the type if the key when indexing into
the object.
</td>
</tr>
<tr>
<td>Function</td>
<td>
<CODE_SNIPPET>
function(x, y) {
return x * y;
}
</CODE_SNIPPET>
</td>
<td>
<a href="#Wrapper_objects_for_primitive_types">
Function object
</a>
</td>
</tr>
<tr>
<td>function(number, number): number</td>
<td>
<CODE_SNIPPET>
function(x, y) {
return x * y;
}
</CODE_SNIPPET>
</td>
<td>function value</td>
</tr>
<tr>
<td>SomeClass</td>
<td>
<CODE_SNIPPET>
/** @constructor */
function SomeClass() {}
new SomeClass();
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>SomeInterface</td>
<td>
<CODE_SNIPPET>
/** @interface */
function SomeInterface() {}
SomeInterface.prototype.draw = function() {};
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>project.MyClass</td>
<td>
<CODE_SNIPPET>
/** @constructor */
project.MyClass = function () {}
new project.MyClass()
</CODE_SNIPPET>
</td>
<td/>
</tr>
<tr>
<td>project.MyEnum</td>
<td>
<CODE_SNIPPET>
/** @enum {string} */
project.MyEnum = {
BLUE: '#0000dd',
RED: '#dd0000'
};
</CODE_SNIPPET>
</td>
<td><a href="#enums">Enumeration</a></td>
</tr>
<tr>
<td>Element</td>
<td>
<CODE_SNIPPET>
document.createElement('div')
</CODE_SNIPPET>
</td>
<td>Elements in the DOM.</td>
</tr>
<tr>
<td>Node</td>
<td>
<CODE_SNIPPET>
document.body.firstChild
</CODE_SNIPPET>
</td>
<td>Nodes in the DOM.</td>
</tr>
<tr>
<td>HTMLInputElement</td>
<td>
<CODE_SNIPPET>
htmlDocument.getElementsByTagName('input')[0]
</CODE_SNIPPET>
</td>
<td>A specific type of DOM element.</td>
</tr>
</tbody>
</table>
</SUBSECTION>
<SUBSECTION title="Nullable vs. Optional Parameters and Properties">
<a name="optional"/>
<p>Because JavaScript is a loosely-typed language, it is very
important to understand the subtle differences between optional,
nullable, and undefined function parameters and class
properties.</p>
<p>Object types (also known as reference types) are nullable by
default. NOTE: Function types are not nullable by default. An
object is defined as anything except a string, number, boolean,
undefined, or null. For example, the following declaration</p>
<CODE_SNIPPET>
/**
* Some class, initialized with a value.
* @param {Object} value Some value.
* @constructor
*/
function MyClass(value) {
/**
* Some value.
* @type {Object}
* @private
*/
this.myValue_ = value;
}
</CODE_SNIPPET>
<p>tells the compiler that the <code>myValue_</code> property holds
either an Object or null. If <code>myValue_</code> must never be
null, it should be declared like this:</p>
<CODE_SNIPPET>
/**
* Some class, initialized with a non-null value.
* @param {!Object} value Some value.
* @constructor
*/
function MyClass(value) {
/**
* Some value.
* @type {!Object}
* @private
*/
this.myValue_ = value;
}
</CODE_SNIPPET>
<p>This way, if the compiler can determine that somewhere in the code
<code>MyClass</code> is initialized with a null value, it will issue
a warning.</p>
<p>Optional parameters to functions may be undefined at runtime, so if
they are assigned to class properties, those properties must be
declared accordingly:</p>
<CODE_SNIPPET>
/**
* Some class, initialized with an optional value.
* @param {Object=} opt_value Some value (optional).
* @constructor
*/
function MyClass(opt_value) {
/**
* Some value.
* @type {Object|undefined}
* @private
*/
this.myValue_ = opt_value;
}
</CODE_SNIPPET>
<p>This tells the compiler that <code>myValue_</code> may hold an
Object, null, or remain undefined.</p>
<p>Note that the optional parameter <code>opt_value</code> is declared
to be of type <code>{Object=}</code>, not
<code>{Object|undefined}</code>. This is because optional
parameters may, by definition, be undefined. While there is no harm
in explicitly declaring an optional parameter as possibly undefined,
it is both unnecessary and makes the code harder to read.</p>
<p>Finally, note that being nullable and being optional are orthogonal
properties. The following four declarations are all different:</p>
<CODE_SNIPPET>
/**
* Takes four arguments, two of which are nullable, and two of which are
* optional.
* @param {!Object} nonNull Mandatory (must not be undefined), must not be null.
* @param {Object} mayBeNull Mandatory (must not be undefined), may be null.
* @param {!Object=} opt_nonNull Optional (may be undefined), but if present,
* must not be null!
* @param {Object=} opt_mayBeNull Optional (may be undefined), may be null.
*/
function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) {
// ...
};
</CODE_SNIPPET>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Comments">
<SUMMARY>Use JSDoc</SUMMARY>
<BODY>
<p>We use
<a href="http://code.google.com/p/jsdoc-toolkit/">
JSDoc
</a>
comments to document files, classes, methods and properties. Inline
comments should be of the // variety. Additionally, we follow the
<a href="cppguide.xml#Comments">
C++ style for comments
</a> in spirit. This means you should have:
</p>
<ul>
<li>copyright and authorship notice,</li>
<li>a top-level (file-level) comment designed to orient readers
unfamiliar with the code to what's in this file (e.g., a
one-paragraph summary of what the major pieces are, how they fit
together, and with what they interact),</li>
<li>class, function, variable, and implementation comments as
necessary,</li>
<li>an indication of the browsers in which the code is expected to
work (if applicable), and</li>
<li>proper capitalization, punctuation, and spelling.</li>
</ul>
<p>Avoid sentence fragments. Start sentences with a properly
capitalized word, and end them with punctuation.</p>
<p>Pretend there's some novice programmer that's going to come along and
have to maintain the code after you. There very well just might
be!</p>
<p>There are now many compiler passes that extract type information from
JSDoc, in order to provide better code validation, removal, and
compression. It is, therefore, very important that you use full and
correct JSDoc.</p>
<SUBSECTION title="Top/File-Level Comments">
<p>
The top level comment is designed
to orient readers unfamiliar with the code to what is in this file.
It should provide a description of the file's contents, its
author(s), and any dependencies or compatibility information. As an
example:</p>
<CODE_SNIPPET>
// Copyright 2009 Google Inc. All Rights Reserved.
/**
* @fileoverview Description of file, its uses and information
* about its dependencies.
* @author user@google.com (Firstname Lastname)
*/
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Class Comments">
<p>Classes must be documented with a description and usage.
The constructor parameters must also be documented.
If the class inherits from another class,
that should be documented with an <code>@extends</code> tag.
If the class implements an interface,
that should be documented with an <code>@implements</code> tag.
</p>
<CODE_SNIPPET>
/**
* Class making something fun and easy.
* @param {string} arg1 An argument that makes this more interesting.
* @param {Array.&lt;number&gt;} arg2 List of numbers to be processed.
* @constructor
* @extends {goog.Disposable}
*/
project.MyClass = function(arg1, arg2) {
// ...
};
goog.inherits(project.MyClass, goog.Disposable);
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Method and Function Comments">
<p>A description must be provided along with parameters. Use full
sentences. Method descriptions should start with a sentence written
in the third person declarative voice.</p>
<CODE_SNIPPET>
/**
* Converts text to some completely different text.
* @param {string} arg1 An argument that makes this more interesting.
* @return {string} Some return value.
*/
project.MyClass.prototype.someMethod = function(arg1) {
// ...
};
/**
* Operates on an instance of MyClass and returns something.
* @param {project.MyClass} obj Instance of MyClass which leads to a long
* comment that needs to be wrapped to two lines.
* @return {boolean} Whether something occured.
*/
function PR_someMethod(obj) {
// ...
}
</CODE_SNIPPET>
<p>For simple getters that take no parameters, the description can be
omitted.</p>
<CODE_SNIPPET>
/**
* @return {Element} The element for the component.
*/
goog.ui.Component.prototype.getElement = function() {
return this.element_;
};
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Property Comments">
<p>It is also nice to have comments for properties.</p>
<CODE_SNIPPET>
/**
* Maximum number of things per pane.
* @type {number}
*/
project.MyClass.prototype.someProperty = 4;
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Type Cast Comments">
<p>In cases where type-checking doesn't accurately infer the type of
an expression, it is possible to add a type cast comment by adding a
type annotation comment and enclosing the expression in
parenthesis. The parentheses are required, and may surround the type
annotation comment as well.</p>
<CODE_SNIPPET>
/** @type {number} */ (x)
(/** @type {number} */ x)
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="JSDoc Indentation">
<p>If you have to line break a <code>@param</code>,
<code>@return</code>, <code>@supported</code>, <code>@this</code> or
<code>@deprecated</code> you should treat this as breaking a code
statement and indent it four spaces.</p>
<CODE_SNIPPET>
/**
* Illustrates line wrapping for long param/return descriptions.
* @param {string} foo This is a param with a description too long to fit in
* one line.
* @return {number} This returns something that has a description too long to
* fit in one line.
*/
project.MyClass.prototype.method = function(foo) {
return 5;
};
</CODE_SNIPPET>
<p>You should not indent the <code>@fileoverview</code> command.</p>
<p>Even though it is not preferred, it is also acceptable to line up
the description. This has the side effect that you will have to
realign the text every time you change a variable name so this will
soon get your code out of sync.</p>
<CODE_SNIPPET>
/**
* This is NOT the preferred indentation method.
* @param {string} foo This is a param with a description too long to fit in
* one line.
* @return {number} This returns something that has a description too long to
* fit in one line.
*/
project.MyClass.prototype.method = function(foo) {
return 5;
};
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Enums">
<a name="enums"/>
<CODE_SNIPPET>
/**
* Enum for tri-state values.
* @enum {number}
*/
project.TriState = {
TRUE: 1,
FALSE: -1,
MAYBE: 0
};
</CODE_SNIPPET>
<p>Note that enums are also valid <a href="#JavaScript_Types">types</a>
and thus can be used as parameter types, etc.</p>
<CODE_SNIPPET>
/**
* Sets project state.
* @param {project.TriState} state New project state.
*/
project.setState = function(state) {
// ...
};
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Typedefs">
<p>Sometimes types can get complicated. A function that accepts
content for an Element might look like:</p>
<CODE_SNIPPET>
/**
* @param {string} tagName
* @param {(string|Element|Text|Array.&lt;Element&gt;|Array.&lt;Text&gt;)} contents
* @return {Element}
*/
goog.createElement = function(tagName, contents) {
...
};
</CODE_SNIPPET>
<p>You can define commonly used type expressions with a
<code>@typedef</code> tag. For example,</p>
<CODE_SNIPPET>
/** @typedef {(string|Element|Text|Array.&lt;Element&gt;|Array.&lt;Text&gt;)} */
goog.ElementContent;
/**
* @param {string} tagName
* @param {goog.ElementContent} contents
* @return {Element}
*/
goog.createElement = function(tagName, contents) {
...
};
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="JSDoc Tag Reference">
<table border="1" style="border-collapse:collapse" cellpadding="4">
<thead>
<tr>
<th>Tag</th>
<th>Template &amp; Examples</th>
<th>Description</th>
<th>Type-Checking Support</th>
</tr>
</thead>
<tbody>
<tr>
<td><a name="tag-param">@param</a></td>
<td>
<tt>@param {Type} varname Description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Queries a Baz for items.
* @param {number} groupNum Subgroup id to query.
* @param {string|number|null} term An itemName,
* or itemId, or null to search everything.
*/
goog.Baz.prototype.query = function(groupNum, term) {
// ...
};
</CODE_SNIPPET>
</td>
<td>
Used with method, function and constructor calls to document
the arguments of a function.
</td>
<td>Fully supported.</td>
</tr>
<tr>
<td><a name="tag-return">@return</a></td>
<td>
<tt>@return {Type} Description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @return {string} The hex ID of the last item.
*/
goog.Baz.prototype.getLastId = function() {
// ...
return id;
};
</CODE_SNIPPET>
</td>
<td>
Used with method and function calls to document the return
type. When writing descriptions for boolean parameters,
prefer "Whether the component is visible" to "True if the
component is visible, false otherwise". If there is no return
value, do not use an <code>@return</code> tag.
</td>
<td>Fully supported.</td>
</tr>
<tr>
<td>
<a name="tag-author">@author</a>
</td>
<td>
<tt>@author username@google.com (first last)</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @fileoverview Utilities for handling textareas.
* @author kuth@google.com (Uthur Pendragon)
*/
</CODE_SNIPPET>
</td>
<td>
Document the author of a file or the owner of a test,
generally only used in the <code>@fileoverview</code> comment.
</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-see">@see</a></td>
<td>
<tt>@see Link</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Adds a single item, recklessly.
* @see #addSafely
* @see goog.Collect
* @see goog.RecklessAdder#add
...
</CODE_SNIPPET>
</td>
<td>Reference a lookup to another class function or method.</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-fileoverview">@fileoverview</a></td>
<td>
<tt>@fileoverview Description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @fileoverview Utilities for doing things that require this very long
* but not indented comment.
* @author kuth@google.com (Uthur Pendragon)
*/
</CODE_SNIPPET>
</td>
<td>Makes the comment block provide file level information.</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-constructor">@constructor</a></td>
<td>
<tt>@constructor</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* A rectangle.
* @constructor
*/
function GM_Rect() {
...
}
</CODE_SNIPPET>
</td>
<td>
Used in a class's documentation to indicate the constructor.
</td>
<td>
Yes. If omitted the compiler will prohibit instantiation.
</td>
</tr>
<tr>
<td><a name="tag-interface">@interface</a></td>
<td>
<tt>@interface</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* A shape.
* @interface
*/
function Shape() {};
Shape.prototype.draw = function() {};
/**
* A polygon.
* @interface
* @extends {Shape}
*/
function Polygon() {};
Polygon.prototype.getSides = function() {};
</CODE_SNIPPET>
</td>
<td>Used to indicate that the function defines an inteface.</td>
<td>
Yes. The compiler will warn about instantiating an interface.
</td>
</tr>
<tr>
<td><a name="tag-type">@type</a></td>
<td>
<tt>
@type Type<br/>
@type {Type}
</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* The message hex ID.
* @type {string}
*/
var hexId = hexId;
</CODE_SNIPPET>
</td>
<td>
Identifies the type of a variable, property, or expression.
Curly braces are not required around most types, but some
projects mandate them for all types, for consistency.
</td>
<td>Yes</td>
</tr>
<tr>
<td><a name="tag-extends">@extends</a></td>
<td>
<tt>
@extends Type<br/>
@extends {Type}
</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Immutable empty node list.
* @constructor
* @extends goog.ds.BasicNodeList
*/
goog.ds.EmptyNodeList = function() {
...
};
</CODE_SNIPPET>
</td>
<td>
Used with @constructor to indicate that a class inherits from
another class. Curly braces around the type are optional.
</td>
<td>Yes</td>
</tr>
<tr>
<td><a name="tag-implements">@implements</a></td>
<td>
<tt>
@implements Type<br/>
@implements {Type}
</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* A shape.
* @interface
*/
function Shape() {};
Shape.prototype.draw = function() {};
/**
* @constructor
* @implements {Shape}
*/
function Square() {};
Square.prototype.draw = function() {
...
};
</CODE_SNIPPET>
</td>
<td>
Used with @constructor to indicate that a class implements an
interface. Curly braces around the type are optional.
</td>
<td>
Yes. The compiler will warn about incomplete implementations
of interfaces.
</td>
</tr>
<tr>
<td><a name="tag-lends">@lends</a></td>
<td>
<tt>@lends objectName</tt><br/>
<tt>@lends {objectName}</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
goog.object.extend(
Button.prototype,
/** @lends {Button.prototype} */ {
isButton: function() { return true; }
});
</CODE_SNIPPET>
</td>
<td>
Indicates that the keys of an object literal should
be treated as properties of some other object. This annotation
should only appear on object literals.<p/>
Notice that the name in braces is not a type name like
in other annotations. It's an object name. It names
the object on which the properties are "lent".
For example, <tt>@type {Foo}</tt> means "an instance of Foo",
but <tt>@lends {Foo}</tt> means "the constructor Foo".<p/>
The <a href="http://code.google.com/p/jsdoc-toolkit/wiki/TagLends">
JSDoc Toolkit docs</a> have more information on this
annotation.
</td>
<td>Yes</td>
</tr>
2010-07-13 06:02:20 +08:00
<tr>
<td><a name="tag-private">@private</a></td>
<td>
<tt>@private</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Handlers that are listening to this logger.
* @type Array.&lt;Function&gt;
* @private
*/
this.handlers_ = [];
</CODE_SNIPPET>
</td>
<td>
Used in conjunction with a trailing underscore on the method
or property name to indicate that the member is
<a href="#Visibility__private_and_protected_fields_">private</a>.
Trailing underscores may eventually be deprecated as tools are
updated to enforce <tt>@private</tt>.
</td>
<td>Enforced with a flag.</td>
</tr>
<tr>
<td><a name="tag-protected">@protected</a></td>
<td>
<tt>@protected</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Sets the component's root element to the given element. Considered
* protected and final.
* @param {Element} element Root element for the component.
* @protected
*/
goog.ui.Component.prototype.setElementInternal = function(element) {
// ...
};
</CODE_SNIPPET>
</td>
<td>
Used to indicate that the member or property is
<a href="#Visibility__private_and_protected_fields_">protected</a>.
Should be used in conjunction with names with no trailing
underscore.
</td>
<td>Enforced with a flag.</td>
</tr>
<tr>
<td><a name="tag-this">@this</a></td>
<td>
<tt>
@this Type<br/>
@this {Type}
</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
pinto.chat.RosterWidget.extern('getRosterElement',
/**
* Returns the roster widget element.
* @this pinto.chat.RosterWidget
* @return {Element}
*/
function() {
return this.getWrappedComponent_().getElement();
});
</CODE_SNIPPET>
</td>
<td>
The type of the object in whose context a particular method is
called. Required when the <tt>this</tt> keyword is referenced
from a function that is not a prototype method.
</td>
<td>Yes</td>
</tr>
<tr>
<td><a name="tag-supported">@supported</a></td>
<td>
<tt>@supported Description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @fileoverview Event Manager
* Provides an abstracted interface to the
* browsers' event systems.
* @supported So far tested in IE6 and FF1.5
*/
</CODE_SNIPPET>
</td>
<td>
Used in a fileoverview to indicate what browsers are supported
by the file.
</td>
<td>Unrelated to type checking.</td></tr>
<tr>
<td><a name="tag-enum">@enum</a></td>
<td>
<tt>@enum {Type}</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Enum for tri-state values.
* @enum {number}
*/
project.TriState = {
TRUE: 1,
FALSE: -1,
MAYBE: 0
};
</CODE_SNIPPET>
</td>
<td>Used for documenting enum types.</td>
<td>Fully supported. If Type is omitted, number assumed.</td>
</tr>
<tr>
<td><a name="tag-deprecated">@deprecated</a></td>
<td>
<tt>@deprecated Description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Determines whether a node is a field.
* @return {boolean} True if the contents of
* the element are editable, but the element
* itself is not.
* @deprecated Use isField().
*/
BN_EditUtil.isTopEditableField = function(node) {
// ...
};
</CODE_SNIPPET>
</td>
<td>
Used to tell that a function, method or property should not be
used any more. Always provide instructions on what callers
should use instead.
</td>
<td>Unrelated to type checking</td>
</tr>
<tr>
<td><a name="tag-override">@override</a></td>
<td>
<tt>@override</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @return {string} Human-readable representation of project.SubClass.
* @override
*/
project.SubClass.prototype.toString() {
// ...
};
</CODE_SNIPPET>
</td>
<td>
Indicates that a method or property of a subclass
intentionally hides a method or property of the superclass. If
no other documentation is included, the method or property
also inherits documentation from its superclass.
</td>
<td>Yes</td>
</tr>
<tr>
<td><a name="tag-inheritDoc">@inheritDoc</a></td>
<td>
<tt>@inheritDoc</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @inheritDoc */
project.SubClass.prototype.toString() {
// ...
};
</CODE_SNIPPET>
</td>
<td>
Indicates that a method or property of a subclass
intentionally hides a method or property of the superclass,
and has exactly the same documentation. Notice that
@inheritDoc implies @override.
</td>
<td>Yes</td>
</tr>
<tr>
<td><a name="tag-code">@code</a></td>
<td>
<tt>{@code ...}</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* Moves to the next position in the selection.
* Throws {@code goog.iter.StopIteration} when it
* passes the end of the range.
* @return {Node} The node at the next position.
*/
goog.dom.RangeIterator.prototype.next = function() {
// ...
};
</CODE_SNIPPET>
</td>
<td>
Indicates that a term in a JSDoc description is code so it may
be correctly formatted in generated documentation.
</td>
<td>Not applicable.</td>
</tr>
<tr>
<td><a name="tag-license">@license</a> or
<a name="tag-preserve">@preserve</a></td>
<td>
<tt>@license Description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @preserve Copyright 2009 SomeThirdParty.
* Here is the full license text and copyright
* notice for this file. Note that the notice can span several
* lines and is only terminated by the closing star and slash:
*/
</CODE_SNIPPET>
</td>
<td>
Anything marked by @license or @preserve will be retained by
the compiler and output at the top of the compiled code for
that file. This annotation allows important notices (such as
legal licenses or copyright text) to survive compilation
unchanged. Line breaks are preserved.
</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-noalias">@noalias</a></td>
<td>
<tt>@noalias</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @noalias */
function Range() {}
</CODE_SNIPPET>
</td>
<td>
Used in an externs file to indicate to the compiler that the
variable or function should not be aliased as part of the
alias externals pass of the compiler.
</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-define">@define</a></td>
<td>
<tt>@define {Type} description</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @define {boolean} */
var TR_FLAGS_ENABLE_DEBUG = true;
/** @define {boolean} */
goog.userAgent.ASSUME_IE = false;
</CODE_SNIPPET>
</td>
<td>
Indicates a constant that can be overridden by the compiler at
compile-time. In the example, the compiler flag
<tt>--define='goog.userAgent.ASSUME_IE=true'</tt>
could be specified in the BUILD file to indicate that the
constant <tt>goog.userAgent.ASSUME_IE</tt> should be replaced
with <tt>true</tt>.
</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-export">@export</a></td>
<td>
<tt>@export</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @export */
foo.MyPublicClass.prototype.myPublicMethod = function() {
// ...
};
</CODE_SNIPPET>
</td>
<td>
<p>Given the code on the left, when the compiler is run with
the <tt>--generate_exports</tt> flag, it will generate the
code:</p>
<CODE_SNIPPET>
goog.exportSymbol('foo.MyPublicClass.prototype.myPublicMethod',
foo.MyPublicClass.prototype.myPublicMethod);
</CODE_SNIPPET>
<p>which will export the symbols to uncompiled code.
Code that uses the <tt>@export</tt> annotation must either</p>
<ol>
<li>include <tt>//javascript/closure/base.js</tt>, or</li>
<li>define both <tt>goog.exportSymbol</tt> and
<tt>goog.exportProperty</tt> with the same method
signature in their own codebase.</li>
</ol>
</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-const">@const</a></td>
<td>
<tt>@const</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @const */ var MY_BEER = 'stout';
/**
* My namespace's favorite kind of beer.
* @const
* @type {string}
*/
mynamespace.MY_BEER = 'stout';
/** @const */ MyClass.MY_BEER = 'stout';
</CODE_SNIPPET>
</td>
<td>
<p>Marks a variable as read-only and suitable for inlining.
Generates warnings if it is rewritten.</p>
<p>Constants should also be ALL_CAPS, but the annotation
should help eliminate reliance on the naming convention.
Although @final is listed at jsdoc.org and is supported as
equivalent to @const in the compiler, it is discouraged.
@const is consistent with JS1.5's const keyword. Note that
changes to properties of const objects are not currently
prohibited by the compiler (inconsistent with C++ const
semantics). The type declaration can be omitted if it can be
clearly inferred. If present, it must be on its own line. An
additional comment about the variable is optional.</p>
</td>
<td>Supported by type checking.</td>
</tr>
<tr>
<td><a name="tag-nosideeffects">@nosideeffects</a></td>
<td>
<tt>@nosideeffects</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @nosideeffects */
function noSideEffectsFn1() {
// ...
};
/** @nosideeffects */
var noSideEffectsFn2 = function() {
// ...
};
/** @nosideeffects */
a.prototype.noSideEffectsFn3 = function() {
// ...
};
</CODE_SNIPPET>
</td>
<td>
This annotation can be used as part of function and
constructor declarations to indicate that calls to the
declared function have no side-effects. This annotation
allows the compiler to remove calls to these functions if the
return value is not used.
</td>
<td>Unrelated to type checking.</td>
</tr>
<tr>
<td><a name="tag-typedef">@typedef</a></td>
<td>
<tt>@typedef</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/** @typedef {(string|number)} */
goog.NumberLike;
/** @param {goog.NumberLike} x A number or a string. */
goog.readNumber = function(x) {
...
}
</CODE_SNIPPET>
</td>
<td>
This annotation can be used to declare an alias of a more
complex type.
</td>
<td>Yes</td>
</tr>
<tr>
<td><a name="tag-externs">@externs</a></td>
<td>
<tt>@externs</tt>
<p><i>For example:</i></p>
<CODE_SNIPPET>
/**
* @fileoverview This is an externs file.
* @externs
*/
var document;
</CODE_SNIPPET>
</td>
<td>
<p>
Declares an
externs file.
</p>
</td>
<td>No</td>
</tr>
</tbody>
</table>
<p>
You may also see other types of JSDoc annotations in third-party
code. These annotations appear in the
<a href="http://code.google.com/p/jsdoc-toolkit/wiki/TagReference">
JSDoc Toolkit Tag Reference
</a>
but are currently discouraged in Google code. You should consider
them "reserved" names for future use. These include:
<ul>
<li>@augments</li>
<li>@argument</li>
<li>@borrows</li>
<li>@class</li>
<li>@constant</li>
<li>@constructs</li>
<li>@default</li>
<li>@event</li>
<li>@example</li>
<li>@field</li>
<li>@function</li>
<li>@ignore</li>
<li>@inner</li>
<li>@link</li>
<li>@memberOf</li>
<li>@name</li>
<li>@namespace</li>
<li>@property</li>
<li>@public</li>
<li>@requires</li>
<li>@returns</li>
<li>@since</li>
<li>@static</li>
<li>@version</li>
</ul>
</p>
</SUBSECTION>
<SUBSECTION title="HTML in JSDoc">
<p>Like JavaDoc, JSDoc supports many HTML tags, like &lt;code&gt;,
&lt;pre&gt;, &lt;tt&gt;, &lt;strong&gt;, &lt;ul&gt;, &lt;ol&gt;,
&lt;li&gt;, &lt;a&gt;, and others.</p>
<p>This means that plaintext formatting is not respected. So, don't
rely on whitespace to format JSDoc:</p>
<BAD_CODE_SNIPPET>
/**
* Computes weight based on three factors:
* items sent
* items received
* last timestamp
*/
</BAD_CODE_SNIPPET>
<p>It'll come out like this:</p>
<tt>Computes weight based on three factors: items sent items received items received</tt>
<p>Instead, do this:</p>
<CODE_SNIPPET>
/**
* Computes weight based on three factors:
* &lt;ul&gt;
* &lt;li&gt;items sent
* &lt;li&gt;items received
* &lt;li&gt;last timestamp
* &lt;/ul&gt;
*/
</CODE_SNIPPET>
<p>Also, don't include HTML or HTML-like tags unless you want them to
be interpreted as HTML.</p>
<BAD_CODE_SNIPPET>
/**
* Changes &lt;b&gt; tags to &lt;span&gt; tags.
*/
</BAD_CODE_SNIPPET>
<p>It'll come out like this:</p>
<tt>Changes <b> tags to <span> tags.</span></b></tt>
<p>On the other hand, people need to be able to read this in its
plaintext form too, so don't go overboard with the HTML:</p>
<BAD_CODE_SNIPPET>
/**
* Changes &amp;lt;b&amp;gt; tags to &amp;lt;span&amp;gt; tags.
*/
</BAD_CODE_SNIPPET>
<p>People will know what you're talking about if you leave the
angle-brackets out, so do this:</p>
<CODE_SNIPPET>
/**
* Changes 'b' tags to 'span' tags.
*/
</CODE_SNIPPET>
</SUBSECTION>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Compiling">
<SUMMARY>Encouraged</SUMMARY>
<BODY>
<p>Use of JS compilers such as the
<a href="http://code.google.com/closure/compiler/">Closure Compiler</a>
is encouraged.</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Tips and Tricks">
<SUMMARY>JavaScript tidbits</SUMMARY>
<BODY>
<SUBSECTION title="True and False Boolean Expressions">
<p>The following are all false in boolean expressions:</p>
<ul>
<li><code>null</code></li>
<li><code>undefined</code></li>
<li><code>''</code> the empty string</li>
<li><code>0</code> the number</li>
</ul>
<p>But be careful, because these are all true:</p>
<ul>
<li><code>'0'</code> the string</li>
<li><code>[]</code> the empty array</li>
<li><code>{}</code> the empty object</li>
</ul>
<p>This means that instead of this:</p>
<BAD_CODE_SNIPPET>
while (x != null) {
</BAD_CODE_SNIPPET>
<p>you can write this shorter code (as long as you don't expect x to
be 0, or the empty string, or false):</p>
<CODE_SNIPPET>
while (x) {
</CODE_SNIPPET>
<p>And if you want to check a string to see if it is null or empty,
you could do this:</p>
<BAD_CODE_SNIPPET>
if (y != null &amp;&amp; y != '') {
</BAD_CODE_SNIPPET>
<p>But this is shorter and nicer:</p>
<CODE_SNIPPET>
if (y) {
</CODE_SNIPPET>
<p><strong>Caution:</strong> There are many unintuitive things about
boolean expressions. Here are some of them:</p>
<ul>
<li><code>
Boolean('0') == true<br/>
'0' != true</code></li>
<li><code>
0 != null<br/>
0 == []<br/>
0 == false</code></li>
<li><code>
Boolean(null) == false<br/>
null != true<br/>
null != false</code></li>
<li><code>
Boolean(undefined) == false<br/>
undefined != true<br/>
undefined != false</code></li>
<li><code>
Boolean([]) == true<br/>
[] != true<br/>
[] == false</code></li>
<li><code>
Boolean({}) == true<br/>
{} != true<br/>
{} != false</code></li>
</ul>
</SUBSECTION>
<SUBSECTION title="Conditional (Ternary) Operator (?:)">
<p>Instead of this:</p>
<CODE_SNIPPET>
if (val != 0) {
return foo();
} else {
return bar();
}
</CODE_SNIPPET>
<p>you can write this:</p>
<CODE_SNIPPET>
return val ? foo() : bar();
</CODE_SNIPPET>
<p>The ternary conditional is also useful when generating HTML:</p>
<CODE_SNIPPET>
var html = '&lt;input type="checkbox"' +
(isChecked ? ' checked' : '') +
(isEnabled ? '' : ' disabled') +
' name="foo"&gt;';
</CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="&amp;&amp; and ||">
<p>These binary boolean operators are short-circuited, and evaluate
to the last evaluated term.</p>
<p>"||" has been called the 'default' operator, because instead of
writing this:</p>
<BAD_CODE_SNIPPET>
/** @param {*=} opt_win */
function foo(opt_win) {
var win;
if (opt_win) {
win = opt_win;
} else {
win = window;
}
// ...
}
</BAD_CODE_SNIPPET>
<p>you can write this:</p>
<CODE_SNIPPET>
/** @param {*=} opt_win */
function foo(opt_win) {
var win = opt_win || window;
// ...
}
</CODE_SNIPPET>
<p>"&amp;&amp;" is also useful for shortening code. For instance,
instead of this:</p>
<BAD_CODE_SNIPPET>
if (node) {
if (node.kids) {
if (node.kids[index]) {
foo(node.kids[index]);
}
}
}
</BAD_CODE_SNIPPET>
<p>you could do this:</p>
<CODE_SNIPPET>
if (node &amp;&amp; node.kids &amp;&amp; node.kids[index]) {
foo(node.kids[index]);
}
</CODE_SNIPPET>
<p>or this:</p>
<CODE_SNIPPET>
var kid = node &amp;&amp; node.kids &amp;&amp; node.kids[index];
if (kid) {
foo(kid);
}
</CODE_SNIPPET>
<p>However, this is going a little too far:</p>
<BAD_CODE_SNIPPET>
node &amp;&amp; node.kids &amp;&amp; node.kids[index] &amp;&amp; foo(node.kids[index]);
</BAD_CODE_SNIPPET>
</SUBSECTION>
<SUBSECTION title="Use join() to Build Strings">
<p>It is common to see this:</p>
<BAD_CODE_SNIPPET>
function listHtml(items) {
var html = '&lt;div class="foo"&gt;';
for (var i = 0; i &lt; items.length; ++i) {
if (i &gt; 0) {
html += ', ';
}
html += itemHtml(items[i]);
}
html += '&lt;/div&gt;';
return html;
}
</BAD_CODE_SNIPPET>
<p>but this is slow in Internet Explorer, so it is better to do
this:</p>
<CODE_SNIPPET>
function listHtml(items) {
var html = [];
for (var i = 0; i &lt; items.length; ++i) {
html[i] = itemHtml(items[i]);
}
return '&lt;div class="foo"&gt;' + html.join(', ') + '&lt;/div&gt;';
}
</CODE_SNIPPET>
<p>You can also use an array as a stringbuilder, and convert it into
a string with <code>myArray.join('')</code>. Note that since
assigning values to an array is faster than using
<code>push()</code> you should use assignment where possible.</p>
</SUBSECTION>
<SUBSECTION title="Iterating over Node Lists">
<p>Node lists are often implemented as node iterators with a filter.
This means that getting a property like length is O(n), and
iterating over the list by re-checking the length will be
O(n^2).</p>
<BAD_CODE_SNIPPET>
var paragraphs = document.getElementsByTagName('p');
for (var i = 0; i &lt; paragraphs.length; i++) {
doSomething(paragraphs[i]);
}
</BAD_CODE_SNIPPET>
<p>It is better to do this instead:</p>
<CODE_SNIPPET>
var paragraphs = document.getElementsByTagName('p');
for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
doSomething(paragraph);
}
</CODE_SNIPPET>
<p>This works well for all collections and arrays as long as the array
does not contain things that are treated as boolean false.</p>
<p>In cases where you are iterating over the childNodes you can also
use the firstChild and nextSibling properties.</p>
<CODE_SNIPPET>
var parentNode = document.getElementById('foo');
for (var child = parentNode.firstChild; child; child = child.nextSibling) {
doSomething(child);
}
</CODE_SNIPPET>
</SUBSECTION>
</BODY>
</STYLEPOINT>
</CATEGORY>
<PARTING_WORDS>
<p>
<em>BE CONSISTENT</em>.
</p>
<p>
If you're editing code, take a few minutes to look at the code
around you and determine its style. If they use spaces around
all their arithmetic operators, you should too. If their
comments have little boxes of hash marks around them, make your
comments have little boxes of hash marks around them too.
</p>
<p>
The point of having style guidelines is to have a common vocabulary
of coding so people can concentrate on what you're saying rather
than on how you're saying it. We present global style rules here so
people know the vocabulary, but local style is also important. If
code you add to a file looks drastically different from the existing
code around it, it throws readers out of their rhythm when they go to
read it. Avoid this.
</p>
</PARTING_WORDS>
<p align="right">
Revision 2.9
2010-07-13 06:02:20 +08:00
</p>
<address>
Aaron Whyte<br/>
Bob Jervis<br/>
Dan Pupius<br/>
Erik Arvidsson<br/>
Fritz Schneider<br/>
Robby Walker<br/>
</address>
</GUIDE>