You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3629 lines
131 KiB
3629 lines
131 KiB
<?xml version = '1.0'?> |
|
<?xml-stylesheet type="text/xsl" href="styleguide.xsl"?> |
|
<GUIDE title="Google JavaScript Style Guide"> |
|
<p class="revision"> |
|
Please note: there's a newer version of this guide that includes |
|
ECMAScript 6th Edition features. It lives <a href="jsguide.html">here</a>. |
|
You should probably be using that for new code. |
|
|
|
Revision 2.93 |
|
</p> |
|
|
|
<address> |
|
Aaron Whyte<br/> |
|
Bob Jervis<br/> |
|
Dan Pupius<br/> |
|
Erik 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> |
|
<ul> |
|
<li>Use <code>NAMES_LIKE_THIS</code> for constant <em>values</em>.</li> |
|
<li>Use <code>@const</code> to indicate a constant (non-overwritable) |
|
<em>pointer</em> (a variable or property).</li> |
|
<li>Never use the |
|
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Statements/const"> |
|
<code>const</code> keyword</a> |
|
as it's not supported in Internet Explorer.</li> |
|
</ul> |
|
</SUMMARY> |
|
<BODY> |
|
<DECISION> |
|
<SUBSECTION title="Constant values"> |
|
|
|
<p>If a value is intended to be <em>constant</em> |
|
and <em>immutable</em>, it should be given a name |
|
in <code>CONSTANT_VALUE_CASE</code>. |
|
<code>ALL_CAPS</code> additionally implies <code>@const</code> |
|
(that the value is not overwritable). |
|
</p> |
|
|
|
<p>Primitive types (<code>number</code>, <code>string</code>, |
|
<code>boolean</code>) are constant values.</p> |
|
|
|
<p><code>Objects</code>' |
|
immutability is more subjective — objects should be |
|
considered immutable only if they do not demonstrate observable |
|
state change. This is not enforced by the compiler.</p> |
|
|
|
|
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="Constant pointers (variables and properties)"> |
|
<p>The <code>@const</code> annotation on a variable or property |
|
implies that it is not overwritable. This is enforced by the |
|
compiler at build time. This behavior is consistent with the |
|
<a href="https://developer.mozilla.org/en/JavaScript/Reference/Statements/const"> |
|
<code>const</code> keyword</a> (which we do not use due to the |
|
lack of support in Internet Explorer).</p> |
|
|
|
<p>A <code>@const</code> annotation on a method additionally |
|
implies that the method cannot not be overridden in subclasses. |
|
</p> |
|
|
|
<p>A <code>@const</code> annotation on a constructor implies the |
|
class cannot be subclassed (akin to <code>final</code> in Java). |
|
</p> |
|
|
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="Examples"> |
|
|
|
<p>Note that <code>@const</code> does not necessarily imply |
|
<code>CONSTANT_VALUES_CASE</code>. |
|
|
|
However, <code>CONSTANT_VALUES_CASE</code> |
|
<em>does</em> imply <code>@const</code>. |
|
</p> |
|
|
|
<CODE_SNIPPET> |
|
/** |
|
* Request timeout in milliseconds. |
|
* @type {number} |
|
*/ |
|
goog.example.TIMEOUT_IN_MILLISECONDS = 60; |
|
</CODE_SNIPPET> |
|
|
|
<p>The number of seconds in a minute never changes. It is a |
|
constant value. <code>ALL_CAPS</code> |
|
also implies <code>@const</code>, so the constant cannot be |
|
overwritten. |
|
</p> |
|
|
|
<p>The open source compiler will allow the symbol to be |
|
overwritten because the constant is |
|
<em>not</em> marked as <code>@const</code>.</p> |
|
|
|
<CODE_SNIPPET> |
|
/** |
|
* Map of URL to response string. |
|
* @const |
|
*/ |
|
MyClass.fetchedUrlCache_ = new goog.structs.Map(); |
|
</CODE_SNIPPET> |
|
|
|
<CODE_SNIPPET> |
|
/** |
|
* Class that cannot be subclassed. |
|
* @const |
|
* @constructor |
|
*/ |
|
sloth.MyFinalClass = function() {}; |
|
</CODE_SNIPPET> |
|
|
|
<p>In this case, the pointer can never be overwritten, but |
|
value is highly mutable and <b>not</b> constant (and thus in |
|
<code>camelCase</code>, not <code>ALL_CAPS</code>).</p> |
|
</SUBSECTION> |
|
|
|
</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. |
|
[ffVersion, ieVersion][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, ieVersion][isIE]()</code>.</li> |
|
<li><code>die</code> is always called since the array minus 1 is |
|
<code>NaN</code> which is never equal to anything (not even if |
|
<code>resultOfOperation()</code> returns <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> |
|
<SUBSECTION title="Clarification: Semicolons and functions"> |
|
<p>Semicolons should be included at the end of function expressions, |
|
but not at the end of function declarations. The distinction is |
|
best illustrated with an example:</p> |
|
<CODE_SNIPPET> |
|
var foo = function() { |
|
return true; |
|
}; // semicolon here. |
|
|
|
function foo() { |
|
return true; |
|
} // no semicolon here. |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Nested functions"> |
|
<SUMMARY>Yes</SUMMARY> |
|
<BODY> |
|
<p>Nested functions can be very useful, for example in the creation of |
|
continuations and for the task of hiding helper functions. Feel free |
|
to use them.</p> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Function Declarations Within Blocks"> |
|
<SUMMARY>No</SUMMARY> |
|
<BODY> |
|
<p>Do not do this:</p> |
|
<BAD_CODE_SNIPPET> |
|
if (x) { |
|
function foo() {} |
|
} |
|
</BAD_CODE_SNIPPET> |
|
|
|
<p>While most script engines support Function Declarations within blocks |
|
it is not part of ECMAScript (see |
|
<a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm">ECMA-262</a>, |
|
clause 13 and 14). Worse implementations are inconsistent with each |
|
other and with future EcmaScript proposals. ECMAScript only allows for |
|
Function Declarations in the root statement list of a script or |
|
function. Instead use a variable initialized with a Function |
|
Expression to define a function within a block:</p> |
|
<CODE_SNIPPET> |
|
if (x) { |
|
var foo = function() {}; |
|
} |
|
</CODE_SNIPPET> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<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="https://code.google.com/closure/library/"> |
|
the Closure Library |
|
</a> |
|
or a similar library function. |
|
</p> |
|
<CODE_SNIPPET> |
|
function D() { |
|
goog.base(this) |
|
} |
|
goog.inherits(D, B); |
|
|
|
D.prototype.method = function() { |
|
... |
|
}; |
|
</CODE_SNIPPET> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Method and property definitions"> |
|
<SUMMARY><code>/** @constructor */ |
|
function SomeConstructor() { |
|
this.someProperty = 1; |
|
} |
|
Foo.prototype.someMethod = function() { ... };</code></SUMMARY> |
|
<BODY> |
|
<p>While there are several ways to attach methods and properties to an |
|
object created via "new", the preferred style for methods |
|
is:</p> |
|
<CODE_SNIPPET> |
|
Foo.prototype.bar = function() { |
|
/* ... */ |
|
}; |
|
</CODE_SNIPPET> |
|
<p>The preferred style for other properties is to initialize the field |
|
in the constructor:</p> |
|
<CODE_SNIPPET> |
|
/** @constructor */ |
|
function Foo() { |
|
this.bar = value; |
|
} |
|
</CODE_SNIPPET> |
|
<SUBSECTION title="Why?"> |
|
<p>Current JavaScript engines optimize based on the "shape" |
|
of an object, <a href="https://developers.google.com/v8/design#prop_access"> |
|
adding a property to an object (including overriding |
|
a value set on the prototype) changes the shape and can degrade |
|
performance.</a></p> |
|
</SUBSECTION> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="delete"> |
|
<SUMMARY>Prefer <code>this.foo = null</code>.</SUMMARY> |
|
<BODY> |
|
<CODE_SNIPPET> |
|
Foo.prototype.dispose = function() { |
|
this.property_ = null; |
|
}; |
|
</CODE_SNIPPET> |
|
<p>Instead of:</p> |
|
<BAD_CODE_SNIPPET> |
|
Foo.prototype.dispose = function() { |
|
delete this.property_; |
|
}; |
|
</BAD_CODE_SNIPPET> |
|
<p>In modern JavaScript engines, changing the number of properties on an |
|
object is much slower than reassigning the values. The delete keyword |
|
should be avoided except when it is necessary to remove a property |
|
from an object's iterated list of keys, or to change the result of |
|
<code>if (key in obj)</code>.</p> |
|
</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 code loaders and REPL (Read–eval–print loop) |
|
</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, clearer, and safer way to write your code, |
|
so its use is generally not permitted.</p> |
|
|
|
<p>For RPC you can always use JSON and read the result using |
|
<code>JSON.parse()</code> instead of <code>eval()</code>.</p> |
|
|
|
<p>Let's assume we have a server that returns something like this:</p> |
|
|
|
<CODE_SNIPPET> |
|
{ |
|
"name": "Alice", |
|
"id": 31502, |
|
"email": "looking_glass@example.com" |
|
} |
|
</CODE_SNIPPET> |
|
|
|
<BAD_CODE_SNIPPET> |
|
var userInfo = eval(feed); |
|
var email = userInfo['email']; |
|
</BAD_CODE_SNIPPET> |
|
|
|
<p>If the feed was modified to include malicious JavaScript code, then |
|
if we use <code>eval</code> then that code will be executed.</p> |
|
|
|
<CODE_SNIPPET> |
|
var userInfo = JSON.parse(feed); |
|
var email = userInfo['email']; |
|
</CODE_SNIPPET> |
|
|
|
<p>With <code>JSON.parse</code>, invalid JSON (including all executable |
|
JavaScript) will cause an exception to be thrown.</p> |
|
|
|
</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. </p> |
|
<p>Use string concatenation instead:</p> |
|
<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.'; |
|
</CODE_SNIPPET> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Array and Object literals"> |
|
<SUMMARY>Yes</SUMMARY> |
|
<BODY> |
|
<p>Use <code>Array</code> and <code>Object</code> literals instead of |
|
<code>Array</code> and <code>Object</code> constructors.</p> |
|
<p>Array constructors are error-prone due to their arguments.</p> |
|
<BAD_CODE_SNIPPET> |
|
// Length is 3. |
|
var a1 = new Array(x1, x2, x3); |
|
|
|
// Length is 2. |
|
var a2 = new Array(x1, x2); |
|
|
|
// If x1 is a number and it is a natural number the length will be x1. |
|
// If x1 is a number but not a natural number this will throw an exception. |
|
// Otherwise the array will have one element with x1 as its value. |
|
var a3 = new Array(x1); |
|
|
|
// Length is 0. |
|
var a4 = new Array(); |
|
</BAD_CODE_SNIPPET> |
|
<p>Because of this, if someone changes the code to pass 1 argument |
|
instead of 2 arguments, the array might not have the expected |
|
length.</p> |
|
<p>To avoid these kinds of weird cases, always use the more readable |
|
array literal.</p> |
|
<CODE_SNIPPET> |
|
var a = [x1, x2, x3]; |
|
var a2 = [x1, x2]; |
|
var a3 = [x1]; |
|
var a4 = []; |
|
</CODE_SNIPPET> |
|
<p>Object constructors don't have the same problems, but for readability |
|
and consistency object literals should be used.</p> |
|
<BAD_CODE_SNIPPET> |
|
var o = new Object(); |
|
|
|
var o2 = new Object(); |
|
o2.a = 0; |
|
o2.b = 1; |
|
o2.c = 2; |
|
o2['strange key'] = 3; |
|
</BAD_CODE_SNIPPET> |
|
<p>Should be written as:</p> |
|
<CODE_SNIPPET> |
|
var o = {}; |
|
|
|
var o2 = { |
|
a: 0, |
|
b: 1, |
|
c: 2, |
|
'strange key': 3 |
|
}; |
|
</CODE_SNIPPET> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Modifying prototypes of builtin objects"> |
|
<SUMMARY>No</SUMMARY> |
|
<BODY> |
|
<p>Modifying builtins like <code>Object.prototype</code> and |
|
<code>Array.prototype</code> are strictly forbidden. Modifying other |
|
builtins like <code>Function.prototype</code> is less dangerous but |
|
still leads to hard to debug issues in production and should be |
|
avoided.</p> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Internet Explorer's Conditional Comments"> |
|
<SUMMARY>No</SUMMARY> |
|
<BODY> |
|
<p>Don't do this:</p> |
|
<BAD_CODE_SNIPPET> |
|
var f = function () { |
|
/*@cc_on if (@_jscript) { return 2* @*/ 3; /*@ } @*/ |
|
}; |
|
</BAD_CODE_SNIPPET> |
|
<p>Conditional Comments hinder automated tools as they can vary the |
|
JavaScript syntax tree at runtime.</p> |
|
</BODY> |
|
</STYLEPOINT> |
|
</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>, |
|
<code>CONSTANT_VALUES_LIKE_THIS</code>, |
|
<code>foo.namespaceNamesLikeThis.bar</code>, and |
|
<code>filenameslikethis.js</code>. |
|
</p> |
|
</SUMMARY> |
|
<BODY> |
|
<SUBSECTION title="Properties and methods"> |
|
<ul> |
|
<li><em>Private</em> properties and methods should be named with a |
|
trailing underscore. |
|
</li> |
|
<li><em>Protected</em> properties 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>EcmaScript 5 getters and setters for properties are discouraged. |
|
However, if they are used, then getters must not change observable |
|
state.</p> |
|
<BAD_CODE_SNIPPET> |
|
/** |
|
* WRONG -- Do NOT do this. |
|
*/ |
|
var foo = { get next() { return this.nextId++; } }; |
|
</BAD_CODE_SNIPPET> |
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="Accessor functions"> |
|
<p>Getters and setters methods 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="https://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 |
|
* @extends {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 |
|
* @extends {foo.hats.RoundHat} |
|
*/ |
|
googleyhats.BowlerHat = function() { |
|
... |
|
}; |
|
|
|
goog.exportSymbol('foo.hats.BowlerHat', googleyhats.BowlerHat); |
|
</CODE_SNIPPET> |
|
|
|
|
|
</SUBSUBSECTION> |
|
<SUBSUBSECTION title="Alias long type names to improve readability"> |
|
<p>Use local aliases for fully-qualified types if doing so improves |
|
readability. The name of a local alias should match the last part |
|
of the type.</p> |
|
<CODE_SNIPPET> |
|
/** |
|
* @constructor |
|
*/ |
|
some.long.namespace.MyClass = function() { |
|
}; |
|
|
|
/** |
|
* @param {some.long.namespace.MyClass} a |
|
*/ |
|
some.long.namespace.MyClass.staticHelper = function(a) { |
|
... |
|
}; |
|
|
|
myapp.main = function() { |
|
var MyClass = some.long.namespace.MyClass; |
|
var staticHelper = some.long.namespace.MyClass.staticHelper; |
|
staticHelper(new MyClass()); |
|
}; |
|
</CODE_SNIPPET> |
|
<p>Do not create local aliases of namespaces. Namespaces should only |
|
be aliased using <a href="#goog-scope">goog.scope</a>.</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> |
|
</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 information.</SUMMARY> |
|
<BODY> |
|
<p>We follow the <a href="cppguide.html#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, with the braces on their own line, 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. Emphasizes each |
|
// individual argument. |
|
function bar(veryDescriptiveArgumentNumberOne, |
|
veryDescriptiveArgumentTwo, |
|
tableModelEventHandlerProxy, |
|
artichokeDescriptorAdapterIterator) { |
|
// ... |
|
} |
|
</CODE_SNIPPET> |
|
<p>When the function call is itself indented, you're free to start the |
|
4-space indent relative to the beginning of the original statement |
|
or relative to the beginning of the current function call. |
|
The following are all acceptable indentation styles.</p> |
|
<CODE_SNIPPET> |
|
if (veryLongFunctionNameA( |
|
veryLongArgumentName) || |
|
veryLongFunctionNameB( |
|
veryLongArgumentName)) { |
|
veryLongFunctionNameC(veryLongFunctionNameD( |
|
veryLongFunctioNameE( |
|
veryLongFunctionNameF))); |
|
} |
|
</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 statement, or 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> |
|
prefix.something.reallyLongFunctionName('whatever', function(a1, a2) { |
|
if (a1.equals(a2)) { |
|
someOtherLongFunctionName(a1); |
|
} else { |
|
andNowForSomethingCompletelyDifferent(a2.parrot); |
|
} |
|
}); |
|
|
|
var names = prefix.something.myExcellentMapFunction( |
|
verboselyNamedCollectionOfItems, |
|
function(item) { |
|
return item.name; |
|
}); |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
<SUBSECTION title="Aliasing with goog.scope"> |
|
<a name="goog-scope"/> |
|
<p> |
|
<a href="https://docs.google.com/document/pub?id=1ETFAuh2kaXMVL-vafUYhaWlhl6b5D9TOvboVg7Zl68Y"><code>goog.scope</code></a> |
|
may be used to shorten references to |
|
namespaced symbols in programs using |
|
<a href="https://code.google.com/closure/library/">the Closure |
|
Library</a>.</p> |
|
<p>Only one <code>goog.scope</code> invocation may be added per |
|
file. Always place it in the global scope.</p> |
|
<p>The opening <code>goog.scope(function() {</code> invocation |
|
must be preceded by exactly one blank line and follow any |
|
<code>goog.provide</code> statements, <code>goog.require</code> |
|
statements, or top-level comments. The invocation must be closed on |
|
the last line in the file. Append <code>// goog.scope</code> to the |
|
closing statement of the scope. Separate the comment from the |
|
semicolon by two spaces.</p> |
|
<p>Similar to C++ namespaces, do not indent under goog.scope |
|
declarations. Instead, continue from the 0 column.</p> |
|
<p>Only alias names that will not be re-assigned to another object |
|
(e.g., most constructors, enums, and namespaces). Do not do |
|
this (see below for how to alias a constructor):</p> |
|
|
|
<BAD_CODE_SNIPPET> |
|
goog.scope(function() { |
|
var Button = goog.ui.Button; |
|
|
|
Button = function() { ... }; |
|
... |
|
</BAD_CODE_SNIPPET> |
|
|
|
<p>Names must be the same as the last property of the global that they |
|
are aliasing.</p> |
|
|
|
<CODE_SNIPPET> |
|
goog.provide('my.module.SomeType'); |
|
|
|
goog.require('goog.dom'); |
|
goog.require('goog.ui.Button'); |
|
|
|
goog.scope(function() { |
|
var Button = goog.ui.Button; |
|
var dom = goog.dom; |
|
|
|
// Alias new types <b>after</b> the constructor declaration. |
|
my.module.SomeType = function() { ... }; |
|
var SomeType = my.module.SomeType; |
|
|
|
// Declare methods on the prototype as usual: |
|
SomeType.prototype.findButton = function() { |
|
// Button as aliased above. |
|
this.button = new Button(dom.getElement('my-button')); |
|
}; |
|
... |
|
}); // goog.scope |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
<SUBSECTION title="Indenting wrapped lines"> |
|
<p>Except for <a href="#Array_and_Object_literals">array literals, |
|
object literals</a>, and anonymous functions, all wrapped lines |
|
should be indented either left-aligned to a sibling expression |
|
above, or four spaces (not two spaces) deeper than a parent |
|
expression (where "sibling" and "parent" refer to parenthesis |
|
nesting level). |
|
</p> |
|
|
|
<CODE_SNIPPET> |
|
someWonderfulHtml = '<div class="' + getClassesForWonderfulHtml()'">' + |
|
getEvenMoreHtml(someReallyInterestingValues, moreValues, |
|
evenMoreParams, 'a duck', true, 72, |
|
slightlyMoreMonkeys(0xfff)) + |
|
'</div>'; |
|
|
|
thisIsAVeryLongVariableName = |
|
hereIsAnEvenLongerOtherFunctionNameThatWillNotFitOnPrevLine(); |
|
|
|
thisIsAVeryLongVariableName = siblingOne + siblingTwo + siblingThree + |
|
siblingFour + siblingFive + siblingSix + siblingSeven + |
|
moreSiblingExpressions + allAtTheSameIndentationLevel; |
|
|
|
thisIsAVeryLongVariableName = operandOne + operandTwo + operandThree + |
|
operandFour + operandFive * ( |
|
aNestedChildExpression + shouldBeIndentedMore); |
|
|
|
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() || |
|
client.alwaysTryAmbientAnyways())) { |
|
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. Otherwise, |
|
line breaks and indentation follow the same rules as in other |
|
Google style guides. This operator placement was initially agreed |
|
upon out of concerns about automatic semicolon insertion. In fact, |
|
semicolon insertion cannot happen before a binary operator, but new |
|
code should stick to this style for consistency.</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> |
|
<p>This includes the dot operator.</p> |
|
<CODE_SNIPPET> |
|
var x = foo.bar(). |
|
doSomething(). |
|
doSomethingElse(); |
|
</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>, <code>in</code> 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>The --jscomp_warning=visibility compiler flag turns on compiler |
|
warnings for visibility violations. See |
|
<a href="https://code.google.com/p/closure-compiler/wiki/Warnings"> |
|
Closure Compiler |
|
Warnings</a>. |
|
</p> |
|
<p><code>@private</code> global variables and functions are only |
|
accessible to code in the same file.</p> |
|
<p>Constructors marked <code>@private</code> may only be instantiated by |
|
code in the same file and by their static and instance members. |
|
<code>@private</code> constructors may also be accessed anywhere in the |
|
same file for their public static properties and by the |
|
<code>instanceof</code> operator.</p> |
|
<p>Global variables, functions, and constructors should never be |
|
annotated <code>@protected</code>.</p> |
|
<CODE_SNIPPET> |
|
// File 1. |
|
// AA_PrivateClass_ and AA_init_ are accessible because they are global |
|
// and in the same file. |
|
|
|
/** |
|
* @private |
|
* @constructor |
|
*/ |
|
AA_PrivateClass_ = function() { |
|
}; |
|
|
|
/** @private */ |
|
function AA_init_() { |
|
return new AA_PrivateClass_(); |
|
} |
|
|
|
AA_init_(); |
|
</CODE_SNIPPET> |
|
<p><code>@private</code> properties are accessible to all code in the |
|
same file, plus all static methods and instance methods of that class |
|
that "owns" the property, if the property belongs to a class. They |
|
cannot be accessed or overridden from a subclass in a different file.</p> |
|
<p><code>@protected</code> properties are accessible to all code in the |
|
same file, plus any static methods and instance methods of any subclass |
|
of a class that "owns" the property.</p> |
|
<p>Note that these semantics differ from those of C++ and Java, in that |
|
they grant private and protected access to all code in the same file, |
|
not just in the same class or class hierarchy. Also, unlike in C++, |
|
private properties cannot be overridden by a subclass. |
|
</p> |
|
<CODE_SNIPPET> |
|
// File 1. |
|
|
|
/** @constructor */ |
|
AA_PublicClass = function() { |
|
/** @private */ |
|
this.privateProp_ = 2; |
|
|
|
/** @protected */ |
|
this.protectedProp = 4; |
|
}; |
|
|
|
/** @private */ |
|
AA_PublicClass.staticPrivateProp_ = 1; |
|
|
|
/** @protected */ |
|
AA_PublicClass.staticProtectedProp = 31; |
|
|
|
/** @private */ |
|
AA_PublicClass.prototype.privateMethod_ = function() {}; |
|
|
|
/** @protected */ |
|
AA_PublicClass.prototype.protectedMethod = function() {}; |
|
|
|
// 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> |
|
|
|
<p>Notice that in JavaScript, there is no distinction between a type |
|
(like <code>AA_PrivateClass_</code>) and the constructor for that |
|
type. There is no way to express both that a type is public and its |
|
constructor is private (because the constructor could easily be aliased |
|
in a way that would defeat the privacy check).</p> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="JavaScript Types"> |
|
<SUMMARY>Encouraged and enforced by the compiler.</SUMMARY> |
|
<BODY> |
|
<a name="JsTypes"/> |
|
<p>When documenting a type in JSDoc, be as specific and accurate as |
|
possible. The types we support are based on the |
|
<a href="http://wiki.ecmascript.org/doku.php?id=spec:spec"> |
|
EcmaScript 4 spec</a>.</p> |
|
<SUBSECTION title="The JavaScript Type Language"> |
|
<p>The ES4 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 ES4 proposal has evolved, this language has changed. The |
|
compiler still supports old syntaxes for types, but those syntaxes |
|
are deprecated.</p> |
|
|
|
<p/> |
|
<table border="1" style="border-collapse:collapse" cellpadding="4"> |
|
<thead> |
|
<tr> |
|
<th>Syntax Name</th> |
|
<th>Syntax</th> |
|
<th>Description</th> |
|
<th>Deprecated Syntaxes</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
<tr> |
|
<td>Primitive Type</td> |
|
<td> |
|
There are 5 primitive types in JavaScript: |
|
<code>{null}</code>, |
|
<code>{undefined}</code>, |
|
<code>{boolean}</code>, |
|
<code>{number}</code>, and |
|
<code>{string}</code>. |
|
</td> |
|
<td>Simply the name of a type.</td> |
|
<td/> |
|
</tr> |
|
|
|
<tr> |
|
<td>Instance Type</td> |
|
<td> |
|
<code>{Object}</code><br/> |
|
An instance of Object or null.<p/> |
|
<code>{Function}</code><br/> |
|
An instance of Function or null.<p/> |
|
<code>{EventTarget}</code><br/> |
|
An instance of a constructor that implements the EventTarget |
|
interface, or null. |
|
</td> |
|
<td>An instance of a constructor or interface function.<p/> |
|
|
|
Constructor functions are functions defined with the |
|
<code>@constructor</code> JSDoc tag. |
|
Interface functions are functions defined with the |
|
<code>@interface</code> JSDoc tag.<p/> |
|
|
|
By default, instance types will accept null. This is the only |
|
type syntax that makes the type nullable. Other type syntaxes |
|
in this table will not accept null. |
|
</td> |
|
<td/> |
|
</tr> |
|
|
|
<tr> |
|
<td>Enum Type</td> |
|
<td> |
|
<code>{goog.events.EventType}</code><br/> |
|
One of the properties of the object literal initializer |
|
of <code>goog.events.EventType</code>. |
|
</td> |
|
<td>An enum must be initialized as an object literal, or as |
|
an alias of another enum, annotated with the <code>@enum</code> |
|
JSDoc tag. The properties of this literal are the instances |
|
of the enum. The syntax of the enum is defined |
|
<a href="#enums">below</a>.<p/> |
|
|
|
Note that this is one of the few things in our type system |
|
that were not in the ES4 spec. |
|
</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>Parameterizes 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.<p/> |
|
|
|
The parentheses may be omitted at the top-level |
|
expression, but the parentheses should be included in |
|
sub-expressions to avoid ambiguity.<br/> |
|
<code>{number|boolean}</code><br/> |
|
<code>{function(): (number|boolean)}</code> |
|
</td> |
|
<td> |
|
<code>{(number,boolean)}</code>,<br/> |
|
<code>{(number||boolean)}</code> |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td>Nullable type</td> |
|
<td> |
|
<code>{?number}</code><br/> A number or null. |
|
</td> |
|
<td>Shorthand for the union of the null type with any |
|
other type. This is just syntactic sugar. |
|
</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>Filters null out of nullable types. Most often used |
|
with instance types, which are nullable by default. |
|
</td> |
|
<td> |
|
<code>{Object!}</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>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>Function <code>new</code> Type</td> |
|
<td> |
|
<code>{function(new:goog.ui.Menu, string)}</code><br/> |
|
A constructor that takes one argument (a string), and |
|
creates a new instance of goog.ui.Menu when called |
|
with the 'new' keyword. |
|
</td> |
|
<td>Specifies the constructed type of a constructor.</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> |
|
|
|
<tr> |
|
<td>The UNKNOWN type</td> |
|
<td><code>{?}</code></td> |
|
<td>Indicates that the variable can take on any type, |
|
and the compiler should not type-check any uses of it.</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 converted to strings, so |
|
<code>obj['1'] == obj[1]</code>. |
|
So the key will always be a string in for...in loops. But the |
|
compiler will verify the type of 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><a name="constructor-tag">SomeClass</a></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 = { |
|
/** The color blue. */ |
|
BLUE: '#0000dd', |
|
/** The color red. */ |
|
RED: '#dd0000' |
|
}; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td><a name="enums">Enumeration</a><p/> |
|
JSDoc comments on enum values are optional. |
|
</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="Type Casts"> |
|
<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 |
|
parentheses. The parentheses are required.</p> |
|
|
|
<CODE_SNIPPET> |
|
/** @type {number} */ (x) |
|
</CODE_SNIPPET> |
|
</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>Instances of classes and interfaces are nullable by default. |
|
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> |
|
|
|
<SUBSECTION title="Typedefs"> |
|
<a name="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="Template types"> |
|
<a name="Template_types"/> |
|
<p>The compiler has limited support for template types. It can only |
|
infer the type of <code>this</code> inside an anonymous function |
|
literal from the type of the <code>this</code> argument and whether the |
|
<code>this</code> argument is missing.</p> |
|
|
|
<CODE_SNIPPET> |
|
/** |
|
* @param {function(this:T, ...)} fn |
|
* @param {T} thisObj |
|
* @param {...*} var_args |
|
* @template T |
|
*/ |
|
goog.bind = function(fn, thisObj, var_args) { |
|
... |
|
}; |
|
// Possibly generates a missing property warning. |
|
goog.bind(function() { this.someProperty; }, new SomeClass()); |
|
// Generates an undefined this warning. |
|
goog.bind(function() { this.someProperty; }); |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Comments"> |
|
<SUMMARY>Use JSDoc</SUMMARY> |
|
<BODY> |
|
<p> |
|
We follow the |
|
<a href="cppguide.html#Comments"> |
|
C++ style for comments</a> in spirit. |
|
</p> |
|
|
|
<p>All files, classes, methods and properties should be documented with |
|
<a href="https://code.google.com/p/jsdoc-toolkit/">JSDoc</a> |
|
comments with the appropriate <a href="#JSDoc_Tag_Reference">tags</a> |
|
and <a href="#JsTypes">types</a>. Textual descriptions for properties, |
|
methods, method parameters and method return values should be included |
|
unless obvious from the property, method, or parameter name. |
|
</p> |
|
|
|
<p>Inline comments should be of the <code>//</code> variety.</p> |
|
|
|
<p>Complete sentences are recommended but not required. |
|
Complete sentences should use appropriate capitalization |
|
and punctuation.</p> |
|
|
|
<SUBSECTION title="Comment Syntax"> |
|
<p>The JSDoc syntax is based on |
|
<a href="https://www.oracle.com/technetwork/java/javase/documentation/index-137868.html"> |
|
JavaDoc</a>. Many tools extract metadata from JSDoc comments to |
|
perform code validation and optimizations. These comments must be |
|
well-formed.</p> |
|
|
|
<CODE_SNIPPET> |
|
/** |
|
* A JSDoc comment should begin with a slash and 2 asterisks. |
|
* Inline tags should be enclosed in braces like {@code this}. |
|
* @desc Block tags should always start on their own line. |
|
*/ |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="JSDoc Indentation"> |
|
<p>If you have to line break a block tag, 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. You do not have to |
|
indent the <code>@desc</code> command.</p> |
|
|
|
<p>Even though it is not preferred, it is also acceptable to line up |
|
the description.</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="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> |
|
|
|
<BAD_CODE_SNIPPET> |
|
Computes weight based on three factors: items sent items received last timestamp |
|
</BAD_CODE_SNIPPET> |
|
|
|
<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> |
|
|
|
The <a href="https://www.oracle.com/technetwork/java/javase/documentation/index-137868.html"> |
|
JavaDoc</a> style guide is a useful resource on how to write |
|
well-formed doc comments. |
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="Top/File-Level Comments"> |
|
<p> |
|
|
|
A <a href="copyright.html">copyright notice</a> and author information are optional. |
|
File overviews are generally recommended whenever a file consists of |
|
more than a single class definition. The top level comment is |
|
designed to orient readers unfamiliar with the code to what is in |
|
this file. If present, it should provide a description of the |
|
file's contents and any dependencies or compatibility information. |
|
As an example: |
|
</p> |
|
|
|
<CODE_SNIPPET> |
|
/** |
|
* @fileoverview Description of file, its uses and information |
|
* about its dependencies. |
|
*/ |
|
</CODE_SNIPPET> |
|
|
|
|
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="Class Comments"> |
|
<p>Classes must be documented with a description and a |
|
<a href="#constructor-tag">type tag that |
|
identifies the constructor</a>. |
|
</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>Parameter and return types should be documented. The method |
|
description may be omitted if it is obvious from the parameter |
|
or return type descriptions. Method descriptions should start |
|
with a sentence written in the third person declarative voice.</p> |
|
<CODE_SNIPPET> |
|
/** |
|
* 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 occurred. |
|
*/ |
|
function PR_someMethod(obj) { |
|
// ... |
|
} |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="Property Comments"> |
|
<CODE_SNIPPET> |
|
/** @constructor */ |
|
project.MyClass = function() { |
|
/** |
|
* Maximum number of things per pane. |
|
* @type {number} |
|
*/ |
|
this.someProperty = 4; |
|
} |
|
</CODE_SNIPPET> |
|
</SUBSECTION> |
|
|
|
<SUBSECTION title="JSDoc Tag Reference"> |
|
<a name="JSDoc_Tag_Reference"/> |
|
<p/> |
|
<table border="1" style="border-collapse:collapse" cellpadding="4"> |
|
<thead> |
|
<tr> |
|
<th>Tag</th> |
|
<th>Template & Examples</th> |
|
<th>Description</th> |
|
</tr> |
|
</thead> |
|
<tbody> |
|
<tr> |
|
<td> |
|
<a name="tag-author">@author</a> |
|
|
|
</td> |
|
<td> |
|
<code>@author username@google.com (first last)</code> |
|
<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> |
|
</tr> |
|
|
|
|
|
|
|
<tr> |
|
<td><a name="tag-code">@code</a></td> |
|
<td> |
|
<code>{@code ...}</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-const">@const</a></td> |
|
<td> |
|
<code>@const</code><br/> |
|
<code>@const {type}</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** @const */ var MY_BEER = 'stout'; |
|
|
|
/** |
|
* My namespace's favorite kind of beer. |
|
* @const {string} |
|
*/ |
|
mynamespace.MY_BEER = 'stout'; |
|
|
|
/** @const */ MyClass.MY_BEER = 'stout'; |
|
|
|
/** |
|
* Initializes the request. |
|
* @const |
|
*/ |
|
mynamespace.Request.prototype.initialize = function() { |
|
// This method cannot be overridden in a subclass. |
|
}; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
<p>Marks a variable (or property) as read-only and suitable |
|
for inlining.</p> |
|
|
|
<p>A <code>@const</code> variable is an immutable pointer to |
|
a value. If a variable or property marked as |
|
<code>@const</code> is overwritten, JSCompiler will give |
|
warnings.</p> |
|
|
|
<p>The type declaration of a constant value can be omitted |
|
if it can be clearly inferred. An additional comment about |
|
the variable is optional.</p> |
|
|
|
<p>When <code>@const</code> is applied to a method, it |
|
implies the method is not only not overwritable, but also |
|
that the method is <em>finalized</em> — |
|
not overridable in subclasses.</p> |
|
|
|
<p>For more on <code>@const</code>, see the |
|
<a href="#Constants">Constants</a> section.</p> |
|
|
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-constructor">@constructor</a></td> |
|
<td> |
|
<code>@constructor</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-define">@define</a></td> |
|
<td> |
|
<code>@define {Type} description</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** @define {boolean} */ |
|
var TR_FLAGS_ENABLE_DEBUG = true; |
|
|
|
/** |
|
* @define {boolean} Whether we know at compile-time that |
|
* the browser is IE. |
|
*/ |
|
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 |
|
<code>--define='goog.userAgent.ASSUME_IE=true'</code> |
|
could be specified in the BUILD file to indicate that the |
|
constant <code>goog.userAgent.ASSUME_IE</code> should be replaced |
|
with <code>true</code>. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-deprecated">@deprecated</a></td> |
|
<td> |
|
<code>@deprecated Description</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-dict">@dict</a></td> |
|
<td> |
|
<code>@dict Description</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* @constructor |
|
* @dict |
|
*/ |
|
function Foo(x) { |
|
this['x'] = x; |
|
} |
|
var obj = new Foo(123); |
|
var num = obj.x; // warning |
|
|
|
(/** @dict */ { x: 1 }).x = 123; // warning |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
When a constructor (<code>Foo</code> in the example) is |
|
annotated with <code>@dict</code>, you can only use the |
|
bracket notation to access the properties of <code>Foo</code> |
|
objects. |
|
The annotation can also be used directly on object literals. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-enum">@enum</a></td> |
|
<td> |
|
<code>@enum {Type}</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-export">@export</a></td> |
|
<td> |
|
<code>@export</code> |
|
<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 <code>--generate_exports</code> 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 <code>@export</code> annotation must either</p> |
|
<ol> |
|
<li>include <code>//javascript/closure/base.js</code>, or</li> |
|
<li>define both <code>goog.exportSymbol</code> and |
|
<code>goog.exportProperty</code> with the same method |
|
signature in their own codebase.</li> |
|
</ol> |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-expose">@expose</a></td> |
|
<td> |
|
<code>@expose</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** @expose */ |
|
MyClass.prototype.exposedProperty = 3; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
<p> |
|
Declares an exposed property. Exposed properties |
|
will not be removed, or renamed, or collapsed, |
|
or optimized in any way by the compiler. No properties |
|
with the same name will be able to be optimized either. |
|
</p> |
|
|
|
<p> |
|
<code>@expose</code> should never be used in library code, |
|
because it will prevent that property from ever getting |
|
removed. |
|
</p> |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-extends">@extends</a></td> |
|
<td> |
|
<code> |
|
@extends Type<br/> |
|
@extends {Type} |
|
</code> |
|
<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 <code>@constructor</code> to indicate that a class |
|
inherits from another class. Curly braces around the type are |
|
optional. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-externs">@externs</a></td> |
|
<td> |
|
<code>@externs</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-fileoverview">@fileoverview</a></td> |
|
<td> |
|
<code>@fileoverview Description</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-implements">@implements</a></td> |
|
<td> |
|
<code> |
|
@implements Type<br/> |
|
@implements {Type} |
|
</code> |
|
<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 <code>@constructor</code> to indicate that a class |
|
implements an interface. Curly braces around the type are |
|
optional. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-inheritDoc">@inheritDoc</a></td> |
|
<td> |
|
<code>@inheritDoc</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** @inheritDoc */ |
|
project.SubClass.prototype.toString() { |
|
// ... |
|
}; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
<p style="font-weight:bold">Deprecated. Use |
|
<code>@override</code> instead.</p> |
|
|
|
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 |
|
<code>@inheritDoc</code> implies <code>@override</code> |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-interface">@interface</a></td> |
|
<td> |
|
<code>@interface</code> |
|
<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 interface. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-lends">@lends</a></td> |
|
<td> |
|
<code>@lends objectName</code><br/> |
|
<code>@lends {objectName}</code> |
|
<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, <code>@type {Foo}</code> means "an instance of Foo", |
|
but <code>@lends {Foo}</code> means "the constructor Foo".<p/> |
|
|
|
The <a href="https://code.google.com/p/jsdoc-toolkit/wiki/TagLends"> |
|
JSDoc Toolkit docs</a> have more information on this |
|
annotation. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-license">@license</a> or |
|
<a name="tag-preserve">@preserve</a></td> |
|
<td> |
|
<code>@license Description</code> |
|
<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 <code>@license</code> or |
|
<code>@preserve</code> 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> |
|
</tr> |
|
|
|
|
|
|
|
|
|
|
|
<tr> |
|
<td><a name="tag-noalias">@noalias</a></td> |
|
<td> |
|
<code>@noalias</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-nocompile">@nocompile</a></td> |
|
<td> |
|
<code>@nocompile</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** @nocompile */ |
|
|
|
// JavaScript code |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
Used at the top of a file to tell the compiler to parse this |
|
file but not compile it. |
|
Code that is not meant for compilation and should be omitted |
|
from compilation tests (such as bootstrap code) uses this |
|
annotation. |
|
Use sparingly. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-nosideeffects">@nosideeffects</a></td> |
|
<td> |
|
<code>@nosideeffects</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-override">@override</a></td> |
|
<td> |
|
<code>@override</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* @return {string} Human-readable representation of project.SubClass. |
|
* @override |
|
*/ |
|
project.SubClass.prototype.toString = function() { |
|
// ... |
|
}; |
|
</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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-param">@param</a></td> |
|
<td> |
|
<code>@param {Type} varname Description</code> |
|
<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.<p/> |
|
|
|
<a href="#JsTypes">Type</a> |
|
names must be enclosed in curly braces. If the type |
|
is omitted, the compiler will not type-check the parameter. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-private">@private</a></td> |
|
<td> |
|
<code>@private</code><br/> |
|
<code>@private {type}</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* Handlers that are listening to this logger. |
|
* @private {!Array.<Function>} |
|
*/ |
|
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> and final. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-protected">@protected</a></td> |
|
<td> |
|
<code>@protected</code><br/> |
|
<code>@protected {type}</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* Sets the component's root element to the given element. |
|
* @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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-public">@public</a></td> |
|
<td> |
|
<code>@public</code><br/> |
|
<code>@public {type}</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* Whether to cancel the event in internal capture/bubble processing. |
|
* @public {boolean} |
|
* @suppress {visiblity} Referencing this outside this package is strongly |
|
* discouraged. |
|
*/ |
|
goog.events.Event.prototype.propagationStopped_ = false; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
Used to indicate that the member or property is public. Variables and |
|
properties are public by default, so this annotation is rarely necessary. |
|
Should only be used in legacy code that cannot be easily changed to |
|
override the visibility of members that were named as private variables. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-return">@return</a></td> |
|
<td> |
|
<code>@return {Type} Description</code> |
|
<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.<p/> |
|
|
|
<a href="#JsTypes">Type</a> |
|
names must be enclosed in curly braces. If the type |
|
is omitted, the compiler will not type-check the return value. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-see">@see</a></td> |
|
<td> |
|
<code>@see Link</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-struct">@struct</a></td> |
|
<td> |
|
<code>@struct Description</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* @constructor |
|
* @struct |
|
*/ |
|
function Foo(x) { |
|
this.x = x; |
|
} |
|
var obj = new Foo(123); |
|
var num = obj['x']; // warning |
|
obj.y = "asdf"; // warning |
|
|
|
Foo.prototype = /** @struct */ { |
|
method1: function() {} |
|
}; |
|
Foo.prototype.method2 = function() {}; // warning |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
When a constructor (<code>Foo</code> in the example) is |
|
annotated with <code>@struct</code>, you can only use the dot |
|
notation to access the properties of <code>Foo</code> objects. |
|
Also, you cannot add new properties to <code>Foo</code> |
|
objects after they have been created. |
|
The annotation can also be used directly on object literals. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-supported">@supported</a></td> |
|
<td> |
|
<code>@supported Description</code> |
|
<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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-suppress">@suppress</a></td> |
|
<td> |
|
<code> |
|
@suppress {warning1|warning2} |
|
</code> |
|
<code> |
|
@suppress {warning1,warning2} |
|
</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* @suppress {deprecated} |
|
*/ |
|
function f() { |
|
deprecatedVersionOfF(); |
|
} |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
Suppresses warnings from tools. Warning categories are |
|
separated by <code>|</code> or <code>,</code>. |
|
|
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-template">@template</a></td> |
|
<td> |
|
<code>@template</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* @param {function(this:T, ...)} fn |
|
* @param {T} thisObj |
|
* @param {...*} var_args |
|
* @template T |
|
*/ |
|
goog.bind = function(fn, thisObj, var_args) { |
|
... |
|
}; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
This annotation can be used to declare a |
|
<a href="#Template_types">template typename</a>. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-this">@this</a></td> |
|
<td> |
|
<code> |
|
@this Type<br/> |
|
@this {Type} |
|
</code> |
|
<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 <code>this</code> keyword is referenced |
|
from a function that is not a prototype method. |
|
</td> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-type">@type</a></td> |
|
<td> |
|
<code> |
|
@type Type<br/> |
|
@type {Type} |
|
</code> |
|
<p><i>For example:</i></p> |
|
<CODE_SNIPPET> |
|
/** |
|
* The message hex ID. |
|
* @type {string} |
|
*/ |
|
var hexId = hexId; |
|
</CODE_SNIPPET> |
|
</td> |
|
<td> |
|
Identifies the <a href="#JsTypes">type</a> 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> |
|
</tr> |
|
|
|
<tr> |
|
<td><a name="tag-typedef">@typedef</a></td> |
|
<td> |
|
<code>@typedef</code> |
|
<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 |
|
<a href="#Typedefs">complex type</a>. |
|
</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="https://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> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Providing Dependencies With goog.provide"> |
|
<SUMMARY> |
|
Only provide top-level symbols. |
|
</SUMMARY> |
|
<BODY> |
|
<p> |
|
All members defined on a class should be in the same file. So, only |
|
top-level classes should be provided in a file that contains multiple |
|
members defined on the same class (e.g. enums, inner classes, etc). |
|
</p> |
|
<p>Do this:</p> |
|
<CODE_SNIPPET> |
|
goog.provide('namespace.MyClass'); |
|
</CODE_SNIPPET> |
|
<p>Not this:</p> |
|
<BAD_CODE_SNIPPET> |
|
goog.provide('namespace.MyClass'); |
|
goog.provide('namespace.MyClass.Enum'); |
|
goog.provide('namespace.MyClass.InnerClass'); |
|
goog.provide('namespace.MyClass.TypeDef'); |
|
goog.provide('namespace.MyClass.CONSTANT'); |
|
goog.provide('namespace.MyClass.staticMethod'); |
|
</BAD_CODE_SNIPPET> |
|
<p> |
|
Members on namespaces may also be provided: |
|
</p> |
|
<CODE_SNIPPET> |
|
goog.provide('foo.bar'); |
|
goog.provide('foo.bar.method'); |
|
goog.provide('foo.bar.CONSTANT'); |
|
</CODE_SNIPPET> |
|
</BODY> |
|
</STYLEPOINT> |
|
|
|
<STYLEPOINT title="Compiling"> |
|
<SUMMARY>Required</SUMMARY> |
|
<BODY> |
|
|
|
|
|
<p>Use of JS compilers such as the |
|
<a href="https://code.google.com/closure/compiler/">Closure Compiler</a> |
|
is required for all customer-facing code.</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) { |
|
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="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"> |
|
Revision 2.93 |
|
</p> |
|
|
|
|
|
<address> |
|
Aaron Whyte<br/> |
|
Bob Jervis<br/> |
|
Dan Pupius<br/> |
|
Erik Arvidsson<br/> |
|
Fritz Schneider<br/> |
|
Robby Walker<br/> |
|
</address> |
|
</GUIDE>
|
|
|