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">
|
|
|
|
|
2010-10-05 00:26:53 +08:00
|
|
|
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>
|
|
|
|
>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.<number>}
|
|
|
|
* @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>
|
|
|
|
|
2010-10-05 00:26:53 +08:00
|
|
|
<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 < 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>
|
2010-10-05 00:26:53 +08:00
|
|
|
|
|
|
|
<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>
|
2010-10-05 00:26:53 +08:00
|
|
|
<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" <fjordmaster@magrathea.com>',
|
|
|
|
'"Zaphod Beeblebrox" <theprez@universe.gov>',
|
|
|
|
'"Ford Prefect" <ford@theguide.com>',
|
|
|
|
'"Arthur Dent" <has.no.tea@gmail.com>',
|
|
|
|
'"Marvin the Paranoid Android" <marv@googlemail.com>',
|
|
|
|
'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) &&
|
|
|
|
!ambientNotification.isActive() && (client.isAmbientSupported() ||
|
2010-10-22 01:20:05 +08:00
|
|
|
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
|
2010-08-05 01:43:38 +08:00
|
|
|
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>
|
2010-08-05 01:43:38 +08:00
|
|
|
<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.<string>}</code><br/>An array of strings.<p/>
|
|
|
|
<code>{Object.<string, number>}</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.<{length}></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.<number></td>
|
|
|
|
<td>
|
|
|
|
<CODE_SNIPPET>
|
|
|
|
[11, 22, 33]
|
|
|
|
</CODE_SNIPPET>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
An Array of numbers
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
<td>Array.<Array.<string>></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.<string></td>
|
|
|
|
<td>
|
|
|
|
<CODE_SNIPPET>
|
|
|
|
{'foo': 'bar'}
|
|
|
|
</CODE_SNIPPET>
|
|
|
|
</td>
|
|
|
|
<td>
|
|
|
|
An Object in which the values are strings.
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
|
|
|
|
<tr>
|
|
|
|
<td>Object.<number, string></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.<number>} 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.<Element>|Array.<Text>)} 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.<Element>|Array.<Text>)} */
|
|
|
|
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 & 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>
|
|
|
|
|
2010-10-05 00:26:53 +08:00
|
|
|
<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.<Function>
|
|
|
|
* @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 <code>,
|
|
|
|
<pre>, <tt>, <strong>, <ul>, <ol>,
|
|
|
|
<li>, <a>, 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:
|
|
|
|
* <ul>
|
|
|
|
* <li>items sent
|
|
|
|
* <li>items received
|
|
|
|
* <li>last timestamp
|
|
|
|
* </ul>
|
|
|
|
*/
|
|
|
|
</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 <b> tags to <span> 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 &lt;b&gt; tags to &lt;span&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 && 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 = '<input type="checkbox"' +
|
|
|
|
(isChecked ? ' checked' : '') +
|
|
|
|
(isEnabled ? '' : ' disabled') +
|
|
|
|
' name="foo">';
|
|
|
|
</CODE_SNIPPET>
|
|
|
|
</SUBSECTION>
|
|
|
|
|
|
|
|
<SUBSECTION title="&& 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>"&&" 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 && node.kids && node.kids[index]) {
|
|
|
|
foo(node.kids[index]);
|
|
|
|
}
|
|
|
|
</CODE_SNIPPET>
|
|
|
|
|
|
|
|
<p>or this:</p>
|
|
|
|
<CODE_SNIPPET>
|
|
|
|
var kid = node && node.kids && node.kids[index];
|
|
|
|
if (kid) {
|
|
|
|
foo(kid);
|
|
|
|
}
|
|
|
|
</CODE_SNIPPET>
|
|
|
|
|
|
|
|
<p>However, this is going a little too far:</p>
|
|
|
|
<BAD_CODE_SNIPPET>
|
|
|
|
node && node.kids && node.kids[index] && 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 = '<div class="foo">';
|
|
|
|
for (var i = 0; i < items.length; ++i) {
|
|
|
|
if (i > 0) {
|
|
|
|
html += ', ';
|
|
|
|
}
|
|
|
|
html += itemHtml(items[i]);
|
|
|
|
}
|
|
|
|
html += '</div>';
|
|
|
|
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 < items.length; ++i) {
|
|
|
|
html[i] = itemHtml(items[i]);
|
|
|
|
}
|
|
|
|
return '<div class="foo">' + html.join(', ') + '</div>';
|
|
|
|
}
|
|
|
|
</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 < 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">
|
2010-10-05 00:26:53 +08:00
|
|
|
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>
|