Google JavaScript Style Guide.docx
《Google JavaScript Style Guide.docx》由会员分享,可在线阅读,更多相关《Google JavaScript Style Guide.docx(63页珍藏版)》请在冰点文库上搜索。
GoogleJavaScriptStyleGuide
GoogleJavaScriptStyleGuide
Revision2.11
AaronWhyte
BobJervis
DanPupius
EricArvidsson
FritzSchneider
RobbyWalker
Eachstylepointhasasummaryforwhichadditionalinformationisavailablebytogglingtheaccompanyingarrowbuttonthatlooksthisway:
▽.Youmaytoggleallsummarieswiththebigarrowbutton:
▽ Toggleallsummaries
TableofContents
JavaScriptLanguageRules
var Constants Semicolons Nestedfunctions FunctionDeclarationsWithinBlocks ExceptionsCustomexceptions Standardsfeatures WrapperobjectsforprimitivetypesMulti-levelprototypehierarchies Methoddefinitions Closures eval() with(){} thisfor-inloop AssociativeArrays Multilinestringliterals ArrayandObjectliteralsModifyingprototypesofbuiltinobjects InternetExplorer'sConditionalComments
JavaScriptStyleRules
Naming CustomtoString()methods Deferredinitialization Explicitscope CodeformattingParentheses Strings Visibility(privateandprotectedfields) JavaScriptTypes CommentsCompiling TipsandTricks
ImportantNote
DisplayingHiddenDetailsinthisGuide
link▽
Thisstyleguidecontainsmanydetailsthatareinitiallyhiddenfromview.Theyaremarkedbythetriangleicon,whichyouseehereonyourleft.Clickitnow.Youshouldsee"Hooray"appearbelow.
Hooray!
Nowyouknowyoucanexpandpointstogetmoredetails.Alternatively,there'sa"toggleall"atthetopofthisdocument.
Background
JavaScriptisthemainclient-sidescriptinglanguageusedbymanyofGoogle'sopen-sourceprojects.Thisstyleguideisalistof dosand don'tsforJavaScriptprograms.
JavaScriptLanguageRules
var
link▽
Declarationswith var:
Always
Decision:
Whenyoufailtospecify var,thevariablegetsplacedintheglobalcontext,potentiallyclobberingexistingvalues.Also,ifthere'snodeclaration,it'shardtotellinwhatscopeavariablelives(e.g.,itcouldbeintheDocumentorWindowjustaseasilyasinthelocalscope).Soalwaysdeclarewith var.
Constants
link▽
>Use NAMES_LIKE_THIS forconstants.Use @const whereappropriate.Neverusethe const keyword.
Decision:
Forsimpleprimitivevalueconstants,thenamingconventionisenough.
/**
*Thenumberofsecondsinaminute.
*@type{number}
*/
goog.example.SECONDS_IN_A_MINUTE=60;
Fornon-primitives,usethe @const annotation.
/**
*Thenumberofsecondsineachofthegivenunits.
*@type{Object.}
*@const
*/
goog.example.SECONDS_TABLE={
minute:
60,
hour:
60*60
day:
60*60*24
}
Thisallowsthecompilertoenforceconstant-ness.
Asforthe const keyword,InternetExplorerdoesn'tparseit,sodon'tuseit.
Semicolons
link▽
Alwaysusesemicolons.
Relyingonimplicitinsertioncancausesubtle,hardtodebugproblems.Don'tdoit.You'rebetterthanthat.
Thereareacoupleplaceswheremissingsemicolonsareparticularlydangerous:
//1.
MyClass.prototype.myMethod=function(){
return42;
}//Nosemicolonhere.
(function(){
//Someinitializationcodewrappedinafunctiontocreateascopeforlocals.
})();
varx={
'i':
1,
'j':
2
}//Nosemicolonhere.
//2.TryingtodoonethingonInternetExplorerandanotheronFirefox.
//Iknowyou'dneverwritecodelikethis,butthrowmeabone.
[normalVersion,ffVersion][isIE]();
varTHINGS_TO_EAT=[apples,oysters,sprayOnCheese]//Nosemicolonhere.
//3.conditionalexecutionalabash
-1==resultOfOperation()||die();
Sowhathappens?
1.JavaScripterror-firstthefunctionreturning42iscalledwiththesecondfunctionasaparameter,thenthenumber42is"called"resultinginanerror.
2.Youwillmostlikelygeta'nosuchpropertyinundefined'erroratruntimeasittriestocall x[ffVersion][isIE]().
3.die iscalledunless resultOfOperation() is NaN and THINGS_TO_EAT getsassignedtheresultof die().
Why?
JavaScriptrequiresstatementstoendwithasemicolon,exceptwhenitthinksitcansafelyinfertheirexistence.Ineachoftheseexamples,afunctiondeclarationorobjectorarrayliteralisusedinsideastatement.Theclosingbracketsarenotenoughtosignaltheendofthestatement.Javascriptneverendsastatementifthenexttokenisaninfixorbracketoperator.
Thishasreallysurprisedpeople,somakesureyourassignmentsendwithsemicolons.
Nestedfunctions
link▽
Yes
Nestedfunctionscanbeveryuseful,forexampleinthecreationofcontinuationsandforthetaskofhidinghelperfunctions.Feelfreetousethem.
FunctionDeclarationsWithinBlocks
link▽
No
Donotdothis:
if(x){
functionfoo(){}
}
WhilemostscriptenginessupportFunctionDeclarationswithinblocksitisnotpartofECMAScript(see ECMA-262,clause13and14).WorseimplementationsareinconsistentwitheachotherandwithfutureEcmaScriptproposals.ECMAScriptonlyallowsforFunctionDeclarationsintherootstatementlistofascriptorfunction.InsteaduseavariableinitializedwithaFunctionExpressiontodefineafunctionwithinablock:
if(x){
varfoo=function(){}
}
Exceptions
link▽
Yes
Youbasicallycan'tavoidexceptionsifyou'redoingsomethingnon-trivial(usinganapplicationdevelopmentframework,etc.).Goforit.
Customexceptions
link▽
Yes
Withoutcustomexceptions,returningerrorinformationfromafunctionthatalsoreturnsavaluecanbetricky,nottomentioninelegant.BadsolutionsincludepassinginareferencetypetoholderrorinformationoralwaysreturningObjectswithapotentialerrormember.Thesebasicallyamounttoaprimitiveexceptionhandlinghack.Feelfreetousecustomexceptionswhenappropriate.
Standardsfeatures
link▽
Alwayspreferredovernon-standardsfeatures
Formaximumportabilityandcompatibility,alwayspreferstandardsfeaturesovernon-standardsfeatures(e.g.,string.charAt(3) over string[3] andelementaccesswithDOMfunctionsinsteadofusinganapplication-specificshorthand).
Wrapperobjectsforprimitivetypes
link▽
No
There'snoreasontousewrapperobjectsforprimitivetypes,plusthey'redangerous:
varx=newBoolean(false);
if(x){
alert('hi');//Shows'hi'.
}
Don'tdoit!
Howevertypecastingisfine.
varx=Boolean(0);
if(x){
alert('hi');//Thiswillneverbealerted.
}
typeofBoolean(0)=='boolean';
typeofnewBoolean(0)=='object';
Thisisveryusefulforcastingthingsto number, string and boolean.
Multi-levelprototypehierarchies
link▽
Notpreferred
Multi-levelprototypehierarchiesarehowJavaScriptimplementsinheritance.Youhaveamulti-levelhierarchyifyouhaveauser-definedclassDwithanotheruser-definedclassBasitsprototype.Thesehierarchiesaremuchhardertogetrightthantheyfirstappear!
Forthatreason,itisbesttouse goog.inherits() from theClosureLibrary orsomethingsimilar.
functionD(){
goog.base(this)
}
goog.inherits(D,B);
D.prototype.method=function(){
...
};
Methoddefinitions
link▽
Foo.prototype.bar=function(){...};
Whilethereareseveralmethodsforattachingmethodsandpropertiestoaconstructor,thepreferredstyleis:
Foo.prototype.bar=function(){
/*...*/
};
Closures
link▽
Yes,butbecareful.
TheabilitytocreateclosuresisperhapsthemostusefulandoftenoverlookedfeatureofJS.Hereis agooddescriptionofhowclosureswork .
Onethingtokeepinmind,however,isthataclosurekeepsapointertoitsenclosingscope.Asaresult,attachingaclosuretoaDOMelementcancreateacircularreferenceandthus,amemoryleak.Forexample,inthefollowingcode:
functionfoo(element,a,b){
element.onclick=function(){/*usesaandb*/};
}
thefunctionclosurekeepsareferenceto element, a,and b evenifitneveruses element.Since element alsokeepsareferencetotheclosure,wehaveacyclethatwon'tbecleanedupbygarbagecollection.Inthesesituations,thecodecanbestructuredasfollows:
functionfoo(element,a,b){
element.onclick=bar(a,b);
}
functionbar(a,b){
returnfunction(){/*usesaandb*/}
}
eval()
link▽
Onlyfordeserialization(e.g.evaluatingRPCresponses)
eval() makesforconfusingsemanticsandisdangeroustouseifthestringbeing eval()'dcontainsuserinput.There'susuallyabetter,moreclear,saferwaytowriteyourcode,soitsusedisgenerallynotpermitted.However eval makesdeserializationconsiderablyeasierthanthenon-eval alternatives,soitsuseisacceptableforthistask(forexample,toevaluateRPCresponses).
Deserializationistheprocessoftransformingaseriesofbytesintoanin-memorydatastructure.Forexample,youmightwriteobjectsouttoafileas:
users=[
{
name:
'Eric',
id:
37824,
email:
'jellyvore@'
},
{
name:
'xtof',
id:
31337,
email:
'b4d455h4x0r@'
},
...
];
Readingthesedatabackintomemoryisassimpleas evalingthestringrepresentationofthefile.
Similarly, eval() cansimplifydecodingRPCreturnvalues.Forexample,youmightusean XMLHttpRequest tomakeanRPC,andinitsresponsetheservercanreturnJavaScript:
varuserOnline=false;
varuser='nusrat';
varxmlhttp=newXMLHttpRequest();
xmlhttp.open('GET','+user,false);
xmlhttp.send('');
//Serverreturns:
//userOnline=true;
if(xmlhttp.status==200){
eval(xmlhttp.responseText);
}
//userOnlineisnowtrue.
with(){}
link▽
No
Using with cloudsthesemanticsofyourprogram.Becausetheobjectofthe with canhavepropertiesthatcollidewithlocalvariables,itcandrasticallychangethemeaningofyourprogram.Forexample,whatdoesthisdo?
with(foo){
varx=3;
returnx;
}
Answer:
anything.Thelocalvariable x couldbeclobberedbyapropertyof foo andperhapsitevenhasasetter,inwhichcaseassigning 3 couldcauselotsof