mirror of
https://github.com/google/styleguide.git
synced 2024-03-22 13:11:43 +08:00
505ba68c74
This reverts commit 54cca78d64
.
3630 lines
131 KiB
XML
3630 lines
131 KiB
XML
<?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>
|