编写快速高效的JavaScript代码.docx
《编写快速高效的JavaScript代码.docx》由会员分享,可在线阅读,更多相关《编写快速高效的JavaScript代码.docx(38页珍藏版)》请在冰豆网上搜索。
![编写快速高效的JavaScript代码.docx](https://file1.bdocx.com/fileroot1/2023-2/3/bf26308f-e33e-4620-b285-35914a715a0e/bf26308f-e33e-4620-b285-35914a715a0e1.gif)
编写快速高效的JavaScript代码
编写快速、高效的JavaScript代码
JavaScriptenginessuchasGoogle’sV8(Chrome,Node)arespecificallydesignedforthefastexecutionoflargeJavaScriptapplications.Asyoudevelop,ifyoucareaboutmemoryusageandperformance,youshouldbeawareofsomeofwhat’sgoingoninyouruser’sbrowser’sJavaScriptenginebehindthescenes.
Whetherit’sV8,SpiderMonkey(Firefox),Carakan(Opera),Chakra(IE)orsomethingelse,doingsocanhelpyoubetteroptimizeyourapplications.That’snottosayoneshouldoptimizeforasinglebrowserorengine.Neverdothat.
Youshould,however,askyourselfquestionssuchas:
∙IsthereanythingIcouldbedoingmoreefficientlyinmycode?
∙What(common)optimizationsdopopularJavaScriptenginesmake?
∙Whatistheengineunabletooptimizefor,andisthegarbagecollectorabletocleanupwhatI’mexpectingitto?
Fast-loadingWebsites—likefastcars—requiretheusespecializedtools.Imagesource:
dHybridcars.
Therearemanycommonpitfallswhenitcomestowritingmemory-efficientandfastcode,andinthisarticlewe’regoingtoexploresometest-provenapproachesforwritingcodethatperformsbetter.
(Smashing’snote:
Ifyouenjoyreadingourarticles,you'lllovetheSmashingeBookLibrary.GetimmediateaccesstoallSmashingeBookswith70%discountandvoteonthetopicsyou’dliketolearnmoreabout.We’llprepareeBooksthatfityourneedsbest!
Subscribenow!
)
So,HowDoesJavaScriptWorkInV8?
Whileit’spossibletodeveloplarge-scaleapplicationswithoutathoroughunderstandingofJavaScriptengines,anycarownerwilltellyouthey’velookedunderthehoodatleastonce.AsChromeismybrowserofchoice,I’mgoingtotalkalittleaboutitsJavaScriptengine.V8ismadeupofafewcorepieces.
∙Abasecompiler,whichparsesyourJavaScriptandgeneratesnativemachinecodebeforeitisexecuted,ratherthanexecutingbytecodeorsimplyinterpretingit.Thiscodeisinitiallynothighlyoptimized.
∙V8representsyourobjectsinanobjectmodel.ObjectsarerepresentedasassociativearraysinJavaScript,butinV8theyarerepresentedwithhiddenclasses,whichareaninternaltypesystemforoptimizedlookups.
∙Theruntimeprofilermonitorsthesystembeingrunandidentifies“hot”functions(i.e.codethatendsupspendingalongtimerunning).
∙Anoptimizingcompilerrecompilesandoptimizesthe“hot”codeidentifiedbytheruntimeprofiler,andperformsoptimizationssuchasinlining(i.e.replacingafunctioncallsitewiththebodyofthecallee).
∙V8supportsdeoptimization,meaningtheoptimizingcompilercanbailoutofcodegeneratedifitdiscoversthatsomeoftheassumptionsitmadeabouttheoptimizedcodeweretoooptimistic.
∙Ithasagarbagecollector.UnderstandinghowitworkscanbejustasimportantastheoptimizedJavaScript.
GarbageCollection
Garbagecollectionisaformofmemorymanagement.It’swherewehavethenotionofacollectorwhichattemptstoreclaimmemoryoccupiedbyobjectsthatarenolongerbeingused.Inagarbage-collectedlanguagesuchasJavaScript,objectsthatarestillreferencedbyyourapplicationarenotcleanedup.
Manuallyde-referencingobjectsisnotnecessaryinmostcases.Bysimplyputtingthevariableswheretheyneedtobe(ideally,aslocalaspossible,i.e.insidethefunctionwheretheyareusedversusanouterscope),thingsshouldjustwork.
Garbagecollectionattemptstoreclaimmemory.Imagesource:
ValtteriMäki.
It’snotpossibletoforcegarbagecollectioninJavaScript.Youwouldn’twanttodothis,becausethegarbagecollectionprocessiscontrolledbytheruntime,anditgenerallyknowsbestwhenthingsshouldbecleanedup.
DE-REFERENCINGMISCONCEPTIONS
InquiteafewdiscussionsonlineaboutreclaimingmemoryinJavaScript,thedeletekeywordisbroughtup,asalthoughitwassupposedtobeusedforjustremovingkeysfromamap,somedevelopersthinkyoucanforcede-referencingusingit.Avoidusingdeleteifyoucan.Inthebelowexample,deleteo.xdoesalotmoreharmthangoodbehindthescenes,asitchangeso‘shiddenclassandmakesitagenericslowobject.
1
varo={x:
1};
2
deleteo.x;//true
3
o.x;//undefined
Thatsaid,youarealmostcertaintofindreferencestodeleteinmanypopularJavaScriptlibraries–itdoeshaveapurposeinthelanguage.Themaintakeawayhereistoavoidmodifyingthestructureofhotobjectsatruntime.JavaScriptenginescandetectsuch“hot”objectsandattempttooptimizethem.Thisiseasieriftheobject’sstructuredoesn’theavilychangeoveritslifetimeanddeletecantriggersuchchanges.
Therearealsomisconceptionsabouthownullworks.Settinganobjectreferencetonulldoesn’t“null”theobject.Itsetstheobjectreferencetonull.Usingo.x=nullisbetterthanusingdelete,butit’sprobablynotevennecessary.
1
varo={x:
1};
2
o=null;
3
o;//null
4
o.x//TypeError
Ifthisreferencewasthelastreferencetotheobject,theobjectistheneligibleforgarbagecollection.Ifthereferencewasnotthelastreferencetotheobject,theobjectisreachableandwillnotbegarbagecollected.
Anotherimportantnotetobeawareofisthatglobalvariablesarenotcleanedupbythegarbagecollectorduringthelifeofyourpage.Regardlessofhowlongthepageisopen,variablesscopedtotheJavaScriptruntimeglobalobjectwillstickaround.
1
varmyGlobalNamespace={};
Globalsarecleanedupwhenyourefreshthepage,navigatetoadifferentpage,closetabsorexityourbrowser.Function-scopedvariablesgetcleanedupwhenavariablefallsoutofscope.Whenfunctionshaveexitedandtherearen’tanymorereferencestoit,thevariablegetscleanedup.
RULESOFTHUMB
Togivethegarbagecollectorachancetocollectasmanyobjectsaspossibleasearlyaspossible,don’tholdontoobjectsyounolongerneed.Thismostlyhappensautomatically;hereareafewthingstokeepinmind.
∙Asmentionedearlier,abetteralternativetomanualde-referencingistousevariableswithanappropriatescope.I.e.insteadofaglobalvariablethat’snulledout,justuseafunction-localvariablethatgoesoutofscopewhenit’snolongerneeded.Thismeanscleanercodewithlesstoworryabout.
∙Ensurethatyou’reunbindingeventlistenerswheretheyarenolongerrequired,especiallywhentheDOMobjectsthey’reboundtoareabouttoberemoved
∙Ifyou’reusingadatacachelocally,makesuretocleanthatcacheoruseanagingmechanismtoavoidlargechunksofdatabeingstoredthatyou’reunlikelytoreuse
FUNCTIONS
Next,let’slookatfunctions.Aswe’vealreadysaid,garbagecollectionworksbyreclaimingblocksofmemory(objects)whicharenolongerreachable.Tobetterillustratethis,herearesomeexamples.
1
functionfoo(){
2
varbar=newLargeObject();
3
bar.someCall();
4
}
Whenfooreturns,theobjectwhichbarpointstoisautomaticallyavailableforgarbagecollection,becausethereisnothingleftthathasareferencetoit.
Comparethisto:
1
functionfoo(){
2
varbar=newLargeObject();
3
bar.someCall();
4
returnbar;
5
}
6
7
//somewhereelse
8
varb=foo();
Wenowhaveareferencetotheobjectwhichsurvivesthecallandpersistsuntilthecallerassignssomethingelsetob(orbgoesoutofscope).
CLOSURES
Whenyouseeafunctionthatreturnsaninnerfunction,thatinnerfunctionwillhaveaccesstotheouterscopeevenaftertheouterfunctionisexecuted.Thisisbasicallyaclosure—anexpressionwhichcanworkwithvariablessetwithinaspecificcontext.Forexample:
01
functionsum(x){
02
functionsumIt(y){
03
returnx+y;
04
};
05
returnsumIt;
06
}
07
08
//Usage
09
varsumA=sum(4);
10
varsumB=sumA(3);
11
console.log(sumB);//Returns7
Thefunctionobjectcreatedwithintheexecutioncontextofthecalltosumcan’tbegarbagecollected,asit’sreferencedbyaglobalvariableandisstillverymuchaccessible.ItcanstillbeexecutedviasumA(n).
Let’slookatanotherexample.Here,canweaccesslargeStr?
1
vara=function(){
2
varlargeStr=newArray(1000000).join('x');
3
returnfunction(){
4
returnlargeStr;
5
};
6
}();
Yes,wecan,viaa(),soit’snotcollected.Howaboutthisone?
1
vara=function(){
2
varsmallStr='x';
3
varlargeStr=newArray(1000000).join('x');
4
returnfunction(n){
5
returnsmallStr;
6
};
7
}();
Wecan’taccessitanymoreandit’sacandidateforgarbagecollection.
TIMERS
Oneoftheworstplacestoleakisinaloop,orinsetTimeout()/setInterval(),butthisisquitecommon.
Considerthefollowingexample.
1
varmyObj={
2
callMeMaybe:
function(){
3
varmyRef=this;
4
varval=setTimeout(function(){
5
console.log('Timeisrunningout!
');
6
myRef.callMeMaybe();
7
},1000);
8
}
9
};
Ifwethenrun:
1
myObj.callMeMaybe();
tobeginthetimer,wecanseeeverysecond“Timeisrunningout!
”Ifwethenrun:
1
myObj=null;
Thetimerwillstillfire.myObjwon’tbegarbagecollectedastheclosurepassedtosetTimeouthastobekeptaliveinordertobeexecuted.Inturn,itholdsreferencestomyObjasitcapturesmyRef.Thiswouldbethesameifwe’dpassedtheclosuretoanyotherfunction,keepingreferencestoit.
Itisalsoworthkeepinginmindthatr