Google的编程样式指南,原文地址:http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml?showone=var#var
var :
When you fail to specify var
, 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 var
.
constants:
Use NAMES_LIKE_THIS
for constants. Use @const
where appropriate. Never use the const
keyword
For simple primitive value constants, the naming convention is enough.
/** * The number of seconds in a minute. * @type {number} */ goog.example.SECONDS_IN_A_MINUTE = 60;
For non-primitives, use the @const
annotation.
/** * The number of seconds in each of the given units. * @type {Object.<number>} * @const */ goog.example.SECONDS_TABLE = { minute: 60, hour: 60 * 60 day: 60 * 60 * 24 }
This allows the compiler to enforce constant-ness.
As for the const
keyword, Internet Explorer doesn't parse it, so don't use it.
function declarations within block:
Do not do this:
if (x) { function foo() {} }
While most script engines support Function Declarations within blocks it is not part of ECMAScript (see ECMA-262, 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:
if (x) { var foo = function() {} }
There's no reason to use wrapper objects for primitive types, plus they're dangerous:
var x = new Boolean(false); if (x) { alert('hi'); // Shows 'hi'. }
Don't do it! However type casting is fine.
var x = Boolean(0); if (x) { alert('hi'); // This will never be alerted. } typeof Boolean(0) == 'boolean'; typeof new Boolean(0) == 'object';
This is very useful for casting things to number
, string
and boolean
.
function foo(element, a, b) { element.onclick = function() { /* uses a and b */ }; }
the function closure keeps a reference to element
, a
, and b
even if it never uses element
. Since element
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:
function foo(element, a, b) { element.onclick = bar(a, b); } function bar(a, b) { return function() { /* uses a and b */ } }
eval()
makes for confusing semantics and is dangerous to use if the string being eval()
'd contains user input. There's usually a better, more clear, safer way to write your code, so its use is generally not permitted. However eval
makes deserialization considerably easier than the non-eval
alternatives, so its use is acceptable for this task (for example, to evaluate RPC responses).
Deserialization is the process of transforming a series of bytes into an in-memory data structure. For example, you might write objects out to a file as:
users = [ { name: 'Eric', id: 37824, email: 'jellyvore@myway.com' }, { name: 'xtof', id: 31337, email: 'b4d455h4x0r@google.com' }, ... ];
Reading these data back into memory is as simple as eval
ing the string representation of the file.
Similarly, eval()
can simplify decoding RPC return values. For example, you might use an XMLHttpRequest
to make an RPC, and in its response the server can return JavaScript:
var userOnline = false; var user = 'nusrat'; var xmlhttp = new XMLHttpRequest(); xmlhttp.open('GET', 'http://chat.google.com/isUserOnline?user=' + user, false); xmlhttp.send(''); // Server returns: // userOnline = true; if (xmlhttp.status == 200) { eval(xmlhttp.responseText); } // userOnline is now true.