JavaScript for Kids: A Playful Introduction to Programming

Transcription

JavaScript for Kids: A Playful Introduction to Programming
JavaScriptforKids:APlayfulIntroductionto
Programming
NickMorgan
PublishedbyNoStarchPress
ToPhilly(andPancake)
AbouttheAuthor
NickMorganisafrontendengineeratTwitter.Helovesallprogramminglanguagesbuthasaparticular
softspotforJavaScript.NicklivesinSanFrancisco(thefoggypart)withhisfiancéeandtheirfluffy
dog,Pancake.Heblogsatskilldrick.co.uk.
AbouttheIllustrator
MiranLipovacaistheauthorofLearnYouaHaskellforGreatGood!.Heenjoysboxing,playingbass
guitar,and,ofcourse,drawing.Hehasafascinationwithdancingskeletonsandthenumber71,and
whenhewalksthroughautomaticdoorshepretendsthathe’sactuallyopeningthemwithhismind.
AbouttheTechnicalReviewer
AngusCrollistheauthorofIfHemingwayWroteJavaScript,andheisobsessedwithJavaScriptand
literatureinequalmeasure.HeworksonTwitter’sUIframeworkteam,whereheco-authoredtheFlight
framework.HewritestheinfluentialJavaScript,JavaScriptblogandspeaksatconferencesworldwide.
Hetweetsat@angustweets.
Acknowledgments
Somanythankstomywonderfulfiancée,Philly,forherencouragementandsupportduringthepast18
months.Itrulycouldn’thavedoneitwithouther.AndthankstoPancake,ourdog,forgraciously
allowingmetousehiminmycodeexamples.
ThankstoAngus,withoutwhomIwouldn’tbehere,inSanFrancisco,writingthisbook.Angusreferred
metoTwitterbackin2011,andthenin2013suggestedtoBillPollockthatImightbeinterestedin
writingthisbookyou’reholding.Andtotopitall,heagreedtobethetechnicalreviewer,catchinga
greatnumberofJavaScriptfauxpas.
ThankstoBillPollock,SephKramer,RileyHoffman,TylerOrtman,andeveryoneelseatNoStarch
Press,whopatientlyguidedmethroughtheprocessofwritingthisbook.SpecialthankstoBillandSeph
formassagingmywritingintoitscurrentform.
ThankstotheyoungreviewersRiverBradley,DamienChamp,andAlexChu,whohadsomegreat
feedbackontheearlyPDFs.
Finally,thankstoMiranLipovaca.I’vebeenafanofMiranforyears—hisbookLearnYouaHaskell
forGreatGoodisoneofmyfavoriteprogrammingbooks,andhisillustrationsforitareamazing.
Findingouthe’dbeillustratingmybookwaslikeadreamcometrue.Hispicturesforthisbookare
betterthanIcouldhaveimagined,andI’mhumbledtohavehadthechancetoworkwithhim.
Introduction
WelcometoJavaScriptforKids!Inthisbook,you’lllearntoprogramwithJavaScript,thelanguageof
theWeb.Butmorethanthat,you’llbecomeaprogrammer—someonewhonotonlyusescomputers
butalsocontrolsthem.Onceyoulearntoprogram,youcanbendcomputerstoyourwillandmakethem
dowhateveryouwant!
JavaScriptisagreatprogramminglanguagetolearnbecauseit’susedeverywhere.Webbrowserslike
Chrome,Firefox,andInternetExploreralluseJavaScript.WiththepowerofJavaScript,web
programmerscantransformwebpagesfromsimpledocumentsintofull-blowninteractiveapplications
andgames.
Butyou’renotlimitedtobuildingwebpages.JavaScriptcanrunonwebserverstocreatewhole
websitesandcanevenbeusedtocontrolrobotsandotherhardware!
WhoShouldReadThisBook?
ThisbookisforanyonewhowantstolearnJavaScriptortostartprogrammingforthefirsttime.The
bookisdesignedtobekidfriendly,butitcanserveasafirstprogrammingbookforbeginnersofall
ages.
Withthisbook,you’llbuildupyourknowledgeofJavaScriptgradually,startingwithJavaScript’s
simpledatatypes,beforemovingontocomplextypes,controlstructures,andfunctions.Afterthatyou’ll
learnhowtowritecodethatreactswhentheusermovesthemouseorpressesakeyonthekeyboard.
Finally,you’lllearnaboutthecanvaselement,whichletsyouuseJavaScripttodrawandanimate
anythingyoucanimagine!
Alongtheway,you’llcreateafewgamestostretchyourprogrammingskillsandputwhatyou’ve
learnedtogooduse.
HowtoReadThisBook
Firstoff,readitinorder!Thatmightsoundlikeasillythingtosay,butlotsofpeoplewanttojump
straightintothefunstuff,likemakinggames.Buteachchapterismeanttobuildonwhatwascovered
inearlierchapters,soifyoubeginatthebeginning,you’llhaveaneasiertimewhenyougettothe
games.
Programminglanguagesarelikespokenlanguages:youhavetolearnthegrammarandthevocabulary,
andthistakestime.Theonlywaytoimproveisbywriting(andreading)alotofcode.Asyouwrite
moreandmoreJavaScript,you’llfindcertainpartsofthelanguagebecomesecondnature,and
eventuallyyou’llbecomeafluentwriterofJavaScript.
Asyouread,Iencourageyoutotypeoutandtestthecodeexamplesthroughoutthebook.Ifyoudon’t
fullyunderstandwhat’sgoingon,trymakingsmallchangestoseewhateffecttheyhave.Ifthechanges
don’thavetheeffectyouexpected,seeifyoucanfindoutwhy.
Aboveall,workthroughthe“TryItOut”andProgrammingChallengessections.Typingoutthecode
thatappearsinthebookisagoodfirststep,butyou’llunderstandprogrammingatadeeperlevelwhen
youstartwritingyourowncode.Ifyoufindachallengeinteresting,thenkeepatit!Comeupwithyour
ownchallengestobuildevenmoreontotheprogramsyou’vewritten.
You’llfindsamplesolutionstotheprogrammingchallenges(aswellasthecodefilesforthegamesand
otherexamples)athttp://nostarch.com/javascriptforkids/.Trylookingatthesolutionsafteryou’ve
solvedachallenge,soyoucancompareyourapproachtomine.Or,ifyou’restuck,youcancheckthe
solutionforhints.Butrememberthatthesearejustsamplesolutions.Therearemany,manydifferent
waystoaccomplishthesamegoalinJavaScript,sodon’tworryifyouendupwithacompletely
differentsolutionfrommine!
Ifyoucomeacrossawordandyoudon’tknowwhatitmeans,checktheglossaryatthebackofthe
book.Theglossarycontainsdefinitionsformanyoftheprogrammingtermsyou’llencounterinthis
book.
What’sinthisBook?
Chapter1givesyouaquickintroductiontoJavaScriptandgetsyoustartedwritingJavaScriptin
GoogleChrome.
Chapter2introducesvariablesandthebasicdatatypesusedbyJavaScript:numbers,strings,and
Booleans.
Chapter3isallaboutarrays,whichareusedtoholdlistsofotherpiecesofdata.
Chapter4isaboutobjects,whichcontainpairsofkeysandvalues.
Chapter5isanintroductiontoHTML,thelanguageusedtocreatewebpages.
Chapter6showsyouhowtogainmorecontroloveryourcodeusingifstatements,forloops,and
othercontrolstructures.
Chapter7putstogethereverythingyou’velearnedsofartocreateasimpleHangmanword-guessing
game.
Chapter8showsyouhowtowriteyourownfunctionssoyoucangrouptogetherandreuseblocksof
code.
Chapter9introducesjQuery,atoolthatmakesiteasytocontrolwebpagesusingJavaScript.
Chapter10showsyouhowtousetimeouts,intervals,andeventhandlerstomakeyourcodemore
interactive.
Chapter11usesfunctions,jQuery,andeventhandlerstocreateagamecalledChapter11
Chapter12teachesastyleofprogrammingcalledobject-orientedprogramming.
Chapter13introducesthecanvaselement,whichallowsyoutodrawgraphicsonawebpagewith
JavaScript.
Chapter14buildsontheanimationtechniquesyoulearnedinChapter10soyoucancreateanimations
withcanvas,andChapter15showsyouhowtocontrolthosecanvasanimationswiththekeyboard.
InChapter16andChapter17,you’llprogramacompleteSnakegame,usingeverythingyoulearned
intheprevious15chapters!
TheAfterwordgivesyousomeideasforhowtolearnevenmoreaboutprogramming.
TheGlossarycontainsdefinitionsformanyofthenewwordsyou’llencounter.
HaveFun!
Onelastthingtoremember:Havefun!Programmingcanbeaplayfulandcreativeactivity,justlike
drawingorplayingagame(infact,you’llbedrawingandplayinggameswithJavaScriptalotinthis
book).Onceyougetthehangofhowtowritecode,theonlylimitisyourimagination.Welcometothe
amazingworldofcomputerprogramming—Ihopeyouhaveablast!
PartI.Fundamentals
Chapter1.WhatIsJavaScript?
Computersareincrediblypowerfulmachines,capableofperformingamazingfeatslikeplaying
competitivechess,servingthousandsofwebpages,ormakingmillionsofcomplexcalculationsinless
thanafewseconds.Butdeepdown,computersareactuallyprettydumb.Computerscanonlydoexactly
whatwehumanstellthemtodo.Wetellcomputershowtobehaveusingcomputerprograms,whichare
justsetsofinstructionsforthecomputerstofollow.Withoutprograms,computerscan’tdoanythingat
all!
MeetJavaScript
Evenworse,computerscan’tunderstandEnglishoranyotherspokenlanguage.Computerprogramsare
writteninaprogramminglanguagelikeJavaScript.YoumightnothaveheardofJavaScriptbefore,but
you’vecertainlyusedit.TheJavaScriptprogramminglanguageisusedtowriteprogramsthatrunin
webpages.JavaScriptcancontrolhowawebpagelooksormakethepagerespondwhenaviewer
clicksabuttonormovesthemouse.
SiteslikeGmail,Facebook,andTwitteruseJavaScripttomakeiteasiertosendemail,postcomments,
orbrowsewebsites.Forexample,whenyou’reonTwitterreadingtweetsfrom@nostarchandyousee
moretweetsatthebottomofthepageasyouscrolldown,that’sJavaScriptinaction.
YouonlyhavetovisitacoupleofwebsitestoseewhyJavaScriptissoexciting.
JavaScriptletsyouplaymusicandcreateamazingvisualeffects.Forexample,youcanflythrough
aninteractivemusicvideocreatedbyHelloEnjoyforEllieGoulding’ssong“Lights”
(http://lights.helloenjoy.com/),asshowninFigure1-1.
JavaScriptletsyoubuildtoolsforotherstomaketheirownart.Patatap(http://www.patatap.com/)
isakindofvirtual“drummachine”thatcreatesallkindsofcoolnoises—andcoolanimationsto
goalongwiththem—asshowninFigure1-2.
Figure1-1.YoucontroltheflashingcursorinHelloEnjoy’s“Lights”musicvideo.
Figure1-2.WhenyouvisitPatatap,trypressingabunchofkeystomakedifferentnoises!
JavaScriptletsyouplayfungames.CubeSlam(https://www.cubeslam.com/)isa3Dre-creationof
theclassicgamePong,whichlooksalittlelikeairhockey.Youcanplayagainstoneofyour
friendsoracomputer-generatedbear,asshowninFigure1-3.
Figure1-3.TheCubeSlamgameisprogrammedentirelyinJavaScript!
WhyLearnJavaScript?
JavaScriptisn’ttheonlyprogramminglanguageoutthere—infact,thereareliterallyhundredsof
programminglanguages.ButtherearemanyreasonstolearnJavaScript.Forone,it’saloteasier(and
morefun)tolearnthanmanyotherprogramminglanguages.Butperhapsbestofall,inordertowrite
andrunJavaScriptprograms,allyouneedisawebbrowserlikeInternetExplorer,MozillaFirefox,or
GoogleChrome.EverywebbrowsercomeswithaJavaScriptinterpreterthatunderstandshowtoread
JavaScriptprograms.
Onceyou’vewrittenaJavaScriptprogram,youcansendpeoplealinktoit,andtheycanrunitinaweb
browserontheircomputer,too!(SeeSharingYourCodeUsingJSFiddle.)
WritingSomeJavaScript
Let’swriteabitofsimpleJavaScriptinGoogleChrome(http://www.google.com/chrome/).Install
Chromeonyourcomputer(ifit’snotalreadyinstalled),andthenopenitandtypeabout:blankinthe
addressbar.NowpressENTERandyou’llseeablankpage,liketheoneinFigure1-4.
We’llbeginbycodinginChrome’sJavaScriptconsole,whichisasecretwayprogrammerscantestout
shortJavaScriptprograms.OnMicrosoftWindowsorLinux,holddowntheCTRLandSHIFTkeysand
pressJ.OnMacOS,holddowntheCOMMANDandOPTIONkeysandpressJ.
Ifyou’vedoneeverythingcorrectly,youshouldseeablankwebpageand,beneaththat,ablinking
cursor(|)nexttoarightanglebracket(>),asshowninFigure1-4.That’swhereyou’llwrite
JavaScript!
NOTE
TheChromeconsolewillcoloryourcodetext;forexample,thetextyouinputwillbeblue,andoutputwillbecoloredbasedonitstype.
Inthisbook,we’llusesimilarcolorsforourcodetextwhereverwe’reusingtheconsole.
Figure1-4.GoogleChrome’sJavaScriptconsole
WhenyouentercodeatthecursorandpressENTER,JavaScriptshouldrun,orexecute,yourcodeand
displaytheresult(ifany)onthenextline.Forexample,typethisintotheconsole:
3+4;
NowpressENTER.JavaScriptshouldoutputtheanswer(7)tothissimplebitofadditiononthefollowing
line:
3+4;
7
Well,that’seasyenough.Butisn’tJavaScriptmorethanaglorifiedcalculator?Let’strysomethingelse.
TheStructureofaJavaScriptProgram
Let’screatesomethingabitsillier—aJavaScriptprogramtoprintaseriesofcatfacesthatlooklike
this:
=^.^=
Unlikeouradditionprogram,thisJavaScriptprogramwilltakeupmultiplelines.Totypetheprogram
intotheconsole,you’llhavetoaddnewlinesbypressingSHIFT-ENTERattheendofeachline.(Ifyou
justpressENTER,Chromewilltrytoexecutewhatyou’vewritten,andtheprogramwon’tworkas
expected.Iwarnedyouthatcomputersweredumb!)
Typethisintoyourbrowserconsole:
//Drawasmanycatsasyouwant!
vardrawCats=function(howManyTimes){
for(vari=0;i<howManyTimes;i++){
console.log(i+"=^.^=");
}
};
drawCats(10);//Youcanputanynumberhereinsteadof10.
Attheveryend,pressENTERinsteadofSHIFT-ENTER.Whenyoudothat,youshouldseethefollowing
output:
0=^.^=
1=^.^=
2=^.^=
3=^.^=
4=^.^=
5=^.^=
6=^.^=
7=^.^=
8=^.^=
9=^.^=
Ifyoumadeanytypos,youroutputmightlookverydifferentoryoumightgetanerror.That’swhatI
meanwhenIsaycomputersaredumb—evenasimplepieceofcodemustbeperfectforacomputerto
understandwhatyouwantittodo!
Iwon’tgothroughexactlyhowthiscodeworksfornow(we’llreturntothisprograminChapter8),but
let’slookatsomeofthefeaturesofthisprogramandofJavaScriptprogramsingeneral.
Syntax
Ourprogramincludeslotsofsymbols,includingparentheses(),semicolons;,curlybrackets{},plus
signs+,andafewwordsthatmightseemmysteriousatfirst(likevarandconsole.log).Theseareall
partofJavaScript’ssyntax—thatis,JavaScript’srulesforhowtocombinesymbolsandwordstocreate
workingprograms.
Whenyou’relearninganewprogramminglanguage,oneofthetrickiestpartsisgettingusedtothe
rulesforhowtowritedifferentkindsofinstructionstothecomputer.Whenyou’refirststartingout,it’s
easytoforgetwhentoincludeparentheses,ortomixuptheorderinwhichyouneedtoincludecertain
values.Butasyoupractice,you’llstarttogetthehangofit.
Inthisbook,we’llgoslowandsteady,introducingnewsyntaxlittlebylittlesothatyoucanbuild
increasinglypowerfulprograms.
Comments
Thefirstlineinourcatsprogramisthis:
//Drawasmanycatsasyouwant!
Thisiscalledacomment.Programmersusecommentstomakeiteasierforotherprogrammerstoread
andunderstandtheircode.Thecomputerignorescommentscompletely.CommentsinJavaScriptstart
withtwoforwardslashes(//).Everythingfollowingtheslashes(onthesameline)isignoredbythe
JavaScriptinterpreter,sothecommentsdon’thaveanyeffectonhowaprogramisexecuted—theyare
justtheretoprovideadescription.
Inthecodeinthisbook,you’llseecommentsthatdescribewhat’shappeninginthecode.Asyouwrite
yourowncode,addyourowncomments.Thenwhenyoulookatyourcodelater,yourcommentswill
remindyouhowthecodeworksandwhat’shappeningineachstep.
There’sanothercodecommentonthelastlineofourprogram.Remember,everythingafterthat//isn’t
runbythecomputer!
drawCats(10);//Youcanputanynumberhereinsteadof10.
Codecommentscanbeontheirownline,ortheycancomeafteryourcode.Ifyouputthe//atthe
front,likethis:
//drawCats(10);
...nothingwillhappen!Chromeseesthewholelineasacomment,evenifit’sJavaScript.
OnceyoustartreadingJavaScriptcodeoutinthewildworld,you’llalsoseecommentsthatlooklike
this:
/*
Drawasmanycats
asyouwant!
*/
Thisisadifferentstyleofcommenting,whichistypicallyusedforcommentsthatarelongerthanone
line.Butitdoesthesamething:everythingbetweenthe/*andthe*/isacommentthatthecomputer
won’trun.
WhatYouLearned
Inthischapter,youlearnedabitaboutwhatJavaScriptisandwhatitcanbeusedfor.Youalsolearned
howtorunJavaScriptusingtheGoogleChromebrowserandtriedoutasampleprogram.Allofthe
codeexamplesinthisbook,unlessIsayotherwise,can(andshould!)beusedinChrome’sJavaScript
console.Don’tjustreadthecode—trytypingthingsout!It’stheonlywaytolearntoprogram.
Inthenextchapter,you’llstartlearningthefundamentalsofJavaScript,beginningwiththethreebasic
typesofinformationyoucanworkwith:numbers,strings,andBooleans.
Chapter2.DataTypesandVariables
Programmingisallaboutmanipulatingdata,butwhatisdata?Dataisinformationthatwestoreinour
computerprograms.Forexample,yournameisapieceofdata,andsoisyourage.Thecolorofyour
hair,howmanysiblingsyouhave,whereyoulive,whetheryou’remaleorfemale—thesethingsareall
data.
InJavaScript,therearethreebasictypesofdata:numbers,strings,andBooleans.Numbersareusedfor
representing,well,numbers!Forexample,youragecanberepresentedasanumber,andsocanyour
height.NumbersinJavaScriptlooklikethis:
5;
Stringsareusedtorepresenttext.YournamecanberepresentedasastringinJavaScript,ascanyour
emailaddress.Stringslooklikethis:
"Hi,I'mastring";
Booleansarevaluesthatcanbetrueorfalse.Forexample,aBooleanvalueaboutyouwouldbewhether
youwearglasses.Anothercouldbewhetheryoulikebroccoli.ABooleanlookslikethis:
true;
Therearedifferentwaystoworkwitheachdatatype.Forexample,youcanmultiplytwonumbers,but
youcan’tmultiplytwostrings.Withastring,youcanaskforthefirstfivecharacters.WithBooleans,
youcanchecktoseewhethertwovaluesarebothtrue.Thefollowingcodeexampleillustrateseachof
thesepossibleoperations.
99*123;
12177
"Thisisalongstring".slice(0,4);
"This"
true&&false;
false
AlldatainJavaScriptisjustacombinationofthesetypesofdata.Inthischapter,we’lllookateachtype
inturnandlearndifferentwaystoworkwitheachtype.
NOTE
Youmayhavenoticedthatallofthesecommandsendwithasemicolon(;).SemicolonsmarktheendofaparticularJavaScript
commandorinstruction(alsocalledastatement),sortofliketheperiodattheendofasentence.
NumbersandOperators
JavaScriptletsyouperformbasicmathematicaloperationslikeaddition,subtraction,multiplication,and
division.Tomakethesecalculations,weusethesymbols+,-,*,and/,whicharecalledoperators.
YoucanusetheJavaScriptconsolejustlikeacalculator.We’vealreadyseenoneexample,adding
together3and4.Let’strysomethingharder.What’s12,345plus56,789?
12345+56789;
69134
That’snotsoeasytoworkoutinyourhead,butJavaScriptcalculateditinnotime.
Youcanaddmultiplenumberswithmultipleplussigns:
22+33+44;
99
JavaScriptcanalsodosubtraction...
1000-17;
983
andmultiplication,usinganasterisk...
123*456;
56088
anddivision,usingaforwardslash...
12345/250;
49.38
Youcanalsocombinethesesimpleoperationstomakesomethingmorecomplex,likethis:
1234+57*3-31/4;
1397.25
Hereitgetsabittricky,becausetheresultofthiscalculation(theanswer)willdependontheorderthat
JavaScriptdoeseachoperation.Inmath,theruleisthatmultiplicationanddivisionalwaystakeplace
beforeadditionandsubtraction,andJavaScriptfollowsthisruleaswell.
Figure2-1.Theorderofoperations:multiplication,division,addition,subtraction
Figure2-1showstheorderJavaScriptwouldfollow.First,JavaScriptmultiplies57*3andgets171
(showninred).Thenitdivides31/4toget7.75(showninblue).Nextitadds1234+171toget
1405(showningreen).Finallyitsubtracts1405-7.75toget1397.25,whichisthefinalresult.
Whatifyouwantedtodotheadditionandthesubtractionfirst,beforedoingthemultiplicationand
division?Forexample,sayyouhave1brotherand3sistersand8candies,andyouwanttosplitthe
candiesequallyamongyour4siblings?(You’vealreadytakenyourshare!)Youwouldhavetodivide8
byyournumberofsiblings.
Here’sanattempt:
8/1+3;
11
Thatcan’tberight!Youcan’tgiveeachsibling11candieswhenyou’veonlygot8!Theproblemisthat
JavaScriptdoesdivisionbeforeaddition,soitdivides8by1(whichequals8)andthenadds3tothat,
givingyou11.TofixthisandmakeJavaScriptdotheadditionfirst,wecanuseparentheses:
8/(1+3);
2
That’smorelikeit!Twocandiestoeachofyoursiblings.TheparenthesesforceJavaScripttoadd1and
3beforedividing8by4.
TRYITOUT!
Let’ssayyourfriendistryingtouseJavaScripttoworkouthowmanyballoonstobuy.She’sthrowingapartyandwantseveryoneto
have2balloonstoblowup.Therewereoriginally15peoplecoming,butthensheinvited9more.Shetriesthefollowingcode:
15+9*2;
33
Butthatdoesn’tseemright.
Theproblemisthatthemultiplicationishappeningbeforetheaddition.HowwouldyouaddparenthesestomakesurethatJavaScript
doestheadditionfirst?Howmanyballoonsdoesyourfriendreallyneed?
Variables
JavaScriptletsyougivenamestovaluesusingvariables.Youcanthinkofavariableasaboxthatyou
canfitonethingin.Ifyouputsomethingelseinit,thefirstthinggoesaway.
Tocreateanewvariable,usethekeywordvar,followedbythenameofthevariable.Akeywordisa
wordthathasspecialmeaninginJavaScript.Inthiscase,whenwetypevar,JavaScriptknowsthatwe
areabouttoenterthenameofanewvariable.Forexample,here’showyou’dmakeanewvariable
callednick:
varnick;
undefined
We’vecreatedanewvariablecallednick.Theconsolespitsoutundefinedinresponse.Butthisisn’t
anerror!That’sjustwhatJavaScriptdoeswheneveracommanddoesn’treturnavalue.What’sareturn
value?Well,forexample,whenyoutyped12345+56789;,theconsolereturnedthevalue69134.
CreatingavariableinJavaScriptdoesn’treturnavalue,sotheinterpreterprintsundefined.
Togivethevariableavalue,usetheequalsign:
varage=12;
undefined
Settingavalueiscalledassignment(weareassigningthevalue12tothevariableage).Again,
undefinedisprinted,becausewe’recreatinganothernewvariable.(Intherestofmyexamples,Iwon’t
showtheoutputwhenit’sundefined.)
Thevariableageisnowinourinterpreterandsettothevalue12.Thatmeansthatifyoutypeageonits
own,theinterpreterwillshowyouitsvalue:
age;
12
Cool!Thevalueofthevariableisn’tsetinstone,though(they’recalledvariablesbecausetheycan
vary),andifyouwanttoupdateit,justuse=again:
age=13;
13
ThistimeIdidn’tusethevarkeyword,becausethevariableagealreadyexists.Youneedtousevar
onlywhenyouwanttocreateavariable,notwhenyouwanttochangethevalueofavariable.Notice
also,becausewe’renotcreatinganewvariable,thevalue13isreturnedfromtheassignmentand
printedonthenextline.
Thisslightlymorecomplexexamplesolvesthecandiesproblemfromearlier,withoutparentheses:
varnumberOfSiblings=1+3;
varnumberOfCandies=8;
numberOfCandies/numberOfSiblings;
2
FirstwecreateavariablecallednumberOfSiblingsandassignitthevalueof1+3(whichJavaScript
worksouttobe4).ThenwecreatethevariablenumberOfCandiesandassign8toit.Finally,wewrite
numberOfCandies/numberOfSiblings.BecausenumberOfCandiesis8andnumberOfSiblingsis
4,JavaScriptworksout8/4andgivesus2.
NamingVariables
Becarefulwithyourvariablenames,becauseit’seasytomisspellthem.Evenifyoujustgetthe
capitalizationwrong,theJavaScriptinterpreterwon’tknowwhatyoumean!Forexample,ifyou
accidentallyusedalowercasecinnumberOfCandies,you’dgetanerror:
numberOfcandies/numberOfSiblings;
ReferenceError:numberOfcandiesisnotdefined
Unfortunately,JavaScriptwillonlydoexactlywhatyouaskittodo.Ifyoumisspellavariablename,
JavaScripthasnoideawhatyoumean,anditwilldisplayanerrormessage.
AnothertrickythingaboutvariablenamesinJavaScriptisthattheycan’tcontainspaces,whichmeans
theycanbedifficulttoread.Icouldhavenamedmyvariablenumberofcandieswithnocapitalletters,
whichmakesitevenhardertoreadbecauseit’snotclearwherethewordsend.Isthisvariable“numb
erofcandies”or“numberofcandies”?Withoutthecapitalletters,it’shardtotell.
OnecommonwaytogetaroundthisistostarteachwordwithacapitalletterasinNumberOfCandies.
(Thisconventioniscalledcamelcasebecauseitsupposedlylookslikethehumpsonacamel.)
Thestandardpracticeistohavevariablesstartwithalowercaseletter,soit’scommontocapitalizeeach
wordexceptforthefirstone,likethis:numberOfCandies.(I’llfollowthisversionofthecamelcase
conventionthroughoutthisbook,butyou’refreetodowhateveryouwant!)
CreatingNewVariablesUsingMath
Youcancreatenewvariablesbydoingsomemathonolderones.Forexample,youcanusevariablesto
findouthowmanysecondsthereareinayear—andhowmanysecondsoldyouare!Let’sstartby
findingthenumberofsecondsinanhour.
SecondsinanHour
FirstwecreatetwonewvariablescalledsecondsInAMinuteandminutesInAnHourandmakethem
both60(because,asweknow,thereare60secondsinaminuteand60minutesinanhour).Thenwe
createavariablecalledsecondsInAnHourandsetitsvaluetotheresultofmultiplying
secondsInAMinuteandminutesInAnHour.At➊,weentersecondsInAnHour,whichislikesaying,
“TellmethevalueofsecondsInAnHourrightnow!”JavaScriptthengivesyoutheanswer:it’s3600.
varsecondsInAMinute=60;
varminutesInAnHour=60;
varsecondsInAnHour=secondsInAMinute*minutesInAnHour;
➊secondsInAnHour;
3600
SecondsinaDay
NowwecreateavariablecalledhoursInADayandsetitto24.Nextwecreatethevariable
secondsInADayandsetitequaltosecondsInAnHourmultipliedbyhoursInADay.Whenweaskforthe
valuesecondsInADayat➊,weget86400,whichisthenumberofsecondsinaday.
varhoursInADay=24;
varsecondsInADay=secondsInAnHour*hoursInADay;
➊secondsInADay;
86400
SecondsinaYear
Finally,wecreatethevariablesdaysInAYearandsecondsInAYear.ThedaysInAYearvariableis
assignedthevalue365,andthevariablesecondsInAYearisassignedthevalueofsecondsInADay
multipliedbydaysInAYear.Finally,weaskforthevalueofsecondsInAYear,whichis31536000
(morethan31million)!
vardaysInAYear=365;
varsecondsInAYear=secondsInADay*daysInAYear;
secondsInAYear;
31536000
AgeinSeconds
Nowthatyouknowthenumberofsecondsinayear,youcaneasilyfigureouthowoldyouarein
seconds(tothenearestyear).Forexample,asI’mwritingthis,I’m29:
varage=29;
age*secondsInAYear;
914544000
Tofigureoutyourageinseconds,enterthesamecode,butchangethevalueinagetoyourage.Orjust
leaveouttheagevariablealtogetheranduseanumberforyourage,likethis:
29*secondsInAYear;
914544000
I’mmorethan900millionsecondsold!Howmanysecondsoldareyou?
IncrementingandDecrementing
Asaprogrammer,you’lloftenneedtoincreaseordecreasethevalueofavariablecontaininganumber
by1.Forexample,youmighthaveavariablethatcountsthenumberofhigh-fivesyoureceivedtoday.
Eachtimesomeonehigh-fivesyou,you’dwanttoincreasethatvariableby1.
Increasingby1iscalledincrementing,anddecreasingby1iscalleddecrementing.Youincrementand
decrementusingtheoperators++and--.
varhighFives=0;
++highFives;
1
++highFives;
2
--highFives;
1
Whenweusethe++operator,thevalueofhighFivesgoesupby1,andwhenweusethe--operator,it
goesdownby1.Youcanalsoputtheseoperatorsafterthevariable.Thisdoesthesamething,butthe
valuethatgetsreturnedisthevaluebeforetheincrementordecrement.
highFives=0;
highFives++;
0
highFives++;
1
highFives;
2
Inthisexample,wesethighFivesto0again.WhenwecallhighFives++,thevariableisincremented,
butthevaluethatgetsprintedisthevaluebeforetheincrementhappened.Youcanseeattheend(after
twoincrements)thatifweaskforthevalueofhighFives,weget2.
+=(plus-equals)and–=(minus-equals)
Toincreasethevalueofavariablebyacertainamount,youcouldusethiscode:
varx=10;
x=x+5;
x;
15
Here,westartoutwithavariablecalledx,setto10.Then,weassignx+5tox.Becausexwas10,x+
5willbe15.Whatwe’redoinghereisusingtheoldvalueofxtoworkoutanewvalueforx.Therefore,
x=x+5reallymeans“add5tox.”
JavaScriptgivesyouaneasierwayofincreasingordecreasingavariablebyacertainamount,withthe
+=and-=operators.Forexample,ifwehaveavariablex,thenx+=5isthesameassayingx=x+
5.The-=operatorworksinthesameway,sox-=9wouldbethesameasx=x-9(“subtract9
fromx”).Here’sanexampleusingbothoftheseoperatorstokeeptrackofascoreinavideogame:
varscore=10;
score+=7;
17
score-=3;
14
Inthisexample,westartwithascoreof10byassigningthevalue10tothevariablescore.Thenwe
beatamonster,whichincreasesscoreby7usingthe+=operator.(score+=7isthesameasscore=
score+7.)Beforewebeatthemonster,scorewas10,and10+7is17,sothisoperationsetsscore
to17.
Afterourvictoryoverthemonster,wecrashintoameteorandscoreisreducedby3.Again,score-=
3isthesameasscore=score-3.Becausescoreis17atthispoint,score-3is14,andthat
valuegetsreassignedtoscore.
TRYITOUT!
Therearesomeotheroperatorsthataresimilarto+=and-=.Forexample,thereare*=and/=.Whatdoyouthinkthesedo?Givethema
try:
varballoons=100;
balloons*=2;
???
Whatdoesballoons*=2do?Nowtrythis:
varballoons=100;
balloons/=4;
???
Whatdoesballoons/=4do?
Strings
Sofar,we’vejustbeenworkingwithnumbers.Nowlet’slookatanothertypeofdata:strings.Stringsin
JavaScript(asinmostprogramminglanguages)arejustsequencesofcharacters,whichcaninclude
letters,numbers,punctuation,andspaces.WeputstringsbetweenquotessoJavaScriptknowswhere
theystartandend.Forexample,here’saclassic:
"Helloworld!";
"Helloworld!"
Toenterastring,justtypeadoublequotationmark(")followedbythetextyouwantinthestring,and
thenclosethestringwithanotherdoublequote.Youcanalsousesinglequotes('),buttokeepthings
simple,we’lljustbeusingdoublequotesinthisbook.
Youcansavestringsintovariables,justlikenumbers:
varmyAwesomeString="SomethingREALLYawesome!!!";
There’salsonothingstoppingyoufromassigningastringtoavariablethatpreviouslycontaineda
number:
varmyThing=5;
myThing="thisisastring";
"thisisastring"
Whatifyouputanumberbetweenquotes?Isthatastringoranumber?InJavaScript,astringisastring
(evenifithappenstohavesomecharactersthatarenumbers).Forexample:
varnumberNine=9;
varstringNine="9";
numberNineisanumber,andstringNineisastring.Toseehowthesearedifferent,let’stryadding
themtogether:
numberNine+numberNine;
18
stringNine+stringNine;
"99"
Whenweaddthenumbervalues9and9,weget18.Butwhenweusethe+operatoron"9"and"9",
thestringsaresimplyjoinedtogethertoform"99".
JoiningStrings
Asyoujustsaw,youcanusethe+operatorwithstrings,buttheresultisverydifferentfromusingthe+
operatorwithnumbers.Whenyouuse+tojointwostrings,youmakeanewstringwiththesecond
stringattachedtotheendofthefirststring,likethis:
vargreeting="Hello";
varmyName="Nick";
greeting+myName;
"HelloNick"
Here,wecreatetwovariables(greetingandmyName)andassigneachastringvalue("Hello"and
"Nick",respectively).Whenweaddthesetwovariablestogether,thestringsarecombinedtomakea
newstring,"HelloNick".
Thatdoesn’tlookright,though—thereshouldbeaspacebetweenHelloandNick.ButJavaScript
won’tputaspacethereunlesswespecificallytellittobyaddingaspaceinoneoftheoriginalstrings:
➊vargreeting="Hello";
varmyName="Nick";
greeting+myName;
"HelloNick"
Theextraspaceinsidethequotesat➊putsaspaceinthefinalstringaswell.
Youcandoalotmorewithstringsotherthanjustaddingthemtogether.Herearesomeexamples.
FindingtheLengthofaString
Togetthelengthofastring,justadd.lengthtotheendofit.
"Supercalifragilisticexpialidocious".length;
34
Youcanadd.lengthtotheendoftheactualstringortoavariablethatcontainsastring:
varjava="Java";
java.length;
4
varscript="Script";
script.length;
6
varjavascript=java+script;
javascript.length;
10
Hereweassignthestring"Java"tothevariablejavaandthestring"Script"tothevariablescript.
Thenweadd.lengthtotheendofeachvariabletodeterminethelengthofeachstring,aswellasthe
lengthofthecombinedstrings.
NoticethatIsaidyoucanadd.lengthto“theactualstringortoavariablethatcontainsastring.”This
illustratessomethingveryimportantaboutvariables:anywhereyoucanuseanumberorastring,you
canalsouseavariablecontaininganumberorastring.
GettingaSingleCharacterfromaString
Sometimesyouwanttogetasinglecharacterfromastring.Forexample,youmighthaveasecretcode
wherethemessageismadeupofthesecondcharacterofeachwordinalistofwords.You’dneedtobe
abletogetjustthesecondcharactersandjointhemalltogethertocreateanewword.
Togetacharacterfromaparticularpositioninastring,usesquarebrackets,[].Justtakethestring,or
thevariablecontainingthestring,andputthenumberofthecharacteryouwantinapairofsquare
bracketsattheend.Forexample,togetthefirstcharacterofmyName,usemyName[0],likethis:
varmyName="Nick";
myName[0];
"N"
myName[1];
"i"
myName[2];
"c"
Noticethattogetthefirstcharacterofthestring,weuse0ratherthan1.That’sbecauseJavaScript(like
manyotherprogramminglanguages)startscountingatzero.Thatmeanswhenyouwantthefirst
characterofastring,youuse0;whenyouwantthesecondone,youuse1;andsoon.
Let’stryoutoursecretcode,wherewehideamessageinsomewords’secondcharacters.Here’showto
findthesecretmessageinasequenceofwords:
varcodeWord1="are";
varcodeWord2="tubas";
varcodeWord3="unsafe";
varcodeWord4="?!";
codeWord1[1]+codeWord2[1]+codeWord3[1]+codeWord4[1];
"run!"
Again,noticethattogetthesecondcharacterofeachstring,weuse1.
CuttingUpStrings
To“cutoff”apieceofabigstring,youcanuseslice.Forexample,youmightwanttograbthefirstbit
ofalongmoviereviewtoshowasateaseronyourwebsite.Touseslice,putaperiodafterastring(or
avariablecontainingastring),followedbythewordsliceandopeningandclosingparentheses.Inside
theparentheses,enterthestartandendpositionsofthesliceofthestringyouwant,separatedbya
comma.Figure2-2showshowtouseslice.
Figure2-2.Howtouseslicetogetcharactersfromastring
Forexample:
varlongString="Mylongstringislong";
longString.slice(3,14);
"longstring"
Thefirstnumberinparenthesesisthenumberofthecharacterthatbeginstheslice,andthesecond
numberisthenumberofthecharacterafterthelastcharacterintheslice.Figure2-3showswhich
charactersthisretrieves,withthestartvalue(3)andstopvalue(14)highlightedinblue.
Figure2-3.Intheexampleabove,slicegrabsthecharactersshowninthegraybox.
HerewebasicallytellJavaScript,“Pullasliceoutofthislongerstringstartingatthecharacteratplace3
andkeepgoinguntilyouhitplace14.”
Ifyouincludeonlyonenumberintheparenthesesafterslice,thestringthatitsliceswillstartfrom
thatnumberandcontinueallthewaytotheendofthestring,likethis:
varlongString="Mylongstringislong";
longString.slice(3);
"longstringislong"
ChangingStringstoAllCapitalorAllLowercaseLetters
Ifyouhavesometextthatyoujustwanttoshout,tryusingtoUpperCasetoturnitallintocapital
letters.
"Hellothere,howareyoudoing?".toUpperCase();
"HELLOTHERE,HOWAREYOUDOING?"
Whenyouuse.toUpperCase()onastring,itmakesanewstringwhereallthelettersareturnedinto
uppercase.
Youcangotheotherwayaround,too:
"hELloTHERE,hOWAREyOudoINg?".toLowerCase();
"hellothere,howareyoudoing?"
Asthenamesuggests,.toLowerCase()makesallofthecharacterslowercase.Butshouldn’tsentences
alwaysstartwithacapitalletter?Howcanwetakeastringandmakethefirstletteruppercasebutturn
therestintolowercase?
NOTE
Seeifyoucanfigureouthowtoturn"hELloTHERE,hOWAREyOudoINg?"into"Hellothere,howareyoudoing?"usingthetools
youjustlearned.Ifyougetstuck,reviewthesectionsongettingasinglecharacterandusingslice.Onceyou’redone,comebackand
havealookathowIdidit.
Here’soneapproach:
➊varsillyString="hELloTHERE,hOWAREyOudoINg?";
➋varlowerString=sillyString.toLowerCase();
➌varfirstCharacter=lowerString[0];
➍varfirstCharacterUpper=firstCharacter.toUpperCase();
➎varrestOfString=lowerString.slice(1);
➏firstCharacterUpper+restOfString;
"Hellothere,howareyoudoing?"
Let’sgothroughthislinebyline.At➊,wecreateanewvariablecalledsillyStringandsavethe
stringwewanttomodifytothatvariable.At➋,wegetthelowercaseversionofsillyString("hello
therehowareyoudoing?")with.toLowerCase()andsavethatinanewvariablecalled
lowerString.
At➌,weuse[0]togetthefirstcharacteroflowerString("h")andsaveitinfirstCharacter(0is
usedtograbthefirstcharacter).Then,at➍,wecreateanuppercaseversionoffirstCharacter("H")
andcallthatfirstCharacterUpper.
At➎,weuseslicetogetallthecharactersinlowerString,startingfromthesecondcharacter("ello
therehowareyoudoing?")andsavethatinrestOfString.Finally,at➏,weadd
firstCharacterUpper("H")torestOfStringtoget"Hellothere,howareyoudoing?".
Becausevaluesandvariablescanbesubstitutedforeachother,wecouldturnlines➋through➏into
justoneline,likethis:
varsillyString="hELloTHERE,hOWAREyOudoINg?";
sillyString[0].toUpperCase()+sillyString.slice(1).toLowerCase();
"Hellothere,howareyoudoing?"
Itcanbeconfusingtofollowalongwithcodewrittenthisway,though,soit’sagoodideatouse
variablesforeachstepofacomplicatedtasklikethis—atleastuntilyougetmorecomfortablereading
thiskindofcomplexcode.
Booleans
NowforBooleans.ABooleanvalueissimplyavaluethat’seithertrueorfalse.Forexample,here’sa
simpleBooleanexpression.
varjavascriptIsCool=true;
javascriptIsCool;
true
Inthisexample,wecreatedanewvariablecalledjavascriptIsCoolandassignedtheBooleanvalue
truetoit.Onthesecondline,wegetthevalueofjavascriptIsCool,which,ofcourse,istrue!
LogicalOperators
Justasyoucancombinenumberswithmathematicaloperators(+,-,*,/,andsoon),youcancombine
BooleanvalueswithBooleanoperators.WhenyoucombineBooleanvalueswithBooleanoperators,the
resultwillalwaysbeanotherBooleanvalue(eithertrueorfalse).
ThethreemainBooleanoperatorsinJavaScriptare&&,||,and!.Theymaylookabitweird,butwitha
littlepractice,they’renothardtouse.Let’strythemout.
&&(and)
&&means“and.”Whenreadingaloud,peoplecallit“and,”“andand,”or“ampersand-ampersand.”
(Ampersandisthenameofthecharacter&.)Usethe&&operatorwithtwoBooleanvaluestoseeif
they’rebothtrue.
Forexample,beforeyougotoschool,youwanttomakesurethatyou’vehadashowerandyouhave
yourbackpack.Ifbotharetrue,youcangotoschool,butifoneorbotharefalse,youcan’tleaveyet.
varhadShower=true;
varhasBackpack=false;
hadShower&&hasBackpack;
false
HerewesetthevariablehadShowertotrueandthevariablehasBackpacktofalse.Whenweenter
hadShower&&hasBackpack,wearebasicallyaskingJavaScript,“Arebothofthesevaluestrue?”
Sincetheyaren’tbothtrue(youdon’thaveyourbackpack),JavaScriptreturnsfalse(you’renotready
forschool).
Let’strythisagain,withbothvaluessettotrue:
varhadShower=true;
varhasBackpack=true;
hadShower&&hasBackpack;
true
NowJavaScripttellsusthathadShower&&hasBackpackistrue.You’rereadyforschool!
||(or)
TheBooleanoperator||means“or.”Itcanbepronounced“or,”oreven“or-or,”butsomepeoplecallit
“pipes,”becauseprogrammerscallthe|characterapipe.YoucanusethisoperatorwithtwoBoolean
valuestofindoutwhethereitheroneistrue.
Forexample,sayyou’restillgettingreadytogotoschoolandyouneedtotakeapieceoffruitfor
lunch,butitdoesn’tmatterwhetheryoutakeanappleoranorangeorboth.YoucanuseJavaScriptto
seewhetheryouhaveatleastone,likethis:
varhasApple=true;
varhasOrange=false;
hasApple||hasOrange;
true
hasApple||hasOrangewillbetrueifeitherhasAppleorhasOrangeistrue,orifbotharetrue.
Butifbotharefalse,theresultwillbefalse(youdon’thaveanyfruit).
!(not)
!justmeans“not.”Youcancallit“not,”butlotsofpeoplecallit“bang.”(Anexclamationpointis
sometimescalledabang.)Useittoturnfalseintotrueortrueintofalse.Thisisusefulforworking
withvaluesthatareopposites.Forexample:
varisWeekend=true;
varneedToShowerToday=!isWeekend;
needToShowerToday;
false
Inthisexample,wesetthevariableisWeekendtotrue.ThenwesetthevariableneedToShowerToday
to!isWeekend.Thebangconvertsthevaluetoitsopposite—soifisWeekendistrue,then
!isWeekendisnottrue(it’sfalse).SowhenweaskforthevalueofneedToShowerToday,weget
false(youdon’tneedtoshowertoday,becauseit’stheweekend).
BecauseneedToShowerTodayisfalse,!needToShowerTodaywillbetrue:
needToShowerToday;
false
!needToShowerToday;
true
Inotherwords,it’struethatyoudonotneedtoshowertoday.
Combininglogicaloperators
Operatorsgetinterestingwhenyoustartcombiningthem.Forexample,sayyoushouldgotoschoolif
it’snottheweekendandyou’veshoweredandyouhaveanappleoryouhaveanorange.Wecould
checkwhetherallofthisistruewithJavaScript,likethis:
varisWeekend=false;
varhadShower=true;
varhasApple=false;
varhasOrange=true;
varshouldGoToSchool=!isWeekend&&hadShower&&(hasApple||hasOrange);
shouldGoToSchool;
true
Inthiscase,it’snottheweekend,youhaveshowered,andyoudon’thaveanapplebutyoudohavean
orange—soyoushouldgotoschool.
hasApple||hasOrangeisinparenthesesbecausewewanttomakesureJavaScriptworksoutthatbit
first.JustasJavaScriptcalculates*before+withnumbers,italsocalculates&&before||inlogical
statements.
ComparingNumberswithBooleans
Booleanvaluescanbeusedtoanswerquestionsaboutnumbersthathaveasimpleyesornoanswer.For
example,imagineyou’rerunningathemeparkandoneoftherideshasaheightrestriction:ridersmust
beatleast60inchestall,ortheymightfallout!Whensomeonewantstogoontherideandtellsyou
theirheight,youneedtoknowifit’sgreaterthanthisheightrestriction.
GreaterThan
Wecanusethegreater-thanoperator(>)toseeifonenumberisgreaterthananother.Forexample,to
seeiftherider’sheight(65inches)isgreaterthantheheightrestriction(60inches),wecouldsetthe
variableheightequalto65andthevariableheightRestrictionequalto60,andthenuse>to
comparethetwo:
varheight=65;
varheightRestriction=60;
height>heightRestriction;
true
Withheight>heightRestriction,we’reaskingJavaScripttotelluswhetherthefirstvalueis
greaterthanthesecond.Inthiscase,therideristallenough!
Whatifariderwereexactly60inchestall,though?
varheight=60;
varheightRestriction=60;
height>heightRestriction;
false
Ohno!Theriderisn’ttallenough!Butiftheheightrestrictionis60,thenshouldn’tpeoplewhoare
exactly60inchesbeallowedin?Weneedtofixthat.Luckily,JavaScripthasanotheroperator,>=,
whichmeans“greaterthanorequalto”:
varheight=60;
varheightRestriction=60;
height>=heightRestriction;
true
Good,that’sbetter—60isgreaterthanorequalto60.
LessThan
Theoppositeofthegreater-thanoperator(>)istheless-thanoperator(<).Thisoperatormightcomein
handyifarideweredesignedonlyforsmallchildren.Forexample,saytherider’sheightis60inches,
butridersmustbenomorethan48inchestall:
varheight=60;
varheightRestriction=48;
height<heightRestriction;
false
Wewanttoknowiftherider’sheightislessthantherestriction,soweuse<.Because60isnotlessthan
48,wegetfalse(someonewhoseheightis60inchesistootallforthisride).
And,asyoumayhaveguessed,wecanalsousetheoperator<=,whichmeans“lessthanorequalto”:
varheight=48;
varheightRestriction=48;
height<=heightRestriction;
true
Someonewhois48inchestallisstillallowedtogoontheride.
EqualTo
Tofindoutiftwonumbersareexactlythesame,usethetripleequalsign(===),whichmeansEqualTo.
Butbecarefulnottoconfuse===withasingleequalsign(=),because===means“arethesetwo
numbersequal?”and=means“savethevalueontherightinthevariableontheleft.”Inotherwords,
===asksaquestion,while=assignsavaluetoavariable.
Whenyouuse=,avariablenamehastobeontheleftandthevalueyouwanttosavetothatvariable
mustbeontheright.Ontheotherhand,===isjustusedforcomparingtwovaluestoseeifthey’rethe
same,soitdoesn’tmatterwhichvalueisonwhichside.
Forexample,sayyou’rerunningacompetitionwithyourfriendsChico,Harpo,andGrouchotoseewho
canguessyoursecretnumber,whichis5.Youmakeiteasyonyourfriendsbysayingthatthenumberis
between1and9,andtheystarttoguess.FirstyousetmySecretNumberequalto5.Yourfirstfriend,
Chico,guessesthatit’s3(chicoGuess).Let’sseewhathappensnext:
varmySecretNumber=5;
varchicoGuess=3;
mySecretNumber===chicoGuess;
false
varharpoGuess=7;
mySecretNumber===harpoGuess;
false
vargrouchoGuess=5;
mySecretNumber===grouchoGuess;
true
ThevariablemySecretNumberstoresyoursecretnumber.ThevariableschicoGuess,harpoGuess,and
grouchoGuessrepresentyourfriends’guesses,andweuse===toseewhethereachguessisthesameas
yoursecretnumber.Yourthirdfriend,Groucho,winsbyguessing5.
Whenyoucomparetwonumberswith===,yougettrueonlywhenbothnumbersarethesame.
BecausegrouchoGuessis5andmySecretNumberis5,mySecretNumber===grouchoGuessreturns
true.Theotherguessesdidn’tmatchmySecretNumber,sotheyreturnedfalse.
Youcanalsouse===tocomparetwostringsortwoBooleans.Ifyouuse===tocomparetwodifferent
types—forexample,astringandanumber—itwillalwaysreturnfalse.
DoubleEquals
Nowtoconfusethingsabit:there’sanotherJavaScriptoperator(doubleequals,or==)thatmeans
“equal-ish.”Usethistoseewhethertwovaluesarethesame,evenifoneisastringandtheotherisa
number.Allvalueshavesomekindoftype.Sothenumber5isdifferentfromthestring"5",even
thoughtheybasicallylooklikethesamething.Ifyouuse===tocomparethenumber5andthestring
"5",JavaScriptwilltellyouthey’renotequal.Butifyouuse==tocomparethem,itwilltellyou
they’rethesame:
varstringNumber="5";
varactualNumber=5;
stringNumber===actualNumber;
false
stringNumber==actualNumber;
true
Atthispoint,youmightbethinkingtoyourself,“Hmm,itseemsmucheasiertousedoubleequalsthan
tripleequals!”Youhavetobeverycareful,though,becausedoubleequalscanbeveryconfusing.For
example,doyouthink0isequaltofalse?Whataboutthestring"false"?Whenyouusedouble
equals,0isequaltofalse,butthestring"false"isnot:
0==false;
true
"false"==false;
false
ThisisbecausewhenJavaScripttriestocomparetwovalueswithdoubleequals,itfirsttriestomake
themthesametype.Inthiscase,itconvertstheBooleanintoanumber.IfyouconvertBooleansto
numbers,falsebecomes0,andtruebecomes1.Sowhenyoutype0==false,yougettrue!
Becauseofthisweirdness,it’sprobablysafesttojuststickwith===fornow.
TRYITOUT!
You’vebeenaskedbythelocalmovietheatermanagerstoimplementsomeJavaScriptforanewautomatedsystemthey’rebuilding.
TheywanttobeabletoworkoutwhethersomeoneisallowedintoaPG-13movieornot.
Therulesare,ifsomeoneis13orover,they’reallowedin.Ifthey’renotover13,buttheyareaccompaniedbyanadult,they’realso
allowedin.Otherwise,theycan’tseethemovie.
varage=12;
varaccompanied=true;
???
Finishthisexampleusingtheageandaccompaniedvariablestoworkoutwhetherthis12-year-oldisallowedtoseethemovie.Try
changingthevalues(forexample,setageto13andaccompaniedtofalse)andseeifyourcodestillworksouttherightanswer.
undefinedandnull
Finally,wehavetwovaluesthatdon’tfitanyparticularmold.They’recalledundefinedandnull.
They’rebothusedtomean“nothing,”butinslightlydifferentways.
undefinedisthevalueJavaScriptuseswhenitdoesn’thaveavalueforsomething.Forexample,when
youcreateanewvariable,ifyoudon’tsetitsvaluetoanythingusingthe=operator,itsvaluewillbeset
toundefined:
varmyVariable;
myVariable;
undefined
Thenullvalueisusuallyusedwhenyouwanttodeliberatelysay“Thisisempty.”
varmyNullVariable=null;
myNullVariable;
null
Atthispoint,youwon’tbeusingundefinedornullveryoften.You’llseeundefinedifyoucreatea
variableanddon’tsetitsvalue,becauseundefinediswhatJavaScriptwillalwaysgiveyouwhenit
doesn’thaveavalue.It’snotverycommontosetsomethingtoundefined;ifyoufeeltheneedtoseta
variableto“nothing,”youshouldusenullinstead.
nullisusedonlywhenyouactuallywanttosaysomething’snotthere,whichisveryoccasionally
helpful.Forexample,sayyou’reusingavariabletotrackwhatyourfavoritevegetableis.Ifyouhateall
vegetablesanddon’thaveafavorite,youmightsetthefavoritevegetablevariabletonull.
Settingthevariabletonullwouldmakeitobvioustoanyonereadingthecodethatyoudon’thavea
favoritevegetable.Ifitwereundefined,however,someonemightjustthinkyouhadn’tgottenaround
tosettingavalueyet.
WhatYouLearned
NowyouknowallthebasicdatatypesinJavaScript—numbers,strings,andBooleans—aswellasthe
specialvaluesnullandundefined.Numbersareusedformath-typethings,stringsareusedfortext,
andBooleansareusedforyesornoquestions.Thevaluesnullandundefinedaretheretogiveusa
waytotalkaboutthingsthatdon’texist.
Inthenexttwochapters,we’lllookatarraysandobjects,whicharebothwaysofjoiningbasictypesto
createmorecomplexcollectionsofvalues.
Chapter3.Arrays
Sofarwe’velearnedaboutnumbersandstrings,whicharetypesofdatathatyoucanstoreandusein
yourprograms.Butnumbersandstringsarekindofboring.There’snotalotthatyoucandowitha
stringonitsown.JavaScriptletsyoucreateandgrouptogetherdatainmoreinterestingwayswith
arrays.AnarrayisjustalistofotherJavaScriptdatavalues.
Forexample,ifyourfriendaskedyouwhatyourthreefavoritedinosaurswere,youcouldcreatean
arraywiththenamesofthosedinosaurs,inorder:
varmyTopThreeDinosaurs=["T-Rex","Velociraptor","Stegosaurus"];
Soinsteadofgivingyourfriendthreeseparatestrings,youcanjustusethesinglearray
myTopThreeDinosaurs.
WhyShouldYouCareAboutArrays?
Let’slookatdinosaursagain.Sayyouwanttouseaprogramtokeeptrackofthemanykindsof
dinosaursyouknowabout.Youcouldcreateavariableforeachdinosaur,likethis:
vardinosaur1="T-Rex";
vardinosaur2="Velociraptor";
vardinosaur3="Stegosaurus";
vardinosaur4="Triceratops";
vardinosaur5="Brachiosaurus";
vardinosaur6="Pteranodon";
vardinosaur7="Apatosaurus";
vardinosaur8="Diplodocus";
vardinosaur9="Compsognathus";
Thislistisprettyawkwardtouse,though,becauseyouhaveninedifferentvariableswhenyoucould
havejustone.Imagineifyouwerekeepingtrackof1000dinosaurs!You’dneedtocreate1000separate
variables,whichwouldbealmostimpossibletoworkwith.
It’slikeifyouhadashoppinglist,buteveryitemwasonadifferentpieceofpaper.You’dhaveone
pieceofpaperthatsaid“eggs,”anotherpiecethatsaid“bread,”andanotherpiecethatsaid“oranges.”
Mostpeoplewouldwritethefulllistofthingstheywanttobuyonasinglepieceofpaper.Wouldn’tit
bemucheasierifyoucouldgroupallninedinosaurstogetherinjustoneplace?
Youcan,andthat’swherearrayscomein.
CreatinganArray
Tocreateanarray,youjustusesquarebrackets,[].Infact,anemptyarrayissimplyapairofsquare
brackets,likethis:
[];
[]
Butwhocaresaboutanemptyarray?Let’sfillitwithourdinosaurs!
Tocreateanarraywithvaluesinit,enterthevalues,separatedbycommas,betweenthesquarebrackets.
Wecancalltheindividualvaluesinanarrayitemsorelements.Inthisexample,ourelementswillbe
strings(thenamesofourfavoritedinosaurs),sowe’llwritethemwithquotemarks.We’llstorethe
arrayinavariablecalleddinosaurs:
vardinosaurs=["T-Rex","Velociraptor","Stegosaurus",
"Triceratops","Brachiosaurus","Pteranodon","Apatosaurus",
"Diplodocus","Compsognathus"];
NOTE
Becausethisisabookandthepageisonlysowide,wecan’tactuallyfitthewholearrayononeline.The istoshowwherewe’veput
thecodeontoanextralinebecausethepageistoonarrow.Whenyoutypethisintoyourcomputer,youcantypeitallononeline.
Longlistscanbehardtoreadononeline,butluckilythat’snottheonlywaytoformat(orlayout)an
array.Youcanalsoformatanarraywithanopeningsquarebracketononeline,thelistofitemsinthe
arrayeachonanewline,andaclosingsquarebracket,likethis:
vardinosaurs=[
"T-Rex",
"Velociraptor",
"Stegosaurus",
"Triceratops",
"Brachiosaurus",
"Pteranodon",
"Apatosaurus",
"Diplodocus",
"Compsognathus"
];
Ifyouwanttotypethisintoyourbrowserconsole,you’llneedtoholddowntheSHIFTkeywhenyou
presstheENTERkeyforeachnewline.OtherwisetheJavaScriptinterpreterwillthinkyou’retryingto
executethecurrent,incomplete,line.Whilewe’reworkingintheinterpreter,it’seasiertowritearrays
ononeline.
Whetheryouchoosetoformattheitemsinanarrayononelineoronseparatelines,it’sallthesameto
JavaScript.Howevermanylinebreaksyouuse,JavaScriptjustseesanarray—inthisexample,an
arraycontainingninestrings.
AccessinganArray’sElements
Whenit’stimetoaccesselementsinanarray,youusesquarebracketswiththeindexoftheelementyou
want,asyoucanseeinthefollowingexample:
dinosaurs[0];
"T-Rex"
dinosaurs[3];
"Triceratops"
Anindexisthenumberthatcorrespondsto(ormatches)thespotinthearraywhereavalueisstored.
Justaswithstrings,thefirstelementinanarrayisatindex0,thesecondisatindex1,thethirdatindex
2,andsoon.That’swhyaskingforindex0fromthedinosaursarrayreturns"T-Rex"(whichisfirstin
thelist),andindex3returns"Triceratops"(whichisfourthinthelist).
It’susefultobeabletoaccessindividualelementsfromanarray.Forexample,ifyoujustwantedto
showsomeoneyourabsolutefavoritedinosaur,youwouldn’tneedthewholedinosaursarray.Instead
youwouldjustwantthefirstelement:
dinosaurs[0];
"T-Rex"
SettingorChangingElementsinanArray
Youcanuseindexesinsquarebracketstoset,change,orevenaddelementstoanarray.Forexample,to
replacethefirstelementinthedinosaursarray("T-Rex")with"TyrannosaurusRex",youcoulddo
this:
dinosaurs[0]="TyrannosaurusRex";
Afteryou’vedonethat,thedinosaursarraywouldlooklikethis:
["TyrannosaurusRex","Velociraptor","Stegosaurus","Triceratops",
"Brachiosaurus","Pteranodon","Apatosaurus","Diplodocus",
"Compsognathus"]
Youcanalsousesquarebracketswithindexestoaddnewelementstoanarray.Forexample,here’show
youcouldcreatethedinosaursarraybysettingeachelementindividuallywithsquarebrackets:
vardinosaurs=[];
dinosaurs[0]="T-Rex";
dinosaurs[1]="Velociraptor";
dinosaurs[2]="Stegosaurus";
dinosaurs[3]="Triceratops";
dinosaurs[4]="Brachiosaurus";
dinosaurs[5]="Pteranodon";
dinosaurs[6]="Apatosaurus";
dinosaurs[7]="Diplodocus";
dinosaurs[8]="Compsognathus";
dinosaurs;
["T-Rex","Velociraptor","Stegosaurus","Triceratops",
"Brachiosaurus","Pteranodon","Apatosaurus","Diplodocus",
"Compsognathus"]
Firstwecreateanemptyarraywithvardinosaurs=[].Then,witheachfollowinglineweadda
valuetothelistwithaseriesofdinosaurs[]entries,fromindex0toindex8.Oncewefinishthelist,
wecanviewthearray(bytypingdinosaurs;).WeseethatJavaScripthasstoredallthenamesordered
accordingtotheindexes.
Youcanactuallyaddanelementatanyindexyouwant.Forexample,toaddanew(made-up)dinosaur
atindex33,youcouldwritethefollowing:
dinosaurs[33]="Philosoraptor";
dinosaurs;
["T-Rex","Velociraptor","Stegosaurus","Triceratops",
"Brachiosaurus","Pteranodon","Apatosaurus","Diplodocus",
"Compsognathus",undefined×24"Philosoraptor"]
Theelementsbetweenindexes8and33willbeundefined.Whenyououtputthearray,Chrome
helpfullytellsyouhowmanyelementswereundefined,ratherthanlistingthemallindividually.
MixingDataTypesinanArray
Arrayelementsdon’tallhavetobethesametype.Forexample,thenextarraycontainsanumber(3),a
string("dinosaurs"),anarray(["triceratops","stegosaurus",3627.5]),andanothernumber
(10):
vardinosaursAndNumbers=[3,"dinosaurs",["triceratops",
"stegosaurus",3627.5],10];
Toaccessanindividualelementinthisarray’sinnerarray,youwouldjustuseasecondsetofsquare
brackets.Forexample,whiledinosaursAndNumbers[2];returnstheentireinnerarray,
dinosaursAndNumbers[2][0];returnsonlythefirstelementofthatinnerarray,whichis
"triceratops".
dinosaursAndNumbers[2];
["triceratops","stegosaurus",3627.5]
dinosaursAndNumbers[2][0];
"triceratops"
WhenwetypedinosaursAndNumbers[2][0];,wetellJavaScripttolookatindex2ofthearray
dinosaursAndNumbers,whichcontainsthearray["triceratops","stegosaurus",3627.5],and
toreturnthevalueatindex0ofthatsecondarray.Index0isthefirstvalueofthesecondarray,whichis
"triceratops".Figure3-1showstheindexpositionsforthisarray.
Figure3-1.Theindexpositionsofthemainarrayarelabeledinred,andtheindexesoftheinnerarrayarelabeledinblue.
WorkingwithArrays
Propertiesandmethodshelpyouworkwitharrays.Propertiesgenerallytellyousomethingaboutthe
array,andmethodsusuallydosomethingtochangethearrayorreturnanewarray.Let’shavealook.
FindingtheLengthofanArray
Sometimesit’susefultoknowhowmanyelementsthereareinanarray.Forexample,ifyoukept
addingdinosaurstoyourdinosaursarray,youmightforgethowmanydinosaursyouhave.
Thelengthpropertyofanarraytellsyouhowmanyelementsthereareinthearray.Tofindthelength
ofanarray,justadd.lengthtotheendofitsname.Let’stryitout.Firstwe’llmakeanewarraywith
threeelements:
varmaniacs=["Yakko","Wakko","Dot"];
maniacs[0];
"Yakko"
maniacs[1];
"Wakko"
maniacs[2];
"Dot"
Tofindthelengthofthearray,add.lengthtomaniacs:
maniacs.length;
3
JavaScripttellsusthatthereare3elementsinthearray,andwealreadyknowtheyhavetheindex
positions0,1,and2.Thisgivesusausefulpieceofinformation:thelastindexinanarrayisalwaysthe
samenumberasthelengthofthearrayminus1.Thismeansthatthereisaneasywaytoaccessthelast
elementinanarray,howeverlongthatarrayis:
maniacs[maniacs.length-1];
"Dot"
Here,we’reaskingJavaScriptforanelementfromourarray.Butinsteadofenteringanindexnumberin
thesquarebrackets,weusealittlebitofmath:thelengthofthearrayminus1.JavaScriptfinds
maniacs.length,gets3,andthensubtracts1toget2.Thenitreturnstheelementfromindex2—the
lastmaniacinthearray,"Dot".
AddingElementstoanArray
Toaddanelementtotheendofanarray,youcanusethepushmethod.Add.pushtothearrayname,
followedbytheelementyouwanttoaddinsideparentheses,likethis:
varanimals=[];
animals.push("Cat");
1
animals.push("Dog");
2
animals.push("Llama");
3
animals;
["Cat","Dog","Llama"]
animals.length;
3
Herewecreateanemptyarraywithvaranimals=[];,andthenusethepushmethodtoadd"Cat"
tothearray.Then,weusepushagaintoaddon"Dog"andthen"Llama".Whenwedisplayanimals;,
weseethat"Cat","Dog",and"Llama"wereaddedtothearray,inthesameorderweenteredthem.
Theactofrunningamethodincomputer-speakisknownascallingthemethod.Whenyoucallthepush
method,twothingshappen.First,theelementinparenthesesisaddedtothearray.Second,thenew
lengthofthearrayisreturned.That’swhyyouseethosenumbersprintedouteverytimeyoucallpush.
Toaddanelementtothebeginningofanarray,youcanuse.unshift(element),likethis:
animals;
["Cat","Dog","Llama"]
➊animals[0];
"Cat"
animals.unshift("Monkey");
4
animals;
["Monkey","Cat","Dog","Llama"]
animals.unshift("PolarBear");
5
animals;
["PolarBear","Monkey","Cat","Dog","Llama"]
animals[0];
"PolarBear"
➋animals[2];
"Cat"
Herewestartedwiththearraythatwe’vebeenusing,["Cat","Dog","Llama"].Then,asweaddthe
elements"Monkey"and"PolarBear"tothebeginningofthearraywithunshift,theoldvaluesget
pushedalongbyoneindexeachtime.So"Cat",whichwasoriginallyatindex0➊,isnowatindex2
➋.
Again,unshiftreturnsthenewlengthofthearrayeachtimeitiscalled,justlikepush.
RemovingElementsfromanArray
Toremovethelastelementfromanarray,youcanpopitoffbyadding.pop()totheendofthearray
name.Thepopmethodcanbeparticularlyhandybecauseitdoestwothings:itremovesthelast
element,anditreturnsthatlastelementasavalue.Forexample,let’sstartwithouranimalsarray,
["PolarBear","Monkey","Cat","Dog","Llama"].Thenwe’llcreateanewvariablecalled
lastAnimalandsavethelastanimalintoitbycallinganimals.pop().
animals;
["PolarBear","Monkey","Cat","Dog","Llama"]
➊varlastAnimal=animals.pop();lastAnimal;
"Llama"
animals;
["PolarBear","Monkey","Cat","Dog"]
➋animals.pop();
"Dog"
animals;
["PolarBear","Monkey","Cat"]
➌animals.unshift(lastAnimal);
4
animals;
["Llama","PolarBear","Monkey","Cat"]
Whenwecallanimals.pop()at➊,thelastitemintheanimalsarray,"Llama",isreturnedandsaved
inthevariablelastAnimal."Llama"isalsoremovedfromthearray,whichleavesuswithfouranimals.
Whenwecallanimals.pop()againat➋,"Dog"isremovedfromthearrayandreturned,leavingonly
threeanimalsinthearray.
Whenweusedanimal.pop()on"Dog",wedidn’tsaveitintoavariable,sothatvalueisn’tsaved
anywhereanymore.The"Llama",ontheotherhand,wassavedtothevariablelastAnimal,sowecan
useitagainwheneverweneedit.At➌,weuseunshift(lastAnimal)toadd"Llama"backontothe
frontofthearray.Thisgivesusafinalarrayof["Llama","PolarBear","Monkey","Cat"].
Pushingandpoppingareausefulpairbecausesometimesyoucareaboutonlytheendofanarray.You
canpushanewitemontothearrayandthenpopitoffwhenyou’rereadytouseit.We’lllookatsome
waystousepushingandpoppinglaterinthischapter.
Toremoveandreturnthefirstelementofanarray,use.shift():
animals;
["Llama","PolarBear","Monkey","Cat"]
varfirstAnimal=animals.shift();
firstAnimal;
"Llama"
animals;
["PolarBear","Monkey","Cat"]
animals.shift()doesthesamethingasanimals.pop(),buttheelementcomesoffthebeginning
instead.Atthestartofthisexample,animalsis["Llama","PolarBear","Monkey","Cat"].
Whenwecall.shift()onthearray,thefirstelement,"Llama",isreturnedandsavedinfirstAnimal.
Because.shift()removesthefirstelementaswellasreturningit,attheendanimalsisjust["Polar
Bear","Monkey","Cat"].
Youcanuseunshiftandshifttoaddandremoveitemsfromthebeginningofanarrayjustasyou’d
usepushandpoptoaddandremoveitemsfromtheendofanarray.
AddingArrays
Toaddtwoarraystogethertomakeanew,singlearray,youcanuse
firstArray.concat(otherArray).Thetermconcatisshortforconcatenate,afancycomputer
sciencewordforjoiningtwovaluestogether.Theconcatmethodwillcombinebotharraysintoanew
array,withthevaluesfromfirstArrayaddedinfrontofthosefromotherArray.
Forexample,saywehavealistofsomefurryanimalsandanotherlistofsomescalyanimals,andwe
wanttocombinethem.IfweputallofourfurryanimalsinanarraycalledfurryAnimalsandallofour
scalyanimalsinanarraycalledscalyAnimals,enteringfurryAnimals.concat(scalyAnimals)will
createanewarraythathasthevaluesfromthefirstarrayatthebeginningandthevaluesfromthe
secondarrayattheend.
varfurryAnimals=["Alpaca","Ring-tailedLemur","Yeti"];
varscalyAnimals=["BoaConstrictor","Godzilla"];
varfurryAndScalyAnimals=furryAnimals.concat(scalyAnimals);
furryAndScalyAnimals;
["Alpaca","Ring-tailedLemur","Yeti","BoaConstrictor","Godzilla"]
furryAnimals;
["Alpaca","Ring-tailedLemur","Yeti"]
scalyAnimals;
["BoaConstrictor","Godzilla"]
EventhoughfirstArray.concat(otherArray)returnsanarraycontainingalltheelementsfrom
firstArrayandsecondArray,neitheroftheoriginalarraysischanged.Whenwelookat
furryAnimalsandscalyAnimals,they’rethesameaswhenwecreatedthem.
JoiningMultipleArrays
Youcanuseconcattojoinmorethantwoarraystogether.Justputtheextraarraysinsidethe
parentheses,separatedbycommas:
varfurryAnimals=["Alpaca","Ring-tailedLemur","Yeti"];
varscalyAnimals=["BoaConstrictor","Godzilla"];
varfeatheredAnimals=["Macaw","Dodo"];
varallAnimals=furryAnimals.concat(scalyAnimals,featheredAnimals);
allAnimals;
["Alpaca","Ring-tailedLemur","Yeti","BoaConstrictor","Godzilla",
"Macaw","Dodo"]
HerethevaluesfromfeatheredAnimalsgetaddedtotheveryendofthenewarray,sincetheyare
listedlastintheparenthesesaftertheconcatmethod.
concatisusefulwhenyouhavemultiplearraysthatyouwanttocombineintoone.Forexample,say
youhavealistofyourfavoritebooks,andyourfriendalsohasalistoffavoritebooks,andyouwantto
goseeifthebooksareavailabletobuyallatonceatthebookstore.Itwouldbeeasierifyouhadonly
onelistofbooks.Allyou’dhavetodoisconcatyourlistwithyourfriend’s,andvoilà!Onelistof
books.
FindingtheIndexofanElementinanArray
Tofindtheindexofanelementinanarray,use.indexOf(element).Herewedefinethearraycolors
andthenaskfortheindexpositionsof"blue"and"green"withcolors.indexOf("blue")and
colors.indexOf("green").Becausetheindexof"blue"inthearrayis2,colors.indexOf("blue")
returns2.Theindexof"green"inthearrayis1,socolors.indexOf("green")returns1.
varcolors=["red","green","blue"];
colors.indexOf("blue");
2
colors.indexOf("green");
1
indexOfislikethereverseofusingsquarebracketstogetavalueataparticularindex;colors[2]is
"blue",socolors.indexOf("blue")is2:
colors[2];
"blue"
colors.indexOf("blue");
2
Eventhough"blue"appearsthirdinthearray,itsindexpositionis2becausewealwaysstartcounting
from0.Andthesamegoesfor"green",ofcourse,atindex1.
Iftheelementwhosepositionyouaskforisnotinthearray,JavaScriptreturns-1.
colors.indexOf("purple");
-1
ThisisJavaScript’swayofsaying“Thatdoesn’texisthere,”whilestillreturninganumber.
Iftheelementappearsmorethanonceinthearray,theindexOfmethodwillreturnthefirstindexofthat
elementinthearray.
varinsects=["Bee","Ant","Bee","Bee","Ant"];
insects.indexOf("Bee");
0
TurninganArrayintoaString
Youcanuse.join()tojoinalltheelementsinanarraytogetherintoonebigstring.
varboringAnimals=["Monkey","Cat","Fish","Lizard"];
boringAnimals.join();
"Monkey,Cat,Fish,Lizard"
Whenyoucallthejoinmethodonanarray,itreturnsastringcontainingalltheelements,separatedby
commas.Butwhatifyoudon’twanttousecommasastheseparator?
Youcanuse.join(separator)todothesamething,butwithyourownchosenseparatorbetween
eachvalue.Theseparatoriswhateverstringyouputinsidetheparentheses.Forexample,wecanuse
threedifferentseparators:ahyphenwithspacesoneitherside,anasterisk,andthewordseeswith
spacesoneitherside.Noticethatyouneedquotemarksaroundtheseparator,becausetheseparatorisa
string.
varboringAnimals=["Monkey","Cat","Fish","Lizard"];
boringAnimals.join("-");
"Monkey-Cat-Fish-Lizard"
boringAnimals.join("*")
"Monkey*Cat*Fish*Lizard"
boringAnimals.join("sees")
"MonkeyseesCatseesFishseesLizard"
Thisisusefulifyouhaveanarraythatyouwanttoturnintoastring.Sayyouhavelotsofmiddlenames
andyou’vegotthemstoredinanarray,alongwithyourfirstandlastname.Youmightbeaskedtogive
yourfullnameasastring.Usingjoin,withasinglespaceastheseparator,willjoinallyournames
togetherintoasinglestring:
varmyNames=["Nicholas","Andrew","Maxwell","Morgan"];
myNames.join("");
"NicholasAndrewMaxwellMorgan"
Ifyoudidn’thavejoin,you’dhavetodosomethinglikethis,whichwouldbereallyannoyingtotype
out:
myNames[0]+""+myNames[1]+""+myNames[2]+""+myNames[3];
"NicholasAndrewMaxwellMorgan"
Also,thiscodewouldworkonlyifyouhadexactlytwomiddlenames.Ifyouhadoneorthreemiddle
names,you’dhavetochangethecode.Withjoin,youdon’thavetochangeanything—itprintsouta
stringwithalloftheelementsofthearray,nomatterhowlongthearrayis.
Ifthevaluesinthearrayaren’tstrings,JavaScriptwillconvertthemtostringsbeforejoiningthem
together:
varages=[11,14,79];
ages.join("");
"111479"
UsefulThingstoDowithArrays
Nowyouknowlotsofdifferentwaystocreatearraysandplayaroundwiththem.Butwhatcanyou
actuallydowithallthesepropertiesandmethods?Inthissection,we’llwriteafewshortprogramsthat
showoffsomeusefulthingstodowitharrays.
FindingYourWayHome
Picturethis:yourfriendhascomeovertoyourhouse.Nowshewantstoshowyouherhouse.Theonly
problemisthatyou’veneverbeentoherhousebefore,andlateryou’llhavetofindyourwayback
homeonyourown.
Luckily,youhaveacleverideatohelpyouwithyourproblem:onthewaytoyourfriend’shouse,you’ll
keepalistofallthelandmarksyousee.Onthewayback,you’llgothroughthelistinreverseandcheck
itemsofftheendofthelisteverytimeyoupassalandmarksoyouknowwheretogonext.
BuildingtheArraywithPush
Let’swritesomecodethatwoulddoexactlythat.Westartoffbycreatinganemptyarray.Thearray
startsoffemptybecauseyoudon’tknowwhatlandmarksyou’llseeuntilyouactuallystartwalkingto
yourfriend’shouse.Then,foreachlandmarkonthewaytoyourfriend’shouse,we’llpushadescription
ofthatlandmarkontotheendofthearray.Then,whenit’stimetogohome,we’llpopeachlandmark
offthearray.
varlandmarks=[];
landmarks.push("Myhouse");
landmarks.push("Frontpath");
landmarks.push("Flickeringstreetlamp");
landmarks.push("Leakyfirehydrant");
landmarks.push("Firestation");
landmarks.push("Catrescuecenter");
landmarks.push("Myoldschool");
landmarks.push("Myfriend'shouse");
Herewecreateanemptyarraynamedlandmarksandthenusepushtostoreallthelandmarksyoupass
onthewaytoyourfriend’shouse.
GoinginReversewithpop
Onceyouarriveatyourfriend’shouse,youcaninspectyourarrayoflandmarks.Sureenough,thefirst
itemis"Myhouse",followedby"Frontpath",andsoonthroughtheendofthearray,withthefinal
item"Myfriend'shouse".Whenit’stimetogohome,allyouneedtodoispopofftheitemsoneby
one,andyou’llknowwheretogonext.
landmarks.pop();
"Myfriend'shouse"
landmarks.pop();
"Myoldschool"
landmarks.pop();
"Catrescuecenter"
landmarks.pop();
"Firestation"
landmarks.pop();
"Leakyfirehydrant"
landmarks.pop();
"Flickeringstreetlamp"
landmarks.pop();
"Frontpath"
landmarks.pop();
"Myhouse"
Phew,youmadeithome!
Didyounoticehowthefirstlandmarkyouputinthearraywasalsothelastoneyougotoutofit?And
thelastlandmarkyouputinthearraywasthefirstonethatcameout?Youmighthavethoughtthat
you’dalwayswantthefirstitemyouputintobethefirstitemyougetout,butyoucanseethatit’s
sometimeshelpfultogobackthroughanarrayinreverse.
It’sactuallyverycommontouseaprocesslikethisinlargerprograms,whichiswhyJavaScriptmakes
pushingandpoppingsoeasy.
NOTE
Thistechniqueisknownasastackincomputer-speak.Thinkofitlikeastackofpancakes.Everytimeyoucookanewpancake,itgoes
ontop(likepush),andeverytimeyoueatone,itcomesoffthetop(likepop).Poppingastackislikegoingbackintime:thelastitem
youpopisthefirstoneyoupushed.It’sthesamewithpancakes:thelastpancakeyoueatisthefirstonethatwascooked.In
programmingjargon,thisisalsocalledLastIn,FirstOut(LIFO).ThealternativetoLIFOisFirstIn,FirstOut(FIFO).Thisisalso
knownasaqueue,becauseitactslikeaqueue(orline)ofpeople.Thefirstpersontojointhequeueisthefirstpersontobeserved.
DecisionMaker
WecanusearraysinJavaScripttobuildaprogramtomakedecisionsforus(likeaMagic8-Ball).First,
though,weneedtofindouthowtogetrandomnumbers.
UsingMath.random()
WecanproducerandomnumbersusingaspecialmethodcalledMath.random(),whichreturnsa
randomnumberbetween0and1eachtimeit’scalled.Here’sanexample:
Math.random();
0.8945409457664937
Math.random();
0.3697543195448816
Math.random();
0.48314980138093233
It’simportanttonotethatMath.random()alwaysreturnsanumberlessthan1andwillneverreturn1
itself.
Ifyouwantabiggernumber,justmultiplytheresultofcallingMath.random().Forexample,ifyou
wantednumbersbetween0and10,youwouldmultiplyMath.random()by10:
Math.random()*10;
7.648027329705656
Math.random()*10;
9.7565904534421861
Math.random()*10;
0.21483442978933454
RoundingDownwithMath.floor()
Wecan’tusethesenumbersasarrayindexes,though,becauseindexeshavetobewholenumberswith
nothingafterthedecimalpoint.Tofixthat,weneedanothermethodcalledMath.floor().Thistakesa
numberandroundsitdowntothewholenumberbelowit(basicallygettingridofeverythingafterthe
decimalpoint).
Math.floor(3.7463463);
3
Math.floor(9.9999);
9
Math.floor(0.793423451963426);
0
Wecancombinethesetwotechniquestocreatearandomindex.Allweneedtodoismultiply
Math.random()bythelengthofthearrayandthencallMath.floor()onthatvalue.Forexample,if
thelengthofthearraywere4,wewoulddothis:
Math.floor(Math.random()*4);
2//couldbe0,1,2,or3
Everytimeyoucallthecodeabove,itreturnsarandomnumberfrom0to3(including0and3).
BecauseMath.random()alwaysreturnsavaluelessthan1,Math.random()*4willneverreturn4or
anythinghigherthan4.
Now,ifweusethatrandomnumberasanindex,wecanselectarandomelementfromanarray:
varrandomWords=["Explosion","Cave","Princess","Pen"];
varrandomIndex=Math.floor(Math.random()*4);
randomWords[randomIndex];
"Cave"
HereweuseMath.floor(Math.random()*4);topickarandomnumberfrom0to3.Oncethat
randomnumberissavedtothevariablerandomIndex,weuseitasanindextoaskforastringfromthe
arrayrandomWords.
Infact,wecouldshortenthisbydoingawaywiththerandomIndexvariablealtogetherandjustsay:
randomWords[Math.floor(Math.random()*4)];
"Princess"
TheCompleteDecisionMaker
Nowlet’screateourarrayofphrases,andwecanusethiscodetopickarandomone.Thisisour
decisionmaker!I’musingcommentsheretoshowsomequestionsyoumightwanttoaskyour
computer.
varphrases=[
"Thatsoundsgood",
"Yes,youshoulddefinitelydothat",
"I'mnotsurethat'sagreatidea",
"Maybenottoday?",
"Computersaysno."
];
//ShouldIhaveanothermilkshake?
phrases[Math.floor(Math.random()*5)];
"I'mnotsurethat'sagreatidea"
//ShouldIdomyhomework?
phrases[Math.floor(Math.random()*5)];
"Maybenottoday?"
Herewecreatedanarraycalledphrasesthatstoresdifferentpiecesofadvice.Now,everytimewehave
aquestion,wecanaskforarandomvaluefromthephrasesarray,anditwillhelpusmakeadecision!
Noticethatbecauseourarrayofdecisionshasfiveitems,wemultiplyMath.random()by5.Thiswill
alwaysreturnoneoffiveindexpositions:0,1,2,3,or4.
CreatingaRandomInsultGenerator
Wecanextendthedecisionmakerexampletocreateaprogramthatgeneratesarandominsultevery
timeyourunit!
varrandomBodyParts=["Face","Nose","Hair"];
varrandomAdjectives=["Smelly","Boring","Stupid"];
varrandomWords=["Fly","Marmot","Stick","Monkey","Rat"];
//PickarandombodypartfromtherandomBodyPartsarray:
➊varrandomBodyPart=randomBodyParts[Math.floor(Math.random()*3)];
//PickarandomadjectivefromtherandomAdjectivesarray:
➋varrandomAdjective=randomAdjectives[Math.floor(Math.random()*3)];
//PickarandomwordfromtherandomWordsarray:
➌varrandomWord=randomWords[Math.floor(Math.random()*5)];
//Joinalltherandomstringsintoasentence:
varrandomInsult="Your"+randomBodyPart+"islikea"+
randomAdjective+""+randomWord+"!!!";
randomInsult;
"YourNoseislikeaStupidMarmot!!!"
Herewehavethreearrays,andinlines➊,➋,and➌,weusethreeindexestopullarandomwordfrom
eacharray.Then,wecombinethemallinthevariablerandomInsulttocreateacompleteinsult.At➊
and➋we’remultiplyingby3becauserandomAdjectivesandrandomBodyPartsbothcontainthree
elements.Likewise,we’remultiplyingby5at➌becauserandomWordsisfiveelementslong.Notice
thatweaddastringwithasinglespacebetweenrandomAdjectiveandrandomWord.Tryrunningthis
codeafewtimes—youshouldgetadifferentrandominsulteachtime!
TRYITOUT!
Ifyouwantedtobereallyclever,youcouldreplaceline➌withthis:
varrandomWord=randomWords[Math.floor(Math.random()*
randomWords.length)];
WeknowthatwealwaysneedtomultiplyMath.random()bythelengthofthearray,sousingrandomWords.lengthmeanswedon’thave
tochangeourcodeifthelengthofthearraychanges.
Here’sanotherwaytobuildupourrandominsult:
varrandomInsult=["Your",randomBodyPart,"is","like","a",
randomAdjective,randomWord+"!!!"].join("");
"YourHairislikeaSmellyFly!!!"
Inthisexample,eachwordofthesentenceisaseparatestringinanarray,whichwejoinwiththespace
character.There’sonlyoneplacewherewedon’twantaspace,whichisinbetweenrandomWordand
"!!!".Inthiscase,weusethe+operatortojointhosetwostringswithoutthespace.
WhatYouLearned
Asyou’veseen,JavaScriptarraysareawaytostorealistofvalues.Nowyouknowhowtocreateand
workwitharrays,andyouhavemanywaysofaccessingtheirelements.
ArraysareoneofthewaysJavaScriptgivesyoutobringmultiplevaluestogetherintooneplace.Inthe
nextchapter,we’lllookatobjects,whichareanotherwayofstoringmultiplevaluesasasingleunit.
Objectsusestringkeystoaccesstheelements,ratherthannumberindexes.
ProgrammingChallenges
Tryoutthesechallengestopracticetheskillsyoulearnedinthischapter.
#1:NEWINSULTS
Makeyourownrandominsultgeneratorwithyourownsetofwords.
#2:MORESOPHISTICATEDINSULTS
Extendtherandominsultgeneratorsoitgeneratesinsultslike“Your[bodypart]ismore[adjective]than
a[animal]’s[animalbodypart].”(Hint:You’llneedtocreateanotherarray.)
#3:USE+ORJOIN?
Maketwoversionsofyourrandominsultgenerator:onethatusesthe+operatortocreatethestring,and
onethatcreatesanarrayandjoinsitwith"".Whichdoyouprefer,andwhy?
#4:JOININGNUMBERS
Howcouldyouturnthearray[3,2,1]intothestring"3isbiggerthan2isbiggerthan1"
usingthejoinmethod?
Chapter4.Objects
ObjectsinJavaScriptareverysimilartoarrays,butobjectsusestringsinsteadofnumberstoaccessthe
differentelements.Thestringsarecalledkeysorproperties,andtheelementstheypointtoarecalled
values.Togetherthesepiecesofinformationarecalledkey-valuepairs.Whilearraysaremostlyusedto
representlistsofmultiplethings,objectsareoftenusedtorepresentsinglethingswithmultiple
characteristics,orattributes.Forexample,inChapter3wemadeseveralarraysthatlisteddifferent
animalnames.Butwhatifwewantedtostoredifferentpiecesofinformationaboutoneanimal?
CreatingObjects
WecouldstorelotsofinformationaboutasingleanimalbycreatingaJavaScriptobject.Here’san
objectthatstoresinformationaboutathree-leggedcatnamedHarmony.
varcat={
"legs":3,
"name":"Harmony",
"color":"Tortoiseshell"
};
Herewecreateavariablecalledcatandassignanobjecttoitwiththreekey-valuepairs.Tocreatean
object,weusecurlybrackets,{},insteadofthestraightbracketsweusedtomakearrays.Inbetween
thecurlybrackets,weenterkey-valuepairs.Thecurlybracketsandeverythinginbetweenthemare
calledanobjectliteral.Anobjectliteralisawayofcreatinganobjectbywritingouttheentireobjectat
once.
NOTE
We’vealsoseenarrayliterals(forexample,["a","b","c"]),numberliterals(forexample,37),stringliterals(forexample,"moose"),
andBooleanliterals(trueandfalse).Literaljustmeansthatthewholevalueiswrittenoutatonce,notbuiltupinmultiplesteps.
Forexample,ifyouwantedtomakeanarraywiththenumbers1through3init,youcouldusethearrayliteral[1,2,3].Oryou
couldcreateanemptyarrayandthenusethepushmethodtoadd1,2,and3tothearray.Youdon’talwaysknowatfirstwhat’sgoingto
beinyourarrayorobject,whichiswhyyoucan’talwaysuseliteralstobuildarraysandobjects.
Figure4-1showsthebasicsyntaxforcreatinganobject.
Figure4-1.Thegeneralsyntaxforcreatinganobject
Whenyoucreateanobject,thekeygoesbeforethecolon(:),andthevaluegoesafter.Thecolonactsa
bitlikeanequalsign—thevaluesontherightgetassignedtothenamesontheleft,justlikewhenyou
createvariables.Inbetweeneachkey-valuepair,youhavetoputacomma.Inourexample,thecommas
areattheendsofthelines—butnoticethatyoudon’tneedacommaafterthelastkey-valuepair
(color:"Tortoiseshell").Becauseit’sthelastkey-valuepair,theclosingcurlybracketcomesnext,
insteadofacomma.
KeysWithoutQuotes
Inourfirstobject,weputeachkeyinquotationmarks,butyoudon’tnecessarilyneedquotesaroundthe
keys—thisisavalidcatobjectliteralaswell:
varcat={
legs:3,
name:"Harmony",
color:"Tortoiseshell"
};
JavaScriptknowsthatthekeyswillalwaysbestrings,whichiswhyyoucanleaveoutthequotes.Ifyou
don’tputquotesaroundthekeys,theunquotedkeyshavetofollowthesamerulesasvariablenames:
spacesaren’tallowedinanunquotedkey,forexample.Ifyouputthekeyinquotes,thenspacesare
allowed:
varcat={
legs:3,
"fullname":"HarmonyPhilomenaSnuggly-PantsMorgan",
color:"Tortoiseshell"
};
Notethat,whileakeyisalwaysastring(withorwithoutquotes),thevalueforthatkeycanbeanykind
ofvalue,orevenavariablecontainingavalue.
Youcanalsoputthewholeobjectononeline,butitcanbehardertoreadlikethat:
varcat={legs:3,name:"Harmony",color:"Tortoiseshell"};
AccessingValuesinObjects
Youcanaccessvaluesinobjectsusingsquarebrackets,justlikewitharrays.Theonlydifferenceisthat
insteadoftheindex(anumber),youusethekey(astring).
cat["name"];
"Harmony"
Justasthequotesaroundkeysareoptionalwhenyoucreateanobjectliteral,thequotesarealsooptional
whenyouareaccessingkeysinobjects.Ifyou’renotgoingtousequotes,however,thecodelooksabit
different:
cat.name;
"Harmony"
Thisstyleiscalleddotnotation.Insteadoftypingthekeynameinquotesinsidesquarebracketsafter
theobjectname,wejustuseaperiod,followedbythekey,withoutanyquotes.Aswithunquotedkeys
inobjectliterals,thiswillworkonlyifthekeydoesn’tcontainanyspecialcharacters,suchasspaces.
Insteadoflookingupavaluebytypingitskey,sayyouwantedtogetalistofallthekeysinanobject.
JavaScriptgivesyouaneasywaytodothat,usingObject.keys():
vardog={name:"Pancake",age:6,color:"white",bark:"Yipyap
yip!"};
varcat={name:"Harmony",age:8,color:"tortoiseshell"};
Object.keys(dog);
["name","age","color","bark"]
Object.keys(cat);
["name","age","color"]
Object.keys(anyObject)returnsanarraycontainingallthekeysofanyObject.
AddingValuestoObjects
Anemptyobjectisjustlikeanemptyarray,butitusescurlybrackets,{},insteadofsquarebrackets:
varobject={};
Youcanadditemstoanobjectjustasyou’dadditemstoanarray,butyouusestringsinsteadof
numbers:
varcat={};
cat["legs"]=3;
cat["name"]="Harmony";
cat["color"]="Tortoiseshell";
cat;
{color:"Tortoiseshell",legs:3,name:"Harmony"}
Here,westartedwithanemptyobjectnamedcat.Thenweaddedthreekey-valuepairs,onebyone.
Then,wetypecat;,andthebrowsershowsthecontentsoftheobject.Differentbrowsersmayoutput
objectsdifferently,though.Forexample,Chrome(atthetimeI’mwritingthis)outputsthecatobject
likethis:
Object{Legs:3,name:"Harmony",Color:"TortoisesheLL"}
WhileChromeprintsoutthekeysinthatorder(legs,name,color),otherbrowsersmayprintthemout
differently.ThisisbecauseJavaScriptdoesn’tstoreobjectswiththeirkeysinanyparticularorder.
Arraysobviouslyhaveacertainorder:index0isbeforeindex1,andindex3isafterindex2.Butwith
objects,there’snoobviouswaytoordereachitem.Shouldcolorgobeforelegsorafter?There’sno
“correct”answertothisquestion,soobjectssimplystorekeyswithoutassigningthemanyparticular
order,andasaresultdifferentbrowserswillprintthekeysindifferentorders.Forthisreason,you
shouldneverwriteaprogramthatreliesonobjectkeysbeinginapreciseorder.
AddingKeyswithDotNotation
Youcanalsousedotnotationwhenaddingnewkeys.Let’strythepreviousexample,wherewestarted
withanemptyobjectandaddedkeystoit,butthistimewe’llusedotnotation:
varcat={};
cat.legs=3;
cat.name="Harmony";
cat.color="Tortoiseshell";
IfyouaskforapropertythatJavaScriptdoesn’tknowabout,itreturnsthespecialvalueundefined.
undefinedjustmeans“There’snothinghere!”Forexample:
vardog={
name:"Pancake",
legs:4,
isAwesome:true
};
dog.isBrown;
undefined
Herewedefinethreepropertiesfordog:name,legs,andisAwesome.Wedidn’tdefineisBrown,so
dog.isBrownreturnsundefined.
CombiningArraysandObjects
Sofar,we’velookedonlyatarraysandobjectsthatcontainsimpletypeslikenumbersandstrings.But
there’snothingstoppingyoufromusinganotherarrayorobjectasavalueinanarrayorobject.
Forexample,anarrayofdinosaurobjectsmightlooklikethis:
vardinosaurs=[
{name:"TyrannosaurusRex",period:"LateCretaceous"},
{name:"Stegosaurus",period:"LateJurassic"},
{name:"Plateosaurus",period:"Triassic"}
];
Togetalltheinformationaboutthefirstdinosaur,youcanusethesametechniqueweusedbefore,
enteringtheindexinsquarebrackets:
dinosaurs[0];
{name:"TyrannosaurusRex",period:"LateCretaceous"}
Ifyouwanttogetonlythenameofthefirstdinosaur,youcanjustaddtheobjectkeyinsquarebrackets
afterthearrayindex:
dinosaurs[0]["name"];
"TyrannosaurusRex"
Or,youcanusedotnotation,likethis:
dinosaurs[1].period;
"LateJurassic"
NOTE
Youcanusedotnotationonlywithobjects,notwitharrays.
AnArrayofFriends
Let’slookatamorecomplexexamplenow.We’llcreateanarrayoffriendobjects,whereeachobject
alsocontainsanarray.First,we’llmaketheobjects,andthenwecanputthemallintoanarray.
varanna={name:"Anna",age:11,luckyNumbers:[2,4,8,16]};
vardave={name:"Dave",age:5,luckyNumbers:[3,9,40]};
varkate={name:"Kate",age:9,luckyNumbers:[1,2,3]};
First,wemakethreeobjectsandsavethemintovariablescalledanna,dave,andkate.Eachobjecthas
threekeys:name,age,andluckyNumbers.Eachnamekeyhasastringvalueassignedtoit,eachagekey
hasasinglenumbervalueassignedtoit,andeachluckyNumberskeyhasanarrayassignedtoit,
containingafewdifferentnumbers.
Nextwe’llmakeanarrayofourfriends:
varfriends=[anna,dave,kate];
Nowwehaveanarraysavedtothevariablefriendswiththreeelements:anna,dave,andkate(which
eachrefertoobjects).Youcanretrieveoneoftheseobjectsusingitsindexinthearray:
friends[1];
{name:"Dave",age:5,luckyNumbers:Array[3]}
Thisretrievesthesecondobjectinthearray,dave(atindex1).ChromeprintsoutArray[3]forthe
luckyNumbersarray,whichisjustitswayofsaying,“Thisisathree-elementarray.”(Youcanuse
Chrometoseewhat’sinthatarray;seeExploringObjectsintheConsole.)Wecanalsoretrieveavalue
withinanobjectbyenteringtheindexoftheobjectinsquarebracketsfollowedbythekeywewant:
friends[2].name
"Kate"
Thiscodeasksfortheelementatindex2,whichisthevariablenamedkate,andthenasksforthe
propertyinthatobjectunderthekey"name",whichis"Kate".Wecouldevenretrieveavaluefroman
arraythat’sinsideoneoftheobjectsinsidethefriendsarray,likeso:
friends[0].luckyNumbers[1];
4
Figure4-2showseachindex.friends[0]istheelementatindex0inthefriendsarray,whichisthe
objectanna.friends[0].luckyNumbersisthearray[2,4,8,16]fromtheobjectcalledanna.
Finally,friends[0].luckyNumbers[1]isindex1inthatarray,whichisthenumbervalue4.
Figure4-2.Accessingnestedvalues
ExploringObjectsintheConsole
Chromewillletyoudigintoobjectsthatyouprintoutintheconsole.Forexample,ifyoutype...
friends[1];
ChromewilldisplaytheoutputshowninFigure4-3.
Figure4-3.HowanobjectisdisplayedintheChromeinterpreter
Thetriangleontheleftmeansthatthisobjectcanbeexpanded.Clicktheobjecttoexpandit,andyou’ll
seewhat’sshowninFigure4-4.
Figure4-4.Expandingtheobject
YoucanexpandluckyNumbers,too,byclickingit(seeFigure4-5).
Figure4-5.Expandinganarraywithintheobject
Don’tworryaboutthose__proto__properties—theyhavetodowiththeobject’sprototype.We’ll
lookatprototypeslater,inChapter12.Also,you’llnoticethattheinterpretershowsthevalueofthe
array’slengthproperty.
Youcanalsoviewtheentirefriendsarrayandexpandeachelementinthearray,asshowninFigure46.
Figure4-6.Allthreeobjectsfromthefriendsarray,asshownintheChromeinterpreter
UsefulThingstoDowithObjects
Nowthatyouknowafewdifferentwaystocreateobjectsandaddpropertiestothem,let’sputwhat
we’velearnedtousebytryingoutsomesimpleprograms.
KeepingTrackofOwedMoney
Let’ssayyou’vedecidedtostartabank.Youlendyourfriendsmoney,andyouwanttohaveawayto
keeptrackofhowmuchmoneyeachofthemowesyou.
Youcanuseanobjectasawayoflinkingastringandavaluetogether.Inthiscase,thestringwouldbe
yourfriend’sname,andthevaluewouldbetheamountofmoneyheorsheowesyou.Let’shavealook.
➊varowedMoney={};
➋owedMoney["Jimmy"]=5;
➌owedMoney["Anna"]=7;
➍owedMoney["Jimmy"];
5
➎owedMoney["Jinen"];
undefined
At➊,wecreateanewemptyobjectcalledowedMoney.At➋,weassignthevalue5tothekey"Jimmy".
Wedothesamethingat➌,assigningthevalue7tothekey"Anna".At➍,weaskforthevalue
associatedwiththekey"Jimmy",whichis5.Thenat➎,weaskforthevalueassociatedwiththekey
"Jinen",whichisundefinedbecausewedidn’tsetit.
Nowlet’simaginethatJimmyborrowssomemoremoney(say,$3).Wecanupdateourobjectandadd3
totheamountJimmyoweswiththeplus-equalsoperator(+=)thatyousawinChapter2.
owedMoney["Jimmy"]+=3;
owedMoney["Jimmy"];
8
ThisislikesayingowedMoney["Jimmy"]=owedMoney["Jimmy"]+3.Wecanalsolookattheentire
objecttoseehowmuchmoneyeachfriendowesus:
owedMoney;
{Jimmy:8,Anna:7}
StoringInformationAboutYourMovies
Let’ssayyouhavealargecollectionofmoviesonDVDandBlu-ray.Wouldn’titbegreattohavethe
informationaboutthosemoviesonyourcomputersoyoucanfindoutabouteachmovieeasily?
Youcancreateanobjecttostoreinformationaboutyourmovies,whereeverykeyisamovietitle,and
everyvalueisanotherobjectcontaininginformationaboutthemovie.Valuesinobjectscanbeobjects
themselves!
varmovies={
"FindingNemo":{
releaseDate:2003,
duration:100,
actors:["AlbertBrooks","EllenDeGeneres","AlexanderGould"],
format:"DVD"
},
"StarWars:EpisodeVI-ReturnoftheJedi":{
releaseDate:1983,
duration:134,
actors:["MarkHamill","HarrisonFord","CarrieFisher"],
format:"DVD"
},
"HarryPotterandtheGobletofFire":{
releaseDate:2005,
duration:157,
actors:["DanielRadcliffe","EmmaWatson","RupertGrint"],
format:"Blu-ray"
}
};
YoumighthavenoticedthatIusedquotesforthemovietitles(thekeysintheouterobject)butnotfor
thekeysintheinnerobjects.That’sbecausethemovietitlesneedtohavespaces—otherwise,I’dhave
totypeeachtitlelikeStarWarsEpisodeVIReturnOfTheJedi,andthat’sjustsilly!Ididn’tneedquotes
forthekeysintheinnerobjects,soIleftthemoff.Itcanmakecodelookabitcleanerwhentherearen’t
unnecessarypunctuationmarksinit.
Now,whenyouwantinformationaboutamovie,it’seasytofind:
varfindingNemo=movies["FindingNemo"];
findingNemo.duration;
100
findingNemo.format;
"DVD"
HerewesavethemovieinformationaboutFindingNemointoavariablecalledfindingNemo.Wecan
thenlookatthepropertiesofthisobject(likedurationandformat)tofindoutaboutthemovie.
Youcanalsoeasilyaddnewmoviestoyourcollection:
varcars={
releaseDate:2006,
duration:117,
actors:["OwenWilson","BonnieHunt","PaulNewman"],
format:"Blu-ray"
};
movies["Cars"]=cars;
HerewecreateanewobjectofmovieinformationaboutCars.Wetheninsertthisintothemovies
object,underthekey"Cars".
Nowthatyou’rebuildingupyourcollection,youmightwanttofindaneasywaytolistthenamesofall
yourmovies.That’swhereObject.keyscomesin:
Object.keys(movies);
["FindingNemo","StarWars:EpisodeVI-ReturnoftheJedi","Harry
PotterandtheGobletofFire","Cars"]
WhatYouLearned
Nowyou’veseenhowobjectsworkinJavaScript.They’realotlikearrays,becauseyoucanusethem
toholdlotsofpiecesofinformationtogetherinoneunit.Onemajordifferenceisthatyouusestringsto
accesselementsinanobjectandyouusenumberstoaccesselementsinanarray.Forthisreason,arrays
areordered,whileobjectsarenot.
We’llbedoingalotmorewithobjectsinlaterchapters,oncewe’velearnedaboutmoreofJavaScript’s
features.Inthenextchapter,we’lllookatconditionalsandloops,whicharebothwaysofadding
structuretoourprogramstomakethemmorepowerful.
ProgrammingChallenges
Tryoutthesechallengestopracticeworkingwithobjects.
#1:SCOREKEEPER
Imagineyou’replayingagamewithsomefriendsandyouwanttokeeptrackofthescore.Createan
objectcalledscores.Thekeyswillbethenamesofyourfriends,andthevalueswillbethescores
(whichwillallstartat0).Astheplayersearnpoints,youmustincreasetheirscores.Howwouldyou
increaseaplayer’sscoreinthescoresobject?
#2:DIGGINGINTOOBJECTSANDARRAYS
Sayyouhadthefollowingobject:
varmyCrazyObject={
"name":"Aridiculousobject",
"somearray":[7,9,{purpose:"confusion",number:123},3.3],
"randomanimal":"BananaShark"
};
Howwouldyougetthenumber123outofthisobjectusingonelineofJavaScript?Tryitoutinthe
consoletoseeifyou’reright.
Chapter5.TheBasicsofHTML
Thebrowser-basedJavaScriptconsolethatwe’vebeenusingsofarisgreatfortryingoutsmallsnippets
ofcode,butinordertocreateactualprograms,we’llneedsomethingabitmoreflexible,likeaweb
pagewithsomeJavaScriptinit.Inthischapter,we’lllearnhowtocreateabasicHTMLwebpage.
HTML(HyperTextMarkupLanguage)isthelanguageusedtomakewebpages.ThewordHyperText
referstotextthatisconnectedbyhyperlinks,thelinksonawebpage.Amarkuplanguageisusedto
annotatedocumentssothatthey’renotjustplaintext.Themarkuptellssoftware(likeawebbrowser)
howtodisplaythetextandwhattodowithit.
Inthischapter,I’llshowyouhowtowriteHTMLdocumentsinatexteditor,asimpleprogramdesigned
forwritingplaintextfileswithouttheformattingyoufindinwordprocessorslikeMicrosoftWord.
Word-processeddocumentscontainformattedtext(withdifferentfonts,typecolors,fontsizes,etc.),
andwordprocessorsaredesignedtomakeiteasytochangetheformattingofthetext.Wordprocessors
usuallyallowyoutoinsertimagesandgraphicsaswell.
Plaintextfilescontainjusttext,withoutanyinformationaboutthefont,color,size,andsoon.Youcan’t
putanimageinatextfileunlessyoumakeitoutoftext—likethiscat,forexample.
/\_/\
=(°w°)=
)(//
(____)//
TextEditors
We’llwriteourHTMLinthecross-platform(compatiblewithWindows,MacOS,andLinux)Sublime
Texteditor.YoucandownloadanduseSublimeTextforfree,butafterawhileyou’llbeaskedtopay
foralicense.Ifyoudon’tlikethatidea,I’velistedsomecompletelyfreealternativesbelow.My
instructionsinthischapteraregearedtowardSublimeText,butsincetexteditorsarerelativelysimple,
theinstructionsshouldworkprettymuchthesameforanyeditor.
Geditisacross-platformtexteditorfromtheGNOMEproject
(https://wiki.gnome.org/Apps/Gedit/).
ForMicrosoftWindows,Notepad++(http://notepad-plus-plus.org/)isanothergoodalternative.
OnMacOS,TextWrangler(http://www.barebones.com/products/textwrangler/)isagoodoption.
ToinstallSublimeText,visithttp://www.sublimetext.com/.Installationinstructionsdifferforeach
operatingsystem,butyoushouldfindthemprettyclear.Ifyourunintoanyproblems,trytheSupport
sectionattheSublimeTexthomepage.
SYNTAXHIGHLIGHTING
SublimeTextwillcolor-codeyourprogramswithsyntaxhighlighting.Thisisdesignedtomakeprogramseasierforprogrammersto
readbyassigningdifferentcolorstodifferenttypesofcode.Forexample,stringsmightbegreen,whilekeywordslikevarmightbe
orange.
SublimeTexthaslotsofcolorschemestochoosefrom.Inthisbook,we’reusingtheIDLEcolorscheme,whichyoucanmatchonyour
screenbygoingtoPreferences▸ColorSchemeandselectingIDLE.
OurFirstHTMLDocument
Onceyou’veinstalledSublimeText,starttheprogramandcreateanewfilewithFile▸NewFile.Next,
chooseFile▸Savetosaveyournew,blankfile;nameitpage.htmlandsaveittoyourdesktop.
Nowit’stimetowritesomeHTML.Enterthefollowingtextintoyourpage.htmlfile:
<h1>Helloworld!</h1>
<p>Myfirstwebpage.</p>
Saveyourupdatedversionofpage.htmlwithFile▸Save.Nowlet’sseewhatthatpagewouldlooklike
inawebbrowser.OpenChrome,chooseFile▸OpenFile,andselectpage.htmlfromyourdesktop.You
shouldseesomethinglikeFigure5-1.
Figure5-1.YourfirstHTMLpageinChrome
You’vejustcreatedyourfirstHTMLdocument!Althoughyou’reviewingitinyourwebbrowser,it’s
notactuallyontheInternet.Chromeisopeningyourpagelocallyandjustreadingyourmarkuptagsto
figureoutwhattodowithitstext.
TagsandElements
HTMLdocumentsaremadeupofelements.Anelementstartswithastarttagandendswithanendtag.
Forexample,inourdocumentsofarwehavetwoelements:h1andp.Theh1elementstartswiththe
starttag<h1>andendswiththeendtag</h1>.Thepelementstartswiththestarttag<p>andendswith
theendtag</p>.Anythingbetweentheopeningandclosingtagsisthecontentoftheelement.
Starttagsconsistoftheelementnamesurroundedbyanglebrackets:<and>.Endtagsarethesame,but
theyhaveaforwardslash(/)beforetheelementname.
HeadingElements
Eachelementhasaspecialmeaninganduse.Forexample,theh1elementmeans“Thisisatop-level
heading.”Thecontentyouputinbetweentheopeningandclosing<h1>tagsisdisplayedbythe
browseronitsownline,inalarge,boldfont.
TherearesixlevelsofheadingelementsinHTML:h1,h2,h3,h4,h5,andh6.Theylooklikethis:
<h1>First-levelheading</h1>
<h2>Second-levelheading</h2>
<h3>Third-levelheading</h3>
<h4>Fourth-levelheading</h4>
<h5>Fifth-levelheading</h5>
<h6>Sixth-levelheading</h6>
Figure5-2showshowtheheadingslookonawebpage.
Figure5-2.Thedifferentheadingelements
ThepElement
Thepelementisusedtodefineseparateparagraphsoftext.Anytextyouputbetween<p>tagswill
displayinaseparateparagraph,withsomespaceaboveandbelowtheparagraph.Let’strycreating
multiplepelements.Addthisnewlinetoyourpage.htmldocument(theoldlinesareshowningray):
<h1>Helloworld!</h1>
<p>Myfirstwebpage.</p>
<p>Let'saddanotherparagraph.</p>
Figure5-3showsthewebpagewiththenewparagraph.
Figure5-3.Thesamepagebutwithanextraparagraph
Noticethattheparagraphsappearondifferentlinesandareseparatedbyabitofspace.Thisisall
becauseofthe<p>tags.
WhitespaceinHTMLandBlock-LevelElements
Whatwouldourpagelooklikewithoutthetags?Let’stakealook:
Helloworld!
Myfirstwebpage.
Let'saddanotherparagraph.
Figure5-4showsourpagewithoutanytags.
Figure5-4.ThesamepagebutwithnoHTMLtags
Ohno!Notonlyhavewelosttheformatting,buteverything’sononelongline!Thereasonisthatin
HTML,allwhitespaceiscollapsedintoasinglespace.Whitespacemeansanycharacterthatresultsin
blankspaceonthepage—forexample,thespacecharacter,thetabcharacter,andthenewlinecharacter
(thecharacterthatisinsertedwhenyoupressENTERorRETURN).Anyblanklinesyouinsertbetweentwo
piecesoftextinanHTMLdocumentwillgetcollapsedintoasinglespace.
Thepandh1elementsarecalledblock-levelelementsbecausetheydisplaytheircontentinaseparate
block,startingonanewline,andwithanyfollowingcontentonanewline.
InlineElements
Let’saddtwomoreelementstoourdocument,emandstrong:
<h1>Helloworld!</h1>
<p>My<em>first</em><strong>webpage</strong>.</p>
<p>Let'saddanother<strong><em>paragraph</em></strong>.</p>
Figure5-5showswhatthepagelookslikewiththenewtags.
Figure5-5.Theemandstrongelements
Theemelementmakesitscontentitalic.Thestrongelementmakesitscontentbold.Theemand
strongelementsarebothinlineelements,whichmeansthattheydon’tputtheircontentontoanew
line,asblock-levelelementsdo.
Tomakecontentboldanditalic,putitinsidebothtags.Noticeinthepreviousexamplethatthebold
italictexthasthetagsinthisorder:<strong><em>paragraph</em></strong>.It’simportantto
properlynestelements.Nestingmeansthatifanelementisinsideanotherelement,itsopeningand
closingtagsshouldbothbeinsidetheparentelement.Forexample,thisisnotallowed:
<strong><em>paragraph</strong></em>
Inthiscase,theclosing</strong>tagcomesbeforetheclosing</em>tag.Browsersgenerallywon’t
tellyouwhenyou’vemadeamistakelikethis,butgettingnestingwrongcancauseyourpagestobreak
instrangeways.
AFullHTMLDocument
Whatwe’velookedatsofarisreallyjustasnippetofHTML.AfullHTMLdocumentrequiressome
extraelements.Let’stakealookatanexampleofacompleteHTMLdocumentandwhateachpart
means.Updateyourpage.htmlfilewiththesenewelements:
<!DOCTYPEhtml>
<html>
<head>
<title>MyfirstproperHTMLpage</title>
</head>
<body>
<h1>Helloworld!</h1>
<p>My<em>first</em><strong>webpage</strong>.</p>
<p>Let'saddanother<strong><em>paragraph</em></strong>.</p>
</body>
</html>
NOTE
SublimeTextshouldautomaticallyindentcertainlinesforyou,asshowninthisexample.It’sactuallyidentifyinglinesbasedontheir
tags(like<html>,<h1>,andsoon)andindentingthemaccordingtotheirnesting.SublimeTextdoesn’tindentthe<head>and<body>
tags,thoughsomeeditorsdo.
Figure5-6showsthecompleteHTMLdocument.
Figure5-6.ThecompleteHTMLdocument
Let’stakeawalkthroughtheelementsinourpage.htmlfile.The<!DOCTYPEhtml>tagisjusta
declaration.Itsimplysays,“ThisisanHTMLdocument.”Nextcomestheopening<html>tag(the
closing</html>tagisattheveryend).AllHTMLdocumentsmusthaveanhtmlelementastheir
outermostelement.
Therearetwoelementsinsidethehtmlelement:headandbody.Theheadelementcontainscertain
informationaboutyourHTMLdocument,suchasthetitleelement,whichcontainsthedocument’s
title.Forexample,noticethatinFigure5-6,thetitleinthebrowsertab—“MyfirstproperHTML
page”—matcheswhatweenteredinthetitleelement.Thetitleelementiscontainedinsidethe
headelement,whichiscontainedinsidethehtmlelement.
Thebodyelementcontainsthecontentthatwillbedisplayedinthebrowser.Here,we’vejustcopiedthe
HTMLfromearlierinthechapter.
HTMLHierarchy
HTMLelementshaveaclearhierarchy,ororder,andcanbethoughtofasakindofupside-downtree.
YoucanseehowourdocumentwouldlookasatreeinFigure5-7.
Figure5-7.TheelementsfromFigure5-6,shownasatree
Thetopelementisthehtmlelement.Itcontainstheheadandbodyelements.Theheadcontainsthe
titleelement,andthebodycontainstheh1andpelements.ThebrowserinterpretsyourHTML
accordingtothishierarchy.We’lllookathowtochangethedocumentstructurelater,inChapter9.
Figure5-8showsanotherwayofvisualizingtheHTMLhierarchy,asasetofnestedboxes.
Figure5-8.TheHTMLhierarchy,shownasnestedboxes
AddingLinkstoYourHTML
Earlierinthischapter,welearnedthattheHTinHTMLstandsforHyperText,orlinkedtext.HTML
documentscancontainhyperlinks(linksforshort)thattakeyoutootherwebpages.Theaelement(for
anchor)createsalinkelement.
ModifyyourHTMLdocumenttomatchthefollowingexample:deletethesecondpelementandthe
<em>and<strong>tags,andthenaddthenewcoloredcodetocreatealinktohttp://xkcd.com/:
<!DOCTYPEhtml>
<html>
<head>
<title>MyfirstproperHTMLpage</title>
</head>
<body>
<h1>Helloworld!</h1>
<p>Myfirstwebpage.</p>
<p><ahref="http://xkcd.com">Clickhere</a>toreadsomeexcellent
comics.</p>
</body>
</html>
Nowsaveandopenyourpageinyourbrowser,anditshouldlooklikeFigure5-9.
Figure5-9.Awebpagecontainingalinktohttp://xkcd.com/
Ifyouclickthatlink,yourbrowsershouldgotothexkcdwebsite,http://xkcd.com/.Onceyou’vehad
yourfillofgeekycomics,clickthebackbuttontoreturntoyourpage.
LinkAttributes
Let’stakeacloserlookathowwecreatedthatHTMLlink.Totellthebrowserwheretogowhenyou
clicktheaelement,weaddedsomethingcalledanattributetotheanchorelement.AttributesinHTML
elementsaresimilartokey-valuepairsinJavaScriptobjects.Everyattributehasanameandavalue.
Here’sthexkcdlinkwecreatedagain:
<ahref="http://xkcd.com">Clickhere</a>
Inthiscase,theattributenameishrefandtheattributevalueis"http://xkcd.com".Thenamehref
standsforhypertextreference,whichisafancywayofsaying“webaddress.”
Figure5-10showsallthepartsofthelink.
Figure5-10.Thebasicsyntaxforcreatingahyperlink
Thelinkwilltakeyoutowhateverwebaddressisenteredasthevalueofthehrefattribute.
TitleAttributes
Anotherattributewecanaddtolinksisthetitleattribute.Thisattributesetsthetextyouseewhen
youhoveryourmouseoveralink.Forexample,changetheopening<a>tagsoitlookslikethis:
<ahref="http://xkcd.com"title="xkcd:Landofgeekycomics!">Clickhere</a>
Nowreloadthepage.Whenyouhoveryourcursoroverthelink,youshouldseethetext“xkcd:Landof
geekycomics!”floatingabovethepage,asshowninFigure5-11.
Figure5-11.Awebpagecontainingalinktohttp://xkcd.com/withatitleattribute
TRYITOUT!
Makeanewfilecalledlinks.html.ItshouldcontainthesameHTMLstructureasourpage.html,butwithanewtitleandheadingand
threeparagraph(p)elements.Ineachparagraph,includealinktooneofyourfavoritewebsites.Makesurealltheaelementshavehref
andtitleattributes.
WhatYouLearned
Inthischapter,youlearnedthebasicsofHTML,thelanguageusedtocreatewebpages.Wecreateda
simplepagecontainingalinktoanotherpage.
Inthenextchapter,we’lllookathowtoembedJavaScriptinourwebpage.Thiswillmakeitmuch
easiertocreatelargerprogramsasweexploremorefeaturesofJavaScriptinthenextfewchapters.
ThisisabookonJavaScript,notHTML,soI’veintroducedonlytheverybasicsofcreatingHTML
documents.HerearesomeresourceswhereyoucanlearnmoreaboutHTML:
TheMozillaDeveloperNetwork’sIntroductiontoHTML:https://developer.mozilla.org/enUS/docs/Web/Guide/HTML/Introduction/
Codecademy’sHTMLandCSScourse:http://www.codecademy.com/tracks/web/
MozillaWebmaker:https://webmaker.org/
Chapter6.ConditionalsandLoops
ConditionalsandloopsaretwoofthemostimportantconceptsinJavaScript.Aconditionalsays,“If
somethingistrue,dothis.Otherwise,dothat.”Forexample,ifyoudoyourhomework,youcanhave
icecream,butifyoudon’tdoyourhomework,youdon’tgettheicecream.Aloopsays,“Aslongas
somethingistrue,keepdoingthis.”Forexample,aslongasyouarethirsty,keepdrinkingwater.
Conditionalsandloopsarepowerfulconceptsthatarekeytoanysophisticatedprogram.Theyarecalled
controlstructuresbecausetheyallowyoutocontrolwhichpartsofyourcodeareexecutedwhenand
howoftenthey’reexecuted,basedoncertainconditionsyoudefine.
WefirstneedtogooverhowtoembedJavaScriptinourHTMLfilesowecanstartcreatinglonger
programsthanwe’velookedatsofar.
EmbeddingJavaScriptinHTML
HereistheHTMLfilewecreatedinChapter5,withadditionsincolorandtheexistingtextingray.(To
makethisexamplealittlesimpler,I’vealsodeletedthelinktoxkcd.)
<!DOCTYPEhtml>
<html>
<head>
<title>MyfirstproperHTMLpage</title>
</head>
<body>
<h1>Helloworld!</h1>
<p>Myfirstwebpage.</p>
<script>
varmessage="Helloworld!";
console.log(message);
</script>
</body>
</html>
Herewe’veaddedanewelement,calledscript.ThisisaspecialelementinHTML.WithmostHTML
elements,thecontentbetweentheopeningandclosingtagsisdisplayedonthepage.Withscript,on
theotherhand,everythingbetweenthetagsistreatedasJavaScriptandrunbytheJavaScript
interpreter.
Nowlet’slookatthecodeinsidethescriptelement:
varmessage="Helloworld!";
➊console.log(message);
RunningJavaScriptinanHTMLfileisquitedifferentfromrunningitintheconsole.Whenyou’re
usingtheJavaScriptconsole,eachlineyoutypeisrunassoonasyoupressENTER,andthevalueofthat
lineisprintedouttotheconsole.Inawebpage,theJavaScriptisallrunfromtoptobottomatonetime,
andnothingisautomaticallyprintedtotheconsole,unlesswetellthebrowserotherwise.Wecanuse
console.logtoprintthingsout,whichwillmakeiteasiertoseewhat’sgoingonaswerunour
programs.Theconsole.logmethodtakesanyvalueandprintsout,orlogs,thatvaluetotheconsole.
Forexample,ifyouloadtheHTMLfilefromthebeginningofthissectionwiththeJavaScriptconsole
open,you’llseethis:
Helloworld!
Callingconsole.log(message)at➊causedthestring"Helloworld!"tobeprintedtotheconsole.
NowthatyouknowhowtowritelongerprogramswithJavaScript,youcanstartlearningabout
conditionals.
Conditionals
TherearetwoformsofconditionalstatementsinJavaScript:ifstatementsandif...elsestatements.
Anifstatementisusedtoexecuteapieceofcodeifsomethingistrue.Forexample,ifyou’vebeen
good,yougetatreat.Anif...elsestatementexecutesonepieceofcodeifsomethingistrueand
anotherifnot.Forexample,ifyou’vebeengood,yougetatreat;else,yougetgrounded.
ifStatements
TheifstatementisthesimplestofJavaScript’scontrolstructures.It’susedtoruncodeonlyifa
conditionistrue.ReturntoyourHTMLfileandreplacethetwolinesinsidethescriptelementwith
this:
➊varname="Nicholas";
➋console.log("Hello"+name);
➌if(name.length>7){
➍console.log("Wow,youhaveaREALLYlongname!");
}
First,at➊wecreateavariablecallednameandsetitsvaluetothestring"Nicholas".Thenweuse
console.logtologthestring"HelloNicholas"at➋.
At➌weuseanifstatementtocheckwhetherthelengthofnameisgreaterthan7.Ifitis,theconsole
willdisplay"Wow,youhaveaREALLYlongname!",usingconsole.logat➍.
AsFigure6-1shows,anifstatementhastwomainparts:theconditionandthebody.Thecondition
shouldbeaBooleanvalue.ThebodyisoneormorelinesofJavaScriptcode,whichareexecutedifthe
conditionistrue.
Figure6-1.Thegeneralstructureofanifstatement
WhenyouloadyourHTMLpagewiththisJavaScriptinit,youshouldseethefollowingintheconsole:
HelloNicholas
Wow,youhaveaREALLYlongname!
BecausethenameNicholashaseightcharacters,name.lengthreturns8.Therefore,thecondition
name.length>7istrue,whichcausesthebodyoftheifstatementtoberun,resultinginthis
somewhatstartlingmessagebeinglogged.Toavoidtriggeringtheifcondition,changethename
NicholastoNick(leavingtherestofthecodeasis):
varname="Nick";
Nowsavethefileandreloadthepage.Thistime,theconditionname.length>7isnottrue,because
name.lengthis4.Thatmeansthatthebodyoftheifstatementisnotrunandallthatgetsprintedto
theconsoleisthis:
HelloNick
Thebodyofanifstatementisexecutedonlyiftheconditionistrue.Whentheconditionisfalse,the
interpretersimplyskipsovertheifstatementandmovesontothenextline.
if...elseStatements
AsIsaidbefore,anifstatementwillexecuteitsbodyonlyiftheconditionistrue.Ifyouwant
somethingelsetohappenwhentheconditionisfalse,youneedtouseanif...elsestatement.
Let’sextendtheexamplefromearlier:
varname="Nicholas";
console.log("Hello"+name);
if(name.length>7){
console.log("Wow,youhaveaREALLYlongname!");}
else{
console.log("Yournameisn'tverylong.");
}
Thisdoesthesamethingasbefore,exceptthatifthenameisn’tlongerthansevencharacters,itprints
outanalternativemessage.
AsFigure6-2shows,if...elsestatementslooklikeifstatements,butwithtwobodies.Thekeyword
elseisplacedbetweenthetwobodies.Inanif...elsestatement,thefirstbodyisrunifthecondition
istrue;otherwise,thesecondbodyisrun.
Figure6-2.Thegeneralstructureofanif...elsestatement
Chainingif...elseStatements
Oftenweneedtocheckasequenceofconditionsanddosomethingwhenoneofthemistrue.For
example,sayyou’reorderingChinesefoodandyou’rechoosingwhattoeat.YourfavoriteChinesedish
islemonchicken,soyou’llhavethatifit’sonthemenu.Ifit’snot,you’llhavebeefwithblackbean
sauce.Ifthat’snotonthemenu,you’llhavesweetandsourpork.Intherarecasethatnoneofthose
optionsisavailable,you’llhaveeggfriedrice,becauseyouknowalltheChineserestaurantsyougoto
willhavethat.
varlemonChicken=false;
varbeefWithBlackBean=true;
varsweetAndSourPork=true;
if(lemonChicken){
console.log("Great!I'mhavinglemonchicken!");
}elseif(beefWithBlackBean){
console.log("I'mhavingthebeef.");
}elseif(sweetAndSourPork){
console.log("OK,I'llhavethepork.");
}else{
console.log("Well,IguessI'llhavericethen.");
}
Tocreateachainofif...elsestatements,startwithanormalifstatementand,aftertheclosingbrace
ofitsbody,enterthekeywordselseif,followedbyanotherconditionandanotherbody.Youcankeep
doingthisuntilyourunoutofconditions;there’snolimittothenumberofconditions.Thefinalelse
sectionwillrunifnoneoftheconditionsistrue.Figure6-3showsagenericchainofif...else
statements.
Figure6-3.Chainingmultipleif...elsestatements
Youcanreadthisasfollows:
1.
2.
3.
4.
Ifthefirstconditionistrue,executethefirstbody.
Otherwise,ifthesecondconditionistrue,executethesecondbody.
Otherwise,ifthethirdconditionistrue,executethethirdbody.
Otherwise,executetheelsebody.
Whenyouhaveachainofif...elsestatementslikethiswithafinalelsesection,youcanbesurethat
one(andonlyone)ofthebodieswillberun.Assoonasatrueconditionisfound,itsassociatedbodyis
run,andnoneoftheotherconditionsischecked.Ifwerunthecodeinthepreviousexample,I'm
havingthebeefwillbeprintedtotheconsole,becausebeefWithBlackBeanisthefirstcondition
that’sfoundtobetrueintheif...elsechain.Ifnoneoftheconditionsistrue,theelsebodyisrun.
There’soneotherthingtonote:youdon’tnecessarilyhavetoincludethefinalelse.Ifyoudon’t,
though,andnoneoftheconditionsistrue,thennothinginsidetheif...elsechainwillbeexecuted.
varlemonChicken=false;
varbeefWithBlackBean=false;
varsweetAndSourPork=false;
if(lemonChicken){
console.log("Great!I'mhavinglemonchicken!");
}elseif(beefWithBlackBean){
console.log("I'mhavingthebeef.");
}elseif(sweetAndSourPork){
console.log("OK,I'llhavethepork.");
}
Inthisexample,we’veleftoutthefinalelsesection.Becausenoneofyourfavoritefoodsisavailable,
nothinggetsprintedout(anditlookslikeyou’renotgoingtohaveanythingtoeat!).
TRYITOUT!
Writeaprogramwithanamevariable.Ifnameisyourname,printoutHellome!;otherwise,printHellostranger!.(Hint:Use===to
comparenametoyourname.)
Next,rewritetheprogramsoit’llsayhitoyourdadifnameissettoyourdad’snameorhitoyourmomifnameisyourmom’sname.If
it’sneitherofthem,sayHellostranger!asbefore.
Loops
Aswe’veseen,conditionalsallowyoutorunapieceofcodeonceifaconditionistrue.Loops,onthe
otherhand,allowyoutorunapieceofcodemultipletimes,dependingonwhetheraconditionremains
true.Forexample,whilethere’sfoodonyourplate,youshouldkeepeating;or,whileyoustillhave
dirtonyourface,youshouldkeepwashing.
whileLoops
Thesimplestkindofloopisawhileloop.Awhilelooprepeatedlyexecutesitsbodyuntilaparticular
conditionstopsbeingtrue.Bywritingawhileloop,youaresaying,“Keepdoingthiswhilethis
conditionistrue.Stopwhentheconditionbecomesfalse.”
AsFigure6-4shows,whileloopsstartwiththewhilekeyword,followedbyaconditioninparentheses
andthenabodyinbraces.
Figure6-4.Thegeneralstructureofawhileloop
Likeanifstatement,thebodyofawhileloopisexecutediftheconditionistrue.Unlikeanif
statement,afterthebodyisexecuted,theconditionischeckedagain,andifit’sstilltrue,thebodyruns
again.Thiscyclegoesonuntiltheconditionisfalse.
CountingSheepwithawhileloop
Sayyou’rehavingtroublesleepingandyouwanttocountsheep.Butyou’reaprogrammer,sowhynot
writeaprogramtocountsheepforyou?
varsheepCounted=0;
➊while(sheepCounted<10){
➋console.log("Ihavecounted"+sheepCounted+"sheep!");
sheepCounted++;
}
console.log("Zzzzzzzzzzz");
WecreateavariablecalledsheepCountedandsetitsvalueto0.Whenwereachthewhileloop➊,we
checktoseewhethersheepCountedislessthan10.Because0islessthan10,thecodeinsidethebraces
(thebodyoftheloop)➋runs,and"Ihavecounted"+sheepCounted+"sheep!"isloggedas
“Ihavecounted0sheep!”Next,sheepCounted++adds1tothevalueofsheepCounted,andwego
backtothestartoftheloop,overandover:
Ihavecounted0sheep!
Ihavecounted1sheep!
Ihavecounted2sheep!
Ihavecounted3sheep!
Ihavecounted4sheep!
Ihavecounted5sheep!
Ihavecounted6sheep!
Ihavecounted7sheep!
Ihavecounted8sheep!
Ihavecounted9sheep!
Zzzzzzzzzzz
ThisrepeatsuntilsheepCountedbecomes10,atwhichpointtheconditionbecomesfalse(10isnot
lessthan10),andtheprogrammovesontowhatevercomesaftertheloop.Inthiscase,itprints
Zzzzzzzzzzz.
PreventingInfiniteLoops
Keepthisinmindwhenyou’reusingloops:iftheconditionyousetneverbecomesfalse,yourloop
willloopforever(oratleastuntilyouquityourbrowser).Forexample,ifyouleftouttheline
sheepCounted++;,thensheepCountedwouldremain0,andtheoutputwouldlooklikethis:
Ihavecounted0sheep!
Ihavecounted0sheep!
Ihavecounted0sheep!
Ihavecounted0sheep!
...
Becausethere’snothingtostopit,theprogramwouldkeepdoingthisforever!Thisiscalledaninfinite
loop.
forLoops
forloopsmakeiteasiertowriteloopsthatcreateavariable,loopuntilaconditionistrue,andupdate
thevariableattheendofeachturnaroundtheloop.Whensettingupaforloop,youcreateavariable,
specifythecondition,andsayhowthevariableshouldchangeaftereachcycle—allbeforeyoureach
thebodyoftheloop.Forexample,here’showwecoulduseaforlooptocountsheep:
for(varsheepCounted=0;sheepCounted<10;sheepCounted++){
console.log("Ihavecounted"+sheepCounted+"sheep!");
}
console.log("Zzzzzzzzzzz");
AsFigure6-5shows,therearethreepartstothisforloop,separatedbysemicolons:thesetup,
condition,andincrement.
Figure6-5.Thegeneralstructureofaforloop
Thesetup(varsheepCounted=0)isrunbeforetheloopstarts.It’sgenerallyusedtocreateavariable
totrackthenumberoftimestheloophasrun.HerewecreatethevariablesheepCountedwithaninitial
valueof0.
Thecondition(sheepCounted<10)ischeckedbeforeeachrunoftheloopbody.Iftheconditionis
true,thebodyisexecuted;ifit’sfalse,theloopstops.Inthiscase,theloopwillstoponce
sheepCountedisnolongerlessthan10.
Theincrement(sheepCounted++)isrunaftereveryexecutionoftheloopbody.It’sgenerallyusedto
updatetheloopingvariable.Here,weuseittoadd1tosheepCountedeachtimetheloopruns.
forloopsareoftenusedtodosomethingasetnumberoftimes.Forexample,thisprogramwillsay
Hello!threetimes.
vartimesToSayHello=3;
for(vari=0;i<timesToSayHello;i++){
console.log("Hello!");
}
Hereistheoutput:
Hello!
Hello!
Hello!
IfweweretheJavaScriptinterpreterrunningthiscode,wewouldfirstcreateavariablecalled
timesToSayHelloandsetitto3.Whenwereachtheforloop,werunthesetup,whichcreatesa
variableiandsetsitto0.Next,wecheckthecondition.Becauseiisequalto0andtimesToSayHello
is3,theconditionistrue,soweentertheloopbody,whichsimplyoutputsthestring"Hello!".We
thenruntheincrement,whichincreasesito1.
Nowwechecktheconditionagain.It’sstilltrue,sowerunthebodyandincrementagain.This
happensrepeatedlyuntiliisequalto3.Atthispoint,theconditionisfalse(3isnotlessthan3),sowe
exittheloop.
UsingforLoopswithArraysandStrings
Oneverycommonuseofforloopsistodosomethingwitheveryelementinanarrayoreverycharacter
inastring.Forexample,hereisaforloopthatprintsouttheanimalsinazoo:
varanimals=["Lion","Flamingo","PolarBear","BoaConstrictor"];
for(vari=0;i<animals.length;i++){
console.log("Thiszoocontainsa"+animals[i]+".");
}
Inthisloop,istartsat0andgoesuptoonelessthananimals.length,whichinthiscaseis3.The
numbers0,1,2,and3aretheindexesoftheanimalsintheanimalsarray.Thismeansthateverytime
aroundtheloop,iisadifferentindex,andanimals[i]isanotheranimalfromtheanimalsarray.
Wheniis0,animals[i]is"Lion".Wheniis1,animals[i]is"Flamingo",andsoon.
Runningthiswouldoutput:
ThiszoocontainsaLion.
ThiszoocontainsaFlamingo.
ThiszoocontainsaPolarBear.
ThiszoocontainsaBoaConstrictor.
AsyousawinChapter2,youcanaccessindividualcharactersinastringinthesamewayyoucan
accessindividualelementsinanarray,usingsquarebrackets.Thisnextexampleusesaforlooptoprint
outthecharactersinaname:
varname="Nick";
for(vari=0;i<name.length;i++){
console.log("Mynamecontainstheletter"+name[i]+".");
}
Thiswouldoutput:
MynamecontainstheletterN.
Mynamecontainstheletteri.
Mynamecontainstheletterc.
Mynamecontainstheletterk.
OtherWaystouseforLoops
Asyoumightimagine,youdon’talwayshavetostarttheloopingvariableat0andincrementitby1.
Forexample,here’sawaytoprintallthepowersof2belowthenumber10,000:
for(varx=2;x<10000;x=x*2){
console.log(x);
}
Wesetxto2andincrementthevalueofxusingx=x*2;,whichwilldoublethevalueofxeach
timetheloopruns.Theresultgetsbigveryquickly,asyoucansee:
2
4
8
16
32
64
128
256
512
1024
2048
4096
8192
Andvoilà!Thisshortforloopprintsoutallthepowersof2below10,000.
TRYITOUT!
Writealooptoprintthepowersof3under10,000(itshouldprint3,9,27,etc.).
Rewritethisloopwithawhileloop.(Hint:Providethesetupbeforetheloop.)
WhatYouLearned
Inthischapter,youlearnedaboutconditionalsandloops.Conditionalsareusedtoruncodeonlywhena
certainconditionistrue.Loopsareusedtoruncodemultipletimesandtokeeprunningthatcodeas
longasacertainconditionistrue.Youcanuseconditionalstomakesurethattherightcodeisrunat
therighttime,andyoucanuseloopstokeepyourprogramrunningaslongasnecessary.Havingthe
abilitytodothesetwothingsopensupawholenewworldofprogrammingpossibilities.
Inthenextchapter,we’llusethepowerofconditionalsandloopstomakeourfirstrealgame!
ProgrammingChallenges
Tryoutthesechallengestopracticeworkingwithconditionalsandloops.
#1:AWESOMEANIMALS
Writeaforloopthatmodifiesanarrayofanimals,makingthemawesome!Forexample,ifyour
startingarrayis...
varanimals=["Cat","Fish",
"Lemur","KomodoDragon"];
thenafteryourunyourloop,itshouldlooklikethis:
["AwesomeCat","AwesomeFish","AwesomeLemur","Awesome
KomodoDragon"]
Hint:You’llneedtoreassignvaluestothearrayateachindex.Thisjustmeansassigninganewvalueat
anexistingpositioninthearray.Forexample,tomakethefirstanimalawesome,youcouldsay:
animals[0]="Awesome"+animals[0];
#2:RANDOMSTRINGGENERATOR
Makearandomstringgenerator.You’llneedtostartwithastringcontainingallthelettersinthe
alphabet:
varalphabet="abcdefghijklmnopqrstuvwxyz";
Topickarandomletterfromthisstring,youcanupdatethecodeweusedfortherandominsult
generatorinChapter3:Math.floor(Math.random()*alphabet.length).Thiswillcreatearandom
indexintothestring.Youcanthenusesquarebracketstogetthecharacteratthatindex.
Tocreatetherandomstring,startwithanemptystring(varrandomString="").Then,createa
whileloopthatwillcontinuallyaddnewrandomletterstothisstring,aslongasthestringlengthisless
than6(oranylengthyouchoose).Youcouldusethe+=operatortoaddanewlettertotheendofthe
string.Aftertheloophasfinished,logittotheconsoletoseeyourcreation!
#3:H4CK3RSP34K
Turntextintoh4ck3rsp34k!AlotofpeopleontheInternetliketoreplacecertainletterswithnumbers
thatlooklikethoseletters.Somenumbersthatlooklikelettersare4forA,3forE,1forI,and0forO.
Eventhoughthenumberslookmorelikecapitalletters,we’llbereplacingthelowercaseversionsof
thoseletters.Tochangenormaltexttoh4ck3rsp34k,we’llneedaninputstringandanewempty
string:
varinput="javascriptisawesome";
varoutput="";
You’llthenneedtouseaforlooptogothroughallthelettersoftheinputstring.Iftheletteris"a",add
a"4"totheoutputstring.Ifit’s"e",adda"3".Ifit’s"i",adda"1",andifit’s"o",adda"0".
Otherwise,justaddtheoriginallettertothenewstring.Asbefore,youcanuse+=toaddeachnewletter
totheoutputstring.
Aftertheloop,logtheoutputstringtotheconsole.Ifitworkscorrectly,youshouldseeitlog
"j4v4scr1pt1s4w3s0m3".
Chapter7.CreatingaHangmanGame
Inthischapterwe’llbuildaHangmangame!We’lllearnhowtousedialogstomakethegame
interactiveandtakeinputfromsomeoneplayingthegame.
Hangmanisaword-guessinggame.Oneplayerpicksasecretword,andtheotherplayertriestoguess
it.
Forexample,ifthewordwereTEACHER,thefirstplayerwouldwrite:
Theguessingplayertriestoguessthelettersintheword.Eachtimetheyguessalettercorrectly,thefirst
playerfillsintheblanksforeachoccurrenceofthatletter.Forexample,iftheguessingplayerguessed
theletterE,thefirstplayerwouldfillintheEsinthewordTEACHERlikeso:
Whentheguessingplayerguessesaletterthatisn’tintheword,theyloseapointandthefirstplayer
drawspartofastick-manforeachwrongguess.Ifthefirstplayercompletesthestickmanbeforethe
guessingplayerguessestheword,theguessingplayerloses.
InourversionofHangman,theJavaScriptprogramwillchoosethewordandthehumanplayerwill
guessletters.Wewon’tbedrawingthestickman,becausewehaven’tyetlearnedhowtodrawin
JavaScript(we’lllearnhowtodothatinChapter13).
InteractingwithaPlayer
Tocreatethisgame,wehavetohavesomewayfortheguessingplayer(human)toentertheirchoices.
Onewayistoopenapop-upwindow(whichJavaScriptcallsaprompt)thattheplayercantypeinto.
CreatingaPrompt
First,let’screateanewHTMLdocument.UsingFile▸SaveAs,saveyourpage.htmlfilefromChapter5
asprompt.html.Tocreateaprompt,enterthiscodebetweenthe<script>tagsofprompt.htmland
refreshthebrowser:
varname=prompt("What'syourname?");
console.log("Hello"+name);
Herewecreateanewvariable,calledname,andassigntoitthevaluereturnedfromcalling
prompt("What'syourname?").Whenpromptiscalled,asmallwindow(ordialog)isopened,which
shouldlooklikeFigure7-1.
Figure7-1.Apromptdialog
Callingprompt("What'syourname?")popsupawindowwiththetext“What’syourname?”along
withatextboxforinput.Atthebottomofthedialogaretwobuttons,CancelandOK.InChrome,the
dialoghastheheadingJavaScript,toinformyouthatJavaScriptopenedtheprompt.
WhenyouentertextintheboxandclickOK,thattextbecomesthevaluethatisreturnedbyprompt.
Forexample,ifIweretoentermynameintothetextboxandclickOK,JavaScriptwouldprintthisin
theconsole:
HelloNick
BecauseIenteredNickinthetextboxandclickedOK,thestring"Nick"issavedinthevariablename
andconsole.logprints"Hello"+"Nick",whichgivesus"HelloNick".
NOTE
ThesecondtimeyouopenanykindofdialoginChrome,itaddsanextralinetothedialogwithacheckboxsaying,“Preventthispage
fromcreatingadditionaldialogs.”ThisisChrome’swayofprotectingusersfromwebpageswithlotsofannoyingpop-ups.Justleave
theboxuncheckedfortheexercisesinthischapter.
WHATHAPPENSIFYOUCLICKCANCEL?
IfyouclicktheCancelbutton,promptreturnsthevaluenull.InChapter2,welearnedthatyoucanusenulltoindicatewhen
somethingisintentionallyempty.
ClickCancelatthedialog,andyoushouldseethis:
Hellonull
Here,nullisprintedasastringbyconsole.log.Normally,nullisn’tastring,butsinceonlystringscanbeprintedtotheconsoleand
youtoldJavaScripttoprint"Hello"+null,JavaScriptturnsthevaluenullintothestring"null"soitcanbeprinted.When
JavaScriptconvertsavalueintoanothertype,it’scalledcoercion.
CoercionisanexampleofJavaScripttryingtobeclever.Thereisn’tanywaytocombineastringandnullusingthe+operator,so
JavaScriptdoesitsbestwiththesituation.Inthiscase,itknowsitneedstwostrings.Thestringversionofnullis"null",whichiswhy
youseethestring"Hellonull"printed.
UsingconfirmtoAskaYesorNoQuestion
Theconfirmfunctionisawaytotakeuserinputwithoutatextboxbyaskingforayesorno(Boolean)
answer.Forexample,hereweuseconfirmtoasktheuseriftheylikecats(seeFigure7-2).Ifso,the
variablelikesCatsissettotrue,andwerespondwith“You’reacoolcat!”Iftheydon’tlikecats,
likesCatsissettofalse,sowerespondwith“Yeah,that’sfine.You’restillcool!”
varlikesCats=confirm("Doyoulikecats?");
if(likesCats){
console.log("You'reacoolcat!");
}else{
console.log("Yeah,that'sfine.You'restillcool!");
}
Figure7-2.Aconfirmdialog
TheanswertotheconfirmpromptisreturnedasaBooleanvalue.IftheuserclicksOKintheconfirm
dialogshowninFigure7-2,trueisreturned.IftheyclickCancel,falseisreturned.
UsingAlertstoGiveaPlayerInformation
Ifyouwanttojustgivetheplayersomeinformation,youcanuseanalertdialogtodisplayamessage
withanOKbutton.Forexample,ifyouthinkthatJavaScriptisawesome,youmightusethisalert
function:
alert("JavaScriptisawesome!");
Figure7-3showswhatthissimplealertdialogwouldlooklike.
Figure7-3.Analertdialog
AlertdialogsjustdisplayamessageandwaituntiltheuserclicksOK.
WhyUsealertInsteadofconsole.log?
Whyuseanalertdialoginagameinsteadofusingconsole.log?First,becauseifallyouwanttodois
telltheplayersomething,usingalertmeanstheplayerdoesn’thavetointerruptgameplaytoopenthe
consoletoseeastatusmessage.Second,callingalert(aswellaspromptandconfirm)pausesthe
JavaScriptinterpreteruntiltheuserclicksOK(orCancel,inthecaseofpromptandconfirm).That
meanstheplayerhastimetoreadthealert.Ontheotherhand,whenyouuseconsole.log,thetextis
displayedimmediatelyandtheinterpretermovesontothenextlineinyourprogram.
DesigningYourGame
BeforewestartwritingtheHangmangame,let’sthinkaboutitsstructure.Thereareafewthingswe
needourprogramtodo:
1.
2.
3.
4.
5.
6.
7.
Pickarandomword.
Taketheplayer’sguess.
Quitthegameiftheplayerwantsto.
Checkthattheplayer’sguessisavalidletter.
Keeptrackofletterstheplayerhasguessed.
Showtheplayertheirprogress.
Finishwhentheplayerhasguessedtheword.
Apartfromthefirstandlasttasks(pickingawordfortheplayertoguessandfinishingthegame),these
stepsallneedtohappenmultipletimes,andwedon’tknowhowmanytimes(itdependsonhowwell
theplayerguesses).Whenyouneedtodothesamethingmultipletimes,youknowyou’llneedaloop.
Butthissimplelistoftasksdoesn’treallygiveusanyideaofwhatneedstohappenwhen.Togeta
betterideaofthestructureofthecode,wecanusepseudocode.
UsingPseudocodetoDesigntheGame
Pseudocodeisahandytoolthatprogrammersoftenusetodesignprograms.Itmeans“fakecode,”and
it’sawayofdescribinghowaprogramwillworkthatlookslikeacrossbetweenwrittenEnglishand
code.Pseudocodehasloopsandconditionals,butotherthanthat,everythingisjustplainEnglish.Let’s
lookatapseudocodeversionofourgametogetanidea:
Pickarandomword
Whilethewordhasnotbeenguessed{
Showtheplayertheircurrentprogress
Getaguessfromtheplayer
Iftheplayerwantstoquitthegame{
Quitthegame
}
ElseIftheguessisnotasingleletter{
Telltheplayertopickasingleletter
}
Else{
Iftheguessisintheword{
Updatetheplayer'sprogresswiththeguess
}
}
}
Congratulatetheplayeronguessingtheword
Asyoucansee,noneofthisisrealcode,andnocomputercouldunderstandit.Butitgivesusanideaof
howourprogramwillbestructured,beforewegettoactuallywritingthecodeandhavingtodealwith
themessydetails,likehowwe’regoingtopickarandomword.
TrackingtheStateoftheWord
Inthepreviouspseudocode,oneofthefirstlinessays,“Showtheplayertheircurrentprogress.”Forthe
Hangmangame,thismeansfillinginthelettersthattheplayerhasguessedcorrectlyandshowingwhich
lettersinthesecretwordarestillblank.Howarewegoingtodothis?Wecanactuallykeeptrackofthe
player’sprogressinasimilarwaytohowtraditionalHangmanworks:bykeepingacollectionofblank
spacesandfillingtheminastheplayerguessescorrectletters.
Inourgame,we’lldothisusinganarrayofblanksforeachletterintheword.We’llcallthistheanswer
array,andwe’llfillitwiththeplayer’scorrectguessesasthey’remade.We’llrepresenteachblankwith
thestring"_".
Theanswerarraywillstartoutasagroupoftheseemptyentriesequalinnumbertothelettersinthe
secretword.Forexample,ifthesecretwordisfish,thearraywouldlooklikethis:
["_","_","_","_"]
Iftheplayercorrectlyguessedtheletteri,we’dchangethesecondblanktoani:
["_","i","_","_"]
Oncetheplayerguessesallthecorrectletters,thecompletedarraywouldlooklikethis:
["f","i","s","h"]
We’llalsouseavariabletokeeptrackofthenumberofremainingletterstheplayerhastoguess.For
everyoccurrenceofacorrectlyguessedletter,thisvariablewilldecreaseby1.Onceithits0,weknow
theplayerhaswon.
DesigningtheGameLoop
Themaingametakesplaceinsideawhileloop(inourpseudocode,thisloopbeginswiththeline
“Whilethewordhasnotbeenguessed”).Inthisloopwedisplaythecurrentstateofthewordbeing
guessed(beginningwithallblanks);asktheplayerforaguess(andmakesureit’savalid,single-letter
guess);andupdatetheanswerarraywiththechosenletter,ifthatletterappearsintheword.
Almostallcomputergamesarebuiltaroundaloopofsomekind,oftenwiththesamebasicstructureas
theloopinourHangmangame.Agameloopgenerallydoesthefollowing:
1. Takesinputfromtheplayer
2. Updatesthegamestate
3. Displaysthecurrentstateofthegametotheplayer
Evengamesthatareconstantlychangingfollowthissamekindofloop—theyjustdoitreallyfast.In
thecaseofourHangmangame,theprogramtakesaguessfromtheplayer,updatestheanswerarrayif
theguessiscorrect,anddisplaysthenewstateoftheanswerarray.
Oncetheplayerguessesalllettersintheword,weshowthecompletedwordandacongratulatory
messagetellingthemthattheywon.
CodingtheGame
Nowthatweknowthegeneralstructureofourgame,wecanstarttogooverhowthecodewilllook.
Thefollowingsectionswillwalkyouthroughallthecodeinthegame.Afterthat,you’llseethewhole
gamecodeinonelistingsoyoucantypeitupandplayityourself.
ChoosingaRandomWord
Thefirstthingwehavetodoistochoosearandomword.Here’showthatwilllook:
➊varwords=[
"javascript",
"monkey",
"amazing",
"pancake"
];
➋varword=words[Math.floor(Math.random()*words.length)];
Webeginourgameat➊bycreatinganarrayofwords(javascript,monkey,amazing,andpancake)to
beusedasthesourceofoursecretword,andwesavethearrayinthewordsvariable.Thewordsshould
bealllowercase.At➋weuseMath.randomandMath.floortopickarandomwordfromthearray,as
wedidwiththerandominsultgeneratorinChapter3.
CreatingtheAnswerArray
NextwecreateanemptyarraycalledanswerArrayandfillitwithunderscores(_)tomatchthenumber
oflettersintheword.
varanswerArray=[];
➊for(vari=0;i<word.length;i++){
answerArray[i]="_";
}
varremainingLetters=word.length;
Theforloopat➊createsaloopingvariableithatstartsat0andgoesupto(butdoesnotinclude)
word.length.Eachtimearoundtheloop,weaddanewelementtoanswerArray,atanswerArray[i].
Whentheloopfinishes,answerArraywillbethesamelengthasword.Forexample,ifwordis
"monkey"(whichhassixletters),answerArraywillbe["_","_","_","_","_","_"](six
underscores).
Finally,wecreatethevariableremainingLettersandsetittothelengthofthesecretword.We’lluse
thisvariabletokeeptrackofhowmanylettersarelefttobeguessed.Everytimetheplayerguessesa
correctletter,thisvaluewillbedecremented(reduced)by1foreachinstanceofthatletterintheword.
CodingtheGameLoop
Theskeletonofthegamelooplookslikethis:
while(remainingLetters>0){
//Gamecodegoeshere
//Showtheplayertheirprogress
//Takeinputfromtheplayer
//UpdateanswerArrayandremainingLettersforeverycorrectguess
}
Weuseawhileloop,whichwillkeeploopingaslongasremainingLetters>0remainstrue.The
bodyoftheloopwillhavetoupdateremainingLettersforeverycorrectguesstheplayermakes.Once
theplayerhasguessedalltheletters,remainingLetterswillbe0andtheloopwillend.
Thefollowingsectionsexplainthecodethatwillmakeupthebodyofthegameloop.
ShowingthePlayer’sProgress
Thefirstthingweneedtodoinsidethegameloopistoshowtheplayertheircurrentprogress:
alert(answerArray.join(""));
WedothatbyjoiningtheelementsofanswerArrayintoastring,usingthespacecharacterasthe
separator,andthenusingalerttoshowthatstringtotheplayer.Forexample,let’ssaythewordis
monkeyandtheplayerhasguessedm,o,andesofar.Theanswerarraywouldlooklikethis["m",
"o","_","_","e","_"],andanswerArray.join("")wouldbe"mo__e_".Thealert
dialogwouldthenlooklikeFigure7-4.
Figure7-4.Showingtheplayer’sprogressusingalert
HandlingthePlayer’sInput
Nowwehavetogetaguessfromtheplayerandensurethatit’sasinglecharacter.
➊varguess=prompt("Guessaletter,orclickCanceltostopplaying.");
➋if(guess===null){
break;
➌}elseif(guess.length!==1){
alert("Pleaseenterasingleletter.");
}else{
➍//Updatethegamestatewiththeguess
}
At➊,prompttakesaguessfromtheplayerandsavesittothevariableguess.Oneoffourthingswill
happenatthispoint.
First,iftheplayerclickstheCancelbutton,thenguesswillbenull.Wecheckforthisconditionat➋
withif(guess===null).Ifthisconditionistrue,weusebreaktoexittheloop.
NOTE
Youcanusethebreakkeywordinanylooptoimmediatelystoplooping,nomatterwheretheprogramisinthelooporwhetherthe
whileconditioniscurrentlytrue.
Thesecondandthirdpossibilitiesarethattheplayerenterseithernothingortoomanyletters.Ifthey
enternothingbutclickOK,guesswillbetheemptystring"".Inthiscase,guess.lengthwillbe0.If
theyenteranythingmorethanoneletter,guess.lengthwillbegreaterthan1.
At➌,weuseelseif(guess.length!==1)tocheckfortheseconditions,ensuringthatguessis
exactlyoneletter.Ifit’snot,wedisplayanalertsaying,“Pleaseenterasingleletter.”
Thefourthpossibilityisthattheplayerentersavalidguessofoneletter.Thenwehavetoupdatethe
gamestatewiththeirguessusingtheelsestatementat➍,whichwe’lldointhenextsection.
UpdatingtheGameState
Oncetheplayerhasenteredavalidguess,wemustupdatethegame’sanswerArrayaccordingtothe
guess.Todothat,weaddthefollowingcodetotheelsestatement:
➊for(varj=0;j<word.length;j++){
➋if(word[j]===guess){
answerArray[j]=guess;
➌remainingLetters--;
}
}
At➊,wecreateaforloopwithanewloopingvariablecalledj,whichrunsfrom0uptoword.length.
(We’reusingjasthevariableinthisloopbecausewealreadyusediinthepreviousforloop.)Weuse
thislooptostepthrougheachletterofword.Forexample,let’ssaywordispancake.Thefirsttime
aroundthisloop,whenjis0,word[j]willbe"p".Thenexttime,word[j]willbe"a",then"n","c",
"a","k",andfinally"e".
At➋,weuseif(word[j]===guess)tocheckwhetherthecurrentletterwe’relookingatmatches
theplayer’sguess.Ifitdoes,weuseanswerArray[j]=guesstoupdatetheanswerarraywiththe
currentguess.Foreachletterinthewordthatmatchesguess,weupdatetheanswerarrayatthe
correspondingpoint.Thisworksbecausetheloopingvariablejcanbeusedasanindexfor
answerArrayjustasitcanbeusedasanindexforword,asyoucanseeinFigure7-5.
Figure7-5.ThesameindexcanbeusedforbothwordandanswerArray.
Forexample,imaginewe’vejuststartedplayingthegameandwereachtheforloopat➊.Let’ssay
wordis"pancake",guessis"a",andanswerArraycurrentlylookslikethis:
["_","_","_","_","_","_","_"]
Thefirsttimearoundtheforloopat➊,jis0,soword[j]is"p".Ourguessis"a",soweskiptheif
statementat➋(because"p"==="a"isfalse).Thesecondtimearound,jis1,soword[j]is"a".
Thisisequaltoguess,soweentertheifpartofthestatement.ThelineanswerArray[j]=guess;
setstheelementatindex1(thesecondelement)ofanswerArraytoguess,soanswerArraynowlooks
likethis:
["_","a","_","_","_","_","_"]
Thenexttwotimesaroundtheloop,word[j]is"n"andthen"c",whichdon’tmatchguess.However,
whenjreaches4,word[j]is"a"again.WeupdateanswerArrayagain,thistimesettingtheelementat
index4(thefifthelement)toguess.NowanswerArraylookslikethis:
["_","a","_","_","a","_","_"]
Theremaininglettersdon’tmatch"a",sonothinghappensthelasttwotimesaroundtheloop.Atthe
endofthisloop,answerArraywillbeupdatedwithalltheoccurrencesofguessinword.
Foreverycorrectguess,inadditiontoupdatinganswerArray,wealsoneedtodecrement
remainingLettersby1.Wedothisat➌usingremainingLetters--;.Everytimeguessmatchesa
letterinword,remainingLettersdecreasesby1.Oncetheplayerhasguessedalltheletterscorrectly,
remainingLetterswillbe0.
EndingtheGame
Aswe’vealreadyseen,themaingameloopconditionisremainingLetters>0,soaslongasthere
arestillletterstoguess,theloopwillkeeplooping.OnceremainingLettersreaches0,weleavethe
loop.Weendwiththefollowingcode:
alert(answerArray.join(""));
alert("Goodjob!Theanswerwas"+word);
Thefirstlineusesalerttoshowtheanswerarrayonelasttime.Thesecondlineusesalertagainto
congratulatethewinningplayer.
TheGameCode
Nowwe’veseenallthecodeforthegame,andwejustneedtoputittogether.Whatfollowsisthefull
listingforourHangmangame.I’veaddedcommentsthroughouttomakeiteasierforyoutoseewhat’s
happeningateachpoint.It’squiteabitlongerthananyofthecodewe’vewrittensofar,buttypingit
outwillhelpyoutobecomemorefamiliarwithwritingJavaScript.CreateanewHTMLfilecalled
hangman.htmlandtypethefollowingintoit:
<!DOCTYPEhtml>
<html>
<head>
<title>Hangman!</title>
</head>
<body>
<h1>Hangman!</h1>
<script>
//Createanarrayofwords
varwords=[
"javascript",
"monkey",
"amazing",
"pancake"
];
//Pickarandomword
varword=words[Math.floor(Math.random()*words.length)];
//Setuptheanswerarray
varanswerArray=[];
for(vari=0;i<word.length;i++){
answerArray[i]="_";
}
varremainingLetters=word.length;
//Thegameloop
while(remainingLetters>0){
//Showtheplayertheirprogress
alert(answerArray.join(""));
//Getaguessfromtheplayer
varguess=prompt("Guessaletter,orclickCanceltostop
playing.");
if(guess===null){
//Exitthegameloop
break;
}elseif(guess.length!==1){
alert("Pleaseenterasingleletter.");
}else{
//Updatethegamestatewiththeguess
for(varj=0;j<word.length;j++){
if(word[j]===guess){
answerArray[j]=guess;
remainingLetters--;
}
}
}
//Theendofthegameloop
}
//Showtheanswerandcongratulatetheplayer
alert(answerArray.join(""));
alert("Goodjob!Theanswerwas"+word);
</script>
</body>
</html>
Ifthegamedoesn’trun,makesurethatyoutypedineverythingcorrectly.Ifyoumakeamistake,the
JavaScriptconsolecanhelpyoufindit.Forexample,ifyoumisspellavariablename,you’llsee
somethinglikeFigure7-6withapointertowhereyoumadeyourmistake.
Figure7-6.AJavaScripterrorintheChromeconsole
Ifyouclickhangman.html:30,you’llseetheexactlinewheretheerroris.Inthiscase,it’sshowingus
thatwemisspelledremainingLettersasremainingLetteratthestartofthewhileloop.
Tryplayingthegameafewtimes.Doesitworkthewayyouexpectedittowork?Canyouimaginethe
codeyouwroterunninginthebackgroundasyouplayit?
WhatYouLearned
Injustafewpages,you’vecreatedyourfirstJavaScriptgame!Asyoucansee,loopsandconditionals
areessentialforcreatinggamesoranyotherinteractivecomputerprogram.Withoutthesecontrol
structures,aprogramjustbeginsandends.
InChapter8,we’llusefunctionstopackageupcodesoyoucanrunitfromdifferentpartsofyour
programs.
ProgrammingChallenges
HerearesomechallengestobuildonandimprovetheHangmangameyoucreatedinthischapter.
#1:MOREWORDS
Addyourownwordstothewordsarray.Remembertoenterwordsinalllowercase.
#2:CAPITALLETTERS
Ifaplayerguessesacapitalletter,itwon’tmatchalowercaseletterinthesecretword.Toaddressthis
potentialproblem,converttheplayer’sguesstolowercase.(Hint:YoucanusethetoLowerCasemethod
toconvertastringtolowercase.)
#3:LIMITINGGUESSES
OurHangmangamegivesaplayerunlimitedguesses.Addavariabletotrackthenumberofguesses
andendthegameiftheplayerrunsoutofguesses.(Hint:Checkthisvariableinthesamewhileloop
thatcheckswhetherremainingLetters>0.AswedidinChapter2,youcanuse&&tocheckwhether
twoBooleanconditionsaretrue.)
#4:FIXINGABUG
There’sabuginthegame:ifyoukeepguessingthesamecorrectletter,remainingLetterswillkeep
decrementing.Canyoufixit?(Hint:Youcouldaddanotherconditiontocheckwhetheravaluein
answerArrayisstillanunderscore.Ifit’snotanunderscore,thenthatlettermusthavebeenguessed
already.)
Chapter8.Functions
Afunctionisawaytobundlecodesothatitcanbereused.Functionsallowustorunthesamepieceof
codefrommultipleplacesinaprogramwithouthavingtocopyandpastethecoderepeatedly.Also,by
hidinglongbitsofcodeinafunctionandgivingitaneasy-to-understandname,you’llbebetterableto
planoutyourcodebecauseyoucanfocusonorganizingyourfunctionsratherthanallofthelittlecode
detailsthatmakethemup.Splittingupyourcodeintosmaller,moremanageablepiecesallowsyouto
seethebiggerpictureandthinkabouthowyourprogramsarestructuredatahigherlevel.
You’llfindfunctionsreallyusefulwhenyouneedtorepeatedlyperformacalculationoraction
throughoutaprogram.Earlierinthebook,youusedvariousfunctionssuchasMath.random,
Math.floor,alert,prompt,andconfirm.Inthischapter,you’lllearnhowtocreateyourown
functions.
TheBasicAnatomyofaFunction
Figure8-1showshowafunctionisbuilt.Thecodebetweenthecurlybracketsiscalledthefunction
body,justasthecodebetweenthecurlybracketsinaloopiscalledtheloopbody.
Figure8-1.Thesyntaxforcreatingafunction
CreatingaSimpleFunction
Let’screateasimplefunctionthatprintsHelloworld!.Enterthefollowingcodeinthebrowser
console.UseSHIFT-ENTERtostarteachnewlinewithoutexecutingthecode.
varourFirstFunction=function(){
console.log("Helloworld!");
};
ThiscodecreatesanewfunctionandsavesitinthevariableourFirstFunction.
CallingaFunction
Torunthecodeinsideafunction(thefunctionbody),weneedtocallthefunction.Tocallafunction,
youenteritsnamefollowedbyapairofopeningandclosingparentheses,asshownhere.
ourFirstFunction();
Helloworld!
CallingourFirstFunctionexecutesthebodyofthefunction,whichisconsole.log("Hello
world!");,andthetextweaskedtobeprintedisdisplayedonthenextline:Helloworld!.
Butifyoucallthisfunctioninyourbrowser,you’llnoticethatthere’sathirdline,withalittleleftfacingarrow,asshowninFigure8-2.Thisisthereturnvalueofthefunction.
Figure8-2.Callingafunctionwithanundefinedreturnvalue
Areturnvalueisthevaluethatafunctionoutputs,whichcanthenbeusedelsewhereinyourcode.In
thiscase,thereturnvalueisundefinedbecausewedidn’ttellthefunctiontoreturnanyparticularvalue
inthebodyofthefunction.Allwedidwasaskittoprintamessagetotheconsole,whichisnotthe
sameasreturningavalue.Afunctionalwaysreturnsundefinedunlessthereissomethinginthe
functionbodythattellsittoreturnadifferentvalue.(We’lllookathowtospecifyareturnvaluein
ReturningValuesfromFunctions.)
NOTE
IntheChromeconsoleandinthecodelistingsthroughoutthisbook,returnvaluesarealwayscolor-codedbasedondatatype,while
textprintedwithconsole.logisalwaysplainblack.
PassingArgumentsintoFunctions
ourFirstFunctionjustprintsthesamelineoftexteverytimeyoucallit,butyou’llprobablywant
yourfunctionstobemoreflexiblethanthat.Functionargumentsallowustopassvaluesintoafunction
inordertochangethefunction’sbehaviorwhenit’scalled.Argumentsalwaysgobetweenthefunction
parentheses,bothwhenyoucreatethefunctionandwhenyoucallit.
ThefollowingsayHelloTofunctionusesanargument(name)tosayhellotosomeoneyouspecify.
varsayHelloTo=function(name){
console.log("Hello"+name+"!");
};
WecreatethefunctioninthefirstlineandassignittothevariablesayHelloTo.Whenthefunctionis
called,itlogsthestring"Hello"+name+"!",replacingnamewithwhatevervalueyoupasstothe
functionasanargument.
Figure8-3showsthesyntaxforafunctionwithoneargument.
Figure8-3.Thesyntaxforcreatingafunctionwithoneargument
Tocallafunctionthattakesanargument,placethevalueyou’dliketousefortheargumentbetweenthe
parenthesesfollowingthefunctionname.Forexample,tosayhellotoNick,youwouldwrite:
sayHelloTo("Nick");
HelloNick!
Or,tosayhellotoLyra,write:
sayHelloTo("Lyra");
HelloLyra!
Eachtimewecallthefunction,theargumentwepassinfornameisincludedinthestringprintedbythe
function.Sowhenwepassin"Nick",theconsoleprints"HelloNick!",andwhenwepassin"Lyra",
itprints"HelloLyra!".
PrintingCatFaces!
Onereasontopassanargumentintoafunctionmightbetotellithowmanytimestodosomething.For
example,thefunctiondrawCatsprintscatfaces(likethis:=^.^=)totheconsole.Wetellthefunction
howmanycatstoprintusingtheargumenthowManyTimes:
vardrawCats=function(howManyTimes){
for(vari=0;i<howManyTimes;i++){
console.log(i+"=^.^=");
}
};
ThebodyofthefunctionisaforloopthatloopsasmanytimesasthehowManyTimesargumenttellsit
to(sincethevariableistartsat0andrepeatsuntilitincrementstohowManyTimesminus1).Eachtime
throughtheloop,thefunctionlogsthestringi+"=^.^=".
Here’swhathappenswhenwecallthisfunctionwiththeargument5forhowManyTimes:
drawCats(5);
0=^.^=
1=^.^=
2=^.^=
3=^.^=
4=^.^=
TryitoutwithhowManyTimesequalto100toprint100catfaces!
PassingMultipleArgumentstoaFunction
Youcanpassmorethanonevalueintoafunctionusingmultiplearguments.Toaddanotherargument,
entertheargumentsbetweentheparenthesesafterthefunctionkeyword,separatingthembycommas.
Figure8-4showsthesyntaxforafunctionwithtwoarguments.
Figure8-4.Thesyntaxforcreatingafunctionwithtwoarguments
Thefollowingfunction,printMultipleTimes,islikedrawCatsexceptthatithasasecondargument
calledwhatToDraw.
varprintMultipleTimes=function(howManyTimes,whatToDraw){
for(vari=0;i<howManyTimes;i++){
console.log(i+""+whatToDraw);
}
};
TheprintMultipleTimesfunctionprintsthestringyouenterforwhatToDrawasmanytimesasyou
specifywiththeargumenthowManyTimes.Thesecondargumenttellsthefunctionwhattoprint,andthe
firstargumenttellsthefunctionhowmanytimestoprintit.
Whencallingafunctionwithmultiplearguments,insertthevaluesyouwishtousebetweenthe
parenthesesfollowingthefunctionname,separatedbycommas.
Forexample,toprintoutcatfacesusingthisnewprintMultipleTimesfunction,you’dcallitlikethis:
printMultipleTimes(5,"=^.^=");
0=^.^=
1=^.^=
2=^.^=
3=^.^=
4=^.^=
TohaveprintMultipleTimesprintahappyfacefourtimes,youcoulddothis:
printMultipleTimes(4,"^_^");
0^_^
1^_^
2^_^
3^_^
WhenwecallprintMultipleTimes,wepassinthearguments4forhowManyTimesand"^_^"for
whatToDraw.Asaresult,theforlooploopsfourtimes(withiincrementingfrom0to3),printingi+
""+"^_^"eachtime.
Todrawthecharacter(>_<)twotimes,youcouldwrite:
printMultipleTimes(2,"(>_<)");
0(>_<)
1(>_<)
Inthiscase,wepassin2forhowManyTimesand"(>_<)"forwhatToDraw.
ReturningValuesfromFunctions
Thefunctionswe’velookedatsofarhaveallprintedtexttotheconsoleusingconsole.log.That’san
easyandusefulwaytomakeJavaScriptdisplayvalues,butwhenwelogavaluetotheconsole,we
aren’tabletousethatvaluelaterintheprogram.Whatifyouwantyourfunctiontooutputthatvalueso
thatyoucankeepusingitinotherpartsofyourcode?
Asmentionedearlierinthischapter,theoutputofafunctioniscalledthereturnvalue.Whenyoucalla
functionthatreturnsavalue,youcanusethatvalueintherestofyourcode(youcouldsaveareturn
valueinavariable,passittoanotherfunction,orsimplycombineitwithothercode).Forexample,the
followinglineofcodeadds5tothereturnvalueofthecalltoMath.floor(1.2345):
5+Math.floor(1.2345);
6
Math.floorisafunctionthatreturnsthenumberyoupasstoit,roundeddowntothenearestwhole
number.WhenyouseeafunctioncalllikeMath.floor(1.2345),imaginereplacingitwiththereturn
valueofthatfunctioncall,whichisthenumber1.
Let’screateafunctionthatreturnsavalue.Thefunctiondoubletakestheargumentnumberandreturns
theresultofnumber*2.Inotherwords,thevaluereturnedbythisfunctionistwicethenumber
suppliedasitsargument.
vardouble=function(number){
➊returnnumber*2;
};
Toreturnavaluefromafunction,usethekeywordreturn,followedbythevalueyouwanttoreturn.
At➊,weusethereturnkeywordtoreturnthevaluenumber*2fromthedoublefunction.
Nowwecancallourdoublefunctiontodoublenumbers:
double(3);
6
Here,thereturnvalue(6)isshownonthesecondline.Eventhoughfunctionscantakemultiple
arguments,theycanreturnonlyonevalue.Ifyoudon’ttellthefunctiontoreturnanything,itwillreturn
undefined.
UsingFunctionCallsasValues
Whenyoucallafunctionfromwithinalargerpieceofcode,thefunction’sreturnvalueisused
whereverthatfunctioncallwasplaced.Forexample,let’suseourdoublefunctiontodeterminethe
resultofdoublingtwonumbersandthenaddingtheresults:
double(5)+double(6);
22
Inthisexample,wecallthedoublefunctiontwiceandaddthetworeturnvaluestogether.Youcan
thinkofthecalldouble(5)asthevalue10andthecalldouble(6)asthevalue12.
Youcanalsopassafunctioncallintoanotherfunctionasanargument,andthefunctioncallwillbe
substitutedwithitsreturnvalue.Inthisnextexamplewecalldouble,passingtheresultofcalling
doublewith3asanargument.Wereplacedouble(3)with6sothatdouble(double(3))simplifiesto
double(6),whichthensimplifiesto12.
double(double(3));
12
Here’showJavaScriptcalculatesthis:
Thebodyofthedoublefunctionreturnsnumber*2,soat➊wereplacedouble(3)with3*2.At➋
wereplace3*2with6.Thenat➌,wedothesamethingandreplacedouble(6)with6*2.Finally,
at➍,wecanreplace6*2with12.
UsingFunctionstoSimplifyCode
InChapter3,weusedthemethodsMath.randomandMath.floortopickrandomwordsfromarrays
andgeneraterandominsults.Inthissection,we’llre-createourinsultgeneratorandsimplifyitby
creatingfunctions.
AFunctiontoPickaRandomWord
HereisthecodeweusedinChapter3tochoosearandomwordfromanarray:
randomWords[Math.floor(Math.random()*randomWords.length)];
Ifweturnthiscodeintoafunction,wecanreuseittopickarandomwordfromanarraywithouthaving
toenterthesamecodeeachtime.Forexample,here’showwecoulddefineapickRandomWord
function.
varpickRandomWord=function(words){
returnwords[Math.floor(Math.random()*words.length)];
};
Allwe’redoinghereiswrappingthepreviouscodeinafunction.Now,wecancreatethisrandomWords
array...
varrandomWords=["Planet","Worm","Flower","Computer"];
andpickarandomwordfromthisarrayusingthepickRandomWordfunction,likethis:
pickRandomWord(randomWords);
"Flower"
Wecanusethissamefunctiononanyarray.Forexample,here’showwewouldpickarandomname
fromanarrayofnames:
pickRandomWord(["Charlie","Raj","Nicole","Kate","Sandy"]);
"Raj"
ARandomInsultGenerator
Nowlet’stryre-creatingourrandominsultgenerator,usingourfunctionthatpicksrandomwords.First,
here’sareminderofwhatthecodefromChapter3lookedlike:
varrandomBodyParts=["Face","Nose","Hair"];
varrandomAdjectives=["Smelly","Boring","Stupid"];
varrandomWords=["Fly","Marmot","Stick","Monkey","Rat"];
//PickarandombodypartfromtherandomBodyPartsarray:
varrandomBodyPart=randomBodyParts[Math.floor(Math.random()*3)];
//PickarandomadjectivefromtherandomAdjectivesarray:
varrandomAdjective=randomAdjectives[Math.floor(Math.random()*3)];
//PickarandomwordfromtherandomWordsarray:
varrandomWord=randomWords[Math.floor(Math.random()*5)];
//Joinalltherandomstringsintoasentence:
varrandomString="Your"+randomBodyPart+"islikea"+
randomAdjective+""+randomWord+"!!!";
randomString;
"YourNoseislikeaStupidMarmot!!!"
Noticethatweenduprepeatingwords[Math.floor(Math.random()*length)]quiteafewtimesin
thiscode.UsingourpickRandomWordfunction,wecouldrewritetheprogramlikethis:
varrandomBodyParts=["Face","Nose","Hair"];
varrandomAdjectives=["Smelly","Boring","Stupid"];
varrandomWords=["Fly","Marmot","Stick","Monkey","Rat"];
//Joinalltherandomstringsintoasentence:
varrandomString="Your"+pickRandomWord(randomBodyParts)+
"islikea"+pickRandomWord(randomAdjectives)+
""+pickRandomWord(randomWords)+"!!!";
randomString;
"YourNoseislikeaSmellyMarmot!!!"
Therearetwochangeshere.First,weusethepickRandomWordfunctionwhenweneedarandomword
fromanarray,insteadofusingwords[Math.floor(Math.random()*length)]eachtime.Also,
insteadofsavingeachrandomwordinavariablebeforeaddingittothefinalstring,we’readdingthe
returnvaluesfromthefunctioncallsdirectlytogethertoformthestring.Acalltoafunctioncanbe
treatedasthevaluethatthefunctionreturns.Soreally,allwe’redoinghereisaddingtogetherstrings.
Asyoucansee,thisversionoftheprogramisaloteasiertoread,anditwaseasiertowritetoo,since
wereusedsomecodebyusingafunction.
MakingtheRandomInsultGeneratorintoaFunction
Wecantakeourrandominsultgeneratoronestepfurtherbycreatingalargerfunctionthatproduces
randominsults.Let’stakealook:
generateRandomInsult=function(){
varrandomBodyParts=["Face","Nose","Hair"];
varrandomAdjectives=["Smelly","Boring","Stupid"];
varrandomWords=["Fly","Marmot","Stick","Monkey","Rat"];
//Joinalltherandomstringsintoasentence:
varrandomString="Your"+pickRandomWord(randomBodyParts)+
"islikea"+pickRandomWord(randomAdjectives)+
""+pickRandomWord(randomWords)+"!!!";
➊returnrandomString;
};
generateRandomInsult();
"YourFaceislikeaSmellyStick!!!"
generateRandomInsult();
"YourHairislikeaBoringStick!!!"
generateRandomInsult();
"YourFaceislikeaStupidFly!!!"
OurnewgenerateRandomInsultfunctionisjustthecodefrombeforeplacedinsideafunctionwithno
arguments.Theonlyadditionisat➊,wherewehavethefunctionreturnrandomStringattheend.You
canseeafewsamplerunsoftheprecedingfunction,anditreturnsanewinsultstringeachtime.
Havingthecodeinonefunctionmeanswecankeepcallingthatfunctiontogetarandominsult,instead
ofhavingtocopyandpastethesamecodeeverytimewewantanewinsult.
LeavingaFunctionEarlywithreturn
AssoonastheJavaScriptinterpreterreachesreturninafunction,itleavesthefunction,evenifmore
coderemainsinthefunctionbody.
Onecommonwaytousereturnistoleaveafunctionearlyifanyoftheargumentstothefunctionare
invalid;thatis,ifthey’renotthekindofargumentsthefunctionneedsinordertorunproperly.For
example,thefollowingfunctionreturnsastringtellingyouthefifthcharacterofyourname.Ifthename
passedtothefunctionhasfewerthanfivecharacters,thefunctionusesreturntoleavethefunction
immediately.Thismeansthereturnstatementattheend,whichtellsyouthefifthletterofyourname,
isneverexecuted.
varfifthLetter=function(name){
➊if(name.length<5){
➋return;
}
return"Thefifthletterofyournameis"+name[4]+".";
};
At➊wechecktoseewhetherthelengthoftheinputnameislessthanfive.Ifitis,weusereturnat➋
toexitthefunctionearly.
Let’strycallingthisfunction.
fifthLetter("Nicholas");
"Thefifthletterofyournameiso."
ThenameNicholasislongerthanfivecharacters,sofifthLettercompletesandreturnsthefifthletter
inthenameNicholas,whichisthelettero.Let’strycallingitagainonashortername:
fifthLetter("Nick");
undefined
WhenwecallfifthLetterwiththenameNick,thefunctionknowsthatthenameisn’tlongenough,so
itexitsearlywiththefirstreturnstatementat➋.Becausethereisnovaluespecifiedafterthereturn
at➋,thefunctionreturnsundefined.
UsingreturnMultipleTimesInsteadofif...elseStatements
Wecanusemultiplereturnkeywordsinsidedifferentifstatementsinafunctionbodytohavea
functionreturnadifferentvaluedependingontheinput.Forexample,sayyou’rewritingagamethat
awardsplayersmedalsbasedontheirscore.Ascoreof3orbelowisabronzemedal,scoresbetween3
and7aresilver,andanythingabove7isgold.YoucoulduseafunctionlikemedalForScoretoevaluate
ascoreandreturntherightkindofmedal,asshownhere:
varmedalForScore=function(score){
if(score<3){
➊return"Bronze";
}
➋if(score<7){
return"Silver";
}
➌return"Gold";
};
At➊wereturn"Bronze"andexitthefunctionifthescoreislessthan3.Ifwereach➋weknowthat
scoremustbeatleast3,becauseifitwaslessthan3,wewouldhavereturnedalready(thatis,we
wouldhaveexitedthefunctionwhenwereachedthereturnkeywordinthefirsttest).Finally,ifwe
reach➌,weknowthatscoremustbeatleast7,sothere’snothinglefttocheck,andwecanjustreturn
"Gold".
Althoughwe’recheckingmultipleconditions,wedon’tneedtousechainedif...elsestatements.We
useif...elsestatementstoensurethatonlyoneoftheoptionsisexecuted.Wheneachoftheoptions
hasitsownreturnstatement,thisalsoensuresthatonlyoneoftheoptionswillbeexecuted(because
functionscanreturnonlyonce).
SHORTHANDFORCREATINGFUNCTIONS
There’salonghandwayandashorthandwaytowritefunctions.I’musingthelonghandwaybecauseitshowsmoreclearlyhowa
functionisstoredasavariable.Still,youshouldknowwhattheshorthandlookslikebecauselotsofJavaScriptcodeusesit.Once
you’reusedtohowfunctionswork,youmightwanttousetheshorthandversion,too.
Here’sanexampleofalonghandfunction:
vardouble=function(number){
returnnumber*2;
};
Theshorthandversionlookslikethis:
functiondouble(number){
returnnumber*2;
}
Asyoucansee,inthelonghandversion,weexplicitlycreateavariablenameandassignthefunctiontothevariable,sodoubleappears
beforethefunctionkeyword.Bycontrast,thefunctionkeywordappearsfirstintheshorthandversion,followedbythefunctionname.
Inthisversion,thevariabledoubleiscreatedbyJavaScriptbehindthescenes.
Intechnicalterms,thelonghandversionisknownasafunctionexpression.Theshorthandversionisknownasafunctiondeclaration.
WhatYouLearned
Functionsallowustoreuseblocksofcode.Theycandodifferentthingsdependingonthearguments
passedtothem,andtheycanreturnvaluestothelocationinthecodewherethefunctionwascalled.
Functionsalsomakeitpossibletogiveapieceofcodeameaningfulname.Forexample,thenameof
thefunctionpickRandomWordmakesclearthatthefunctionhassomethingtodowithpickingarandom
word.
Inthenextchapter,we’lllearnhowtowriteJavaScriptthatcanmanipulateHTMLdocuments.
ProgrammingChallenges
Herearesomechallengesforyoutopracticeworkingwithfunctions.
#1:DOINGARITHMETICWITHFUNCTIONS
Createtwofunctions,addandmultiply.Eachshouldtaketwoarguments.Theaddfunctionshould
sumitsargumentsandreturntheresult,andmultiplyshouldmultiplyitsarguments.
Usingonlythesetwofunctions,solvethissimplemathematicalproblem:
36325*9824+777
#2:ARETHESEARRAYSTHESAME?
WriteafunctioncalledareArraysSamethattakestwoarraysofnumbersasarguments.Itshouldreturn
trueifthetwoarraysarethesame(thatis,theyhavethesamenumbersinthesameorder)andfalseif
they’redifferent.Tryrunningthefollowingcodetomakesureyourfunctionsareworkingcorrectly:
areArraysSame([1,2,3],[4,5,6]);
false
areArraysSame([1,2,3],[1,2,3]);
true
areArraysSame([1,2,3],[1,2,3,4]);
false
Hint1:you’llneedtouseaforlooptogothrougheachofthevaluesinthefirstarraytoseewhether
they’rethesameinthesecondarray.Youcanreturnfalseintheforloopifyoufindavaluethat’snot
equal.
Hint2:youcanleavethefunctionearlyandskiptheforloopaltogetherifthearraysaredifferent
lengths.
#3:HANGMAN,USINGFUNCTIONS
GobacktoyourHangmangamefromChapter7.We’regoingtorewriteitusingfunctions.
I’verewrittenthefinalHangmancodehere,butwithcertainpartsofthecodereplacedbyfunctioncalls.
Allyouneedtodoiswritethefunctions!
//Writeyourfunctionshere
varword=pickWord();
varanswerArray=setupAnswerArray(word);
varremainingLetters=word.length;
while(remainingLetters>0){
showPlayerProgress(answerArray);
varguess=getGuess();
if(guess===null){
break;
}elseif(guess.length!==1){
alert("Pleaseenterasingleletter.");
}else{
varcorrectGuesses=updateGameState(guess,word,answerArray);
remainingLetters-=correctGuesses;
}
}
showAnswerAndCongratulatePlayer(answerArray);
ThisversionofthecodeusingfunctionsisalmostassimpleasthepseudocodeversionfromChapter7.
Thisshouldgiveyousomeideaofhowusefulfunctionscanbeformakingcodeeasiertounderstand.
Herearethefunctionsyouneedtofillin:
varpickWord=function(){
//Returnarandomword
};
varsetupAnswerArray=function(word){
//Returntheanswerarray
};
varshowPlayerProgress=function(answerArray){
//Usealerttoshowtheplayertheirprogress
};
vargetGuess=function(){
//Useprompttogetaguess
};
varupdateGameState=function(guess,word,answerArray){
//UpdateanswerArrayandreturnanumbershowinghowmany
//timestheguessappearsinthewordsoremainingLetters
//canbeupdated
};
varshowAnswerAndCongratulatePlayer=function(answerArray){
//Usealerttoshowtheanswerandcongratulatetheplayer
};
PartII.AdvancedJavaScript
Chapter9.TheDOMandjQuery
Sofar,we’vebeenusingJavaScripttodorelativelysimplethingslikeprinttexttothebrowserconsole
ordisplayanalertorpromptdialog.ButyoucanalsouseJavaScripttomanipulate(controlormodify)
andinteractwiththeHTMLyouwriteinwebpages.Inthischapter,we’lldiscusstwotoolsthatwill
allowyoutowritemuchmorepowerfulJavaScript:theDOMandjQuery.
TheDOM,ordocumentobjectmodel,iswhatallowsJavaScripttoaccessthecontentofawebpage.
WebbrowsersusetheDOMtokeeptrackoftheelementsonapage(suchasparagraphs,headings,and
otherHTMLelements),andJavaScriptcanmanipulateDOMelementsinvariousways.Forexample,
you’llsoonseehowyoucanuseJavaScripttoreplacethemainheadingoftheHTMLdocumentwith
inputfromapromptdialog.
We’llalsolookatausefultoolcalledjQuery,whichmakesitmucheasiertoworkwiththeDOM.
jQuerygivesusasetoffunctionsthatwecanusetochoosewhichelementstoworkwithandtomake
changestothoseelements.
Inthischapter,we’lllearnhowtousetheDOMandjQuerytoeditexistingDOMelementsandcreate
newDOMelements,givingusfullcontroloverthecontentofourwebpagesfromJavaScript.We’ll
alsolearnhowtousejQuerytoanimateDOMelements—forexample,fadingelementsinandout.
SelectingDOMElements
WhenyouloadanHTMLdocumentintoabrowser,thebrowserconvertstheelementsintoatree-like
structure.ThistreeisknownastheDOMtree.Figure9-1showsasimpleDOMtree—thesametree
weusedinChapter5toillustratethehierarchyofHTML.ThebrowsergivesJavaScriptprogrammersa
waytoaccessandmodifythistreestructureusingacollectionofmethodscalledtheDOM.
Figure9-1.TheDOMtreeforasimpleHTMLdocument,liketheonewemadeinChapter5
UsingidtoIdentifyElements
TheHTMLidattributeletsyouassignauniquename,oridentifier,toanHTMLelement.Forexample,
thish1elementhasanidattribute:
<h1id="main-heading">Helloworld!</h1>
Inthisexample,theidof"main-heading"willletusidentify,andeventuallychange,thisparticular
headingwithoutaffectingotherelementsorevenotherh1headings.
SelectinganElementUsinggetElementById
Havinguniquelyidentifiedanelementwithid(eachidmusthaveauniquevalue),wecanusethe
DOMmethoddocument.getElementByIdtoreturnthe"main-heading"element:
varheadingElement=document.getElementById("main-heading");
Bycallingdocument.getElementById("main-heading"),wetellthebrowsertolookfortheelement
withtheidof"main-heading".ThiscallreturnsaDOMobjectthatcorrespondstotheid,andwesave
thisDOMobjecttothevariableheadingElement.
Oncewe’veselectedanelement,wecanmanipulateitwithJavaScript.Forexample,wecanusethe
innerHTMLpropertytoretrieveandreplacethetextinsidetheselectedelement:
headingElement.innerHTML;
ThiscodereturnstheHTMLcontentsofheadingElement—theelementweselectedusing
getElementById.Inthiscase,thecontentofthiselementisthetextHelloworld!thatweentered
betweenthe<h1>tags.
ReplacingtheHeadingTextUsingtheDOM
Here’sanexampleofhowtoreplaceheadingtextusingtheDOM.First,wecreateanewHTML
documentcalleddom.htmlcontainingthiscode:
<!DOCTYPEhtml>
<html>
<head>
<title>PlayingwiththeDOM</title>
</head>
<body>
<h1id="main-heading">Helloworld!</h1>
<script>
➊varheadingElement=document.getElementById("main-heading");
➋console.log(headingElement.innerHTML);
➌varnewHeadingText=prompt("Pleaseprovideanewheading:");
➍headingElement.innerHTML=newHeadingText;
</script>
</body>
</html>
At➊weusedocument.getElementByIdtogettheh1element(withtheidof"main-heading")and
saveitintothevariableheadingElement.At➋weprintthestringreturnedby
headingElement.innerHTML,whichprintsHelloworld!totheconsole.At➌weuseapromptdialog
toasktheuserforanewheadingandsavethetexttheuserentersinthevariablenewHeadingText.
Finally,at➍wesettheinnerHTMLpropertyofheadingElementtothetextsavedinnewHeadingText.
Whenyouloadthispage,youshouldseeapromptdialogliketheoneshowninFigure9-2.
Figure9-2.Ourpagewiththedialogopen
EnterthetextJAVASCRIPTISAWESOMEintothedialogandclickOK.Theheadingshouldupdate
instantlywiththenewtext,asshowninFigure9-3.
Figure9-3.Ourpageaftertheheadingchange
UsingtheinnerHTMLproperty,wecanchangethecontentofanyDOMelementusingJavaScript.
UsingjQuerytoWorkwiththeDOMTree
Thebuilt-inDOMmethodsaregreat,butthey’renotveryeasytouse.Becauseofthis,manydevelopers
useasetoftoolscalledjQuerytoaccessandmanipulatetheDOMtree.jQueryisaJavaScriptlibrary
—acollectionofrelatedtools(mostlyfunctions)thatgivesus,inthiscase,asimplerwaytoworkwith
DOMelements.Onceweloadalibraryontoourpage,wecanuseitsfunctionsandmethodsinaddition
tothosebuiltintoJavaScriptandthoseprovidedbythebrowser.
LoadingjQueryonYourHTMLPage
TousethejQuerylibrary,wefirsttellthebrowsertoloaditwiththislineofHTML:
<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
Noticethatthe<script>tagherehasnocontents,andithasasrcattribute.Thesrcattributeletsus
insertaJavaScriptfileintoourpagebyincludingitsURL(webaddress).Inthiscase,
https://code.jquery.com/jquery-2.1.0.jsistheURLforaspecificversionofjQuery(version2.1.0)onthe
jQuerywebsite.
ToseethejQuerylibrary,visitthatURL;you’llseetheJavaScriptthatwillbeloadedwhenthis
<script>tagisadded.Theentirelibraryisover9,000linesofcomplicatedJavaScript,though,sodon’t
expecttounderstanditallrightnow!
ReplacingtheHeadingTextUsingjQuery
InReplacingtheHeadingTextUsingtheDOM,youlearnedhowtoreplacetextusingthebuilt-inDOM
methods.Inthissection,we’llupdatethatcodetousejQuerytoreplacetheheadingtextinstead.Open
dom.htmlandmakethechangesshown.
<!DOCTYPEhtml>
<html>
<head>
<title>PlayingwiththeDOM</title>
</head>
<body>
<h1id="main-heading">Helloworld!</h1>
➊<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
varnewHeadingText=prompt("Pleaseprovideanewheading:");
➋$("#main-heading").text(newHeadingText);
</script>
</body>
</html>
At➊weaddanew<script>tagtothepagetoloadjQuery.WithjQueryloaded,weusethejQuery
function$toselectanHTMLelement.
The$functiontakesoneargument,calledaselectorstring,whichtellsjQuerywhichelementor
elementstoselectfromtheDOMtree.Inthiscase,weentered"#main-heading"astheargument.The
#characterinaselectorstringmeans“ID,”soourselectorstring"#main-heading"means“theelement
withanidofmain-heading.”
The$functionreturnsajQueryobjectthatrepresentstheelementsyouselected.Forexample,
$("#main-heading")returnsajQueryobjectfortheh1element(whichhasanidof"mainheading").
WenowhaveajQueryobjectrepresentingtheh1element.Wecanmodifyitstextbycallingthetext
methodonthejQueryobjectat➋,passinginthenewtextforthatelement,andreplacingthetextofthe
headingwiththeuserinputsavedtothevariablenewHeadingText.Asbefore,whenyouloadthispage,
adialogshouldpromptyoutoenterreplacementtextfortheoldtextintheh1element.
CreatingNewElementswithjQuery
InadditiontomanipulatingelementswithjQuery,wecanalsousejQuerytocreatenewelementsand
addthemtotheDOMtree.Todoso,wecallappendonajQueryobjectwithastringcontainingHTML.
TheappendmethodconvertsthestringtoaDOMelement(usingtheHTMLtagsinthestring)andadds
thenewelementtotheendoftheoriginalone.
Forexample,toaddapelementtotheendofthepage,wecouldaddthistoourJavaScript:
$("body").append("<p>Thisisanewparagraph</p>");
Thefirstpartofthisstatementusesthe$functionwiththeselectorstring"body"toselectthebodyof
ourHTMLdocument.Theselectorstringdoesn’thavetobeanid.Thecode$("body")selectsthe
bodyelement.Likewise,wecouldusethecode$("p")toselectallthepelements.
Next,wecalltheappendmethodontheobjectreturnedby$("body").Thestringpassedtoappendis
turnedintoaDOMelement,anditisaddedinsidethebodyelement,justbeforetheclosingtag.
Figure9-4showswhatourrevisedpagewouldlooklike.
Figure9-4.Ourdocumentwithanewelement
Wecouldalsouseappendtoaddmultipleelementsinaforlooplikethis:
for(vari=0;i<3;i++){
varhobby=prompt("Tellmeoneofyourhobbies!");
$("body").append("<p>"+hobby+"</p>");
}
Thisloopsthreetimes.Eachtimethroughaloop,apromptappears,askinguserstoenteroneoftheir
hobbies.Eachhobbyisthenputinsideasetof<p>tagsandpassedtotheappendmethod,whichadds
thehobbytotheendofthebodyelement.Tryaddingthiscodetoyourdom.htmldocument,andthen
loaditinabrowsertotestit.ItshouldlooklikeFigure9-5.
Figure9-5.Extraelementsaddedinaloop
AnimatingElementswithjQuery
Lotsofwebsitesuseanimationstoshowandhidecontent.Forexample,ifyouwereaddinganew
paragraphoftexttoyourpage,youmightwanttofadeitinslowlysoitdoesn’tappearallofasudden.
jQuerymakesiteasytoanimateelements.Forexample,tofadeanelementout,wecanusethefadeOut
method.Totestthismethod,replacethecontentsofthesecondscriptelementindom.htmlwiththis:
$("h1").fadeOut(3000);
Weusethe$functiontoselectallh1elements.Becausedom.htmlhasonlyoneh1element(theheading
containingthetextHelloworld!),thatheadingisselectedasajQueryobject.Bycalling
.fadeOut(3000)onthisjQueryobject,wemaketheheadingfadeawayuntilitdisappears,overthe
courseof3seconds.(TheargumenttofadeOutisinmilliseconds,orthousandthsofasecond,so
entering3000makestheanimationlast3seconds.)
Assoonasyouloadthepagewiththiscode,theh1elementshouldstarttofadeaway.
ChainingjQueryAnimations
WhenyoucallamethodonajQueryobject,themethodusuallyreturnstheoriginalobjectthatitwas
calledon.Forexample,$("h1")returnsajQueryobjectrepresentingallh1elements,and
$("h1").fadeOut(3000)returnsthesamejQueryobjectrepresentingallh1elements.Tochangethe
textoftheh1elementandfadeitout,youcouldenter:
$("h1").text("Thiswillfadeout").fadeOut(3000);
Callingmultiplemethodsinarowlikethisisknownaschaining.
Wecanchainmultipleanimationsonthesameelement.Forexample,here’showwecouldchainacall
tothefadeOutandfadeInmethodstofadeanelementoutandthenimmediatelyfadeitinagain:
$("h1").fadeOut(3000).fadeIn(2000);
ThefadeInanimationmakesaninvisibleelementfadebackin.jQueryissmartenoughtoknowthat
whenyouchaintwoanimationsinarowlikethis,youprobablywantthemtohappenoneafterthe
other.Therefore,thiscodefadestheh1elementoutoverthecourseof3secondsandthenfadesitback
inover2seconds.
jQueryprovidestwoadditionalanimationmethodssimilartofadeOutandfadeIn,calledslideUpand
slideDown.TheslideUpmethodmakeselementsdisappearbyslidingthemup,andslideDownmakes
themreappearbyslidingthemdown.Replacethesecondscriptelementinthedom.htmldocument
withthefollowing,andreloadthepagetotryitout:
$("h1").slideUp(1000).slideDown(1000);
Hereweselecttheh1element,slideitupover1second,andthenslideitdownover1seconduntilit
reappears.
TRYITOUT!
WeusefadeIntomakeinvisibleelementsvisible.ButwhathappensifyoucallfadeInonanelementthat’salreadyvisibleoran
elementthatcomesaftertheelementyou’reanimating?
Forexample,sayyouaddanewpelementtoyourdom.htmldocumentaftertheheading.TryusingslideUpandslideDowntohideand
showtheh1element,andseewhathappenstothepelement.WhatifyouusefadeOutandfadeIn?
WhathappensifyoucallfadeOutandfadeInonthesameelementwithoutchainingthecalls?Forexample:
$("h1").fadeOut(1000);
$("h1").fadeIn(1000);
Tryaddingtheprecedingcodeinsideaforloopsettorunfivetimes.Whathappens?
WhatdoyouthinktheshowandhidejQuerymethodsdo?Trythemouttoseeifyou’reright.Howcouldyouusehidetofadeinan
elementthat’salreadyvisible?
WhatYouLearned
Inthischapter,youlearnedhowtoupdateHTMLpagesusingJavaScriptbymanipulatingDOM
elements.Asyou’veseen,jQuerygivesusevenmorepowerfulwaystoselectelementsandchangeor
evenanimatethem.YoualsolearnedanewHTMLattribute,id,whichallowsyoutogiveanelementa
uniqueidentifier.
Inthenextchapter,you’lllearnhowtocontrolwhenyourJavaScriptisrun—forexample,onceatimer
hasrunoutorwhenyouclickabutton.We’llalsolookathowtorunthesamepieceofcodemultiple
timeswithatimedelayinbetween—forexample,updatingaclockonceeverysecond.
ProgrammingChallenges
TrythesechallengestopracticemorethingsyoucandowithjQueryandDOMelements.
#1:LISTINGYOURFRIENDSWITHJQUERY(ANDMAKINGTHEMSMELL!)
Createanarraycontainingthenamesofafewfriends.Usingaforloop,createapelementforeachof
yourfriendsandaddittotheendofthebodyelementusingthejQueryappendmethod.UsejQueryto
changetheh1elementsoitsaysMyfriendsinsteadofHelloworld!.Usethehidemethodfollowed
bythefadeInmethodtofadeineachnameasit’sprovided.
Now,modifythepelementsyoucreatedtoaddthetextsmells!aftereachfriend.Hint:Ifyouselect
thepelementsusing$("p"),theappendmethodwillapplytoallthepelements.
#2:MAKINGAHEADINGFLASH
HowcouldyouusefadeOutandfadeIntocausetheheadingtoflashfivetimes,onceasecond?How
couldyoudothisusingaforloop?Trymodifyingyourloopsoitfadesoutandfadesinover1second
thefirsttime,over2secondsthesecondtime,over3secondsthethirdtime,andsoon.
#3:DELAYINGANIMATIONS
Thedelaymethodcanbeusedtodelayanimations.Usingdelay,fadeOut,andfadeIn,makean
elementonyourpagefadeoutandthenfadebackinagainafter5seconds.
#4:USINGFADETO
TryusingthefadeTomethod.Itsfirstargumentisanumberofmilliseconds,asinalltheother
animationmethods.Itssecondargumentisanumberbetween0and1.Whathappenswhenyourunthe
followingcode?
$("h1").fadeTo(2000,0.5);
Whatdoyouthinkthesecondargumentmeans?Tryusingdifferentvaluesbetween0and1tofigureout
whatthesecondargumentisusedfor.
Chapter10.InteractiveProgramming
Untilnow,theJavaScriptcodeonourwebpageshasrunassoonasthepageisloaded,pausingonlyif
weincludeacalltoafunctionlikealertorconfirm.Butwedon’talwaysnecessarilywantallofour
codetorunassoonasthepageloads—whatifwewantsomecodetorunafteradelayorinresponse
tosomethingtheuserdoes?
Inthischapter,we’lllookatdifferentwaysofmodifyingwhenourcodeisrun.Programminginthis
wayiscalledinteractiveprogramming.Thiswillletuscreateinteractivewebpagesthatchangeover
timeandrespondtoactionsbytheuser.
DelayingCodewithsetTimeout
InsteadofhavingJavaScriptexecuteafunctionimmediately,youcantellittoexecuteafunctionaftera
certainperiodoftime.Delayingafunctionlikethisiscalledsettingatimeout.Tosetatimeoutin
JavaScript,weusethefunctionsetTimeout.Thisfunctiontakestwoarguments(asshowninFigure101):thefunctiontocallafterthetimehaselapsedandtheamountoftimetowait(inmilliseconds).
Figure10-1.TheargumentsforsetTimeout
ThefollowinglistingshowshowwecouldusesetTimeouttodisplayanalertdialog.
➊vartimeUp=function(){
alert("Time'sup!");
};
➋setTimeout(timeUp,3000);
1
At➊wecreatethefunctiontimeUp,whichopensanalertdialogthatdisplaysthetext"Time'sup!".
At➋wecallsetTimeoutwithtwoarguments:thefunctionwewanttocall(timeUp)andthenumberof
milliseconds(3000)towaitbeforecallingthatfunction.We’reessentiallysaying,“Wait3secondsand
thencalltimeUp.”WhensetTimeout(timeUp,3000)isfirstcalled,nothinghappens,butafter3
secondstimeUpiscalledandthealertdialogpopsup.
NoticethatcallingsetTimeoutreturns1.ThisreturnvalueiscalledthetimeoutID.ThetimeoutIDisa
numberthat’susedtoidentifythisparticulartimeout(thatis,thisparticulardelayedfunctioncall).The
actualnumberreturnedcouldbeanynumber,sinceit’sjustanidentifier.CallsetTimeoutagain,andit
shouldreturnadifferenttimeoutID,asshownhere:
setTimeout(timeUp,5000);
2
YoucanusethistimeoutIDwiththeclearTimeoutfunctiontocancelthatspecifictimeout.We’lllook
atthatnext.
CancelingaTimeout
Onceyou’vecalledsetTimeouttosetupadelayedfunctioncall,youmayfindthatyoudon’tactually
wanttocallthatfunctionafterall.Forexample,ifyousetanalarmtoremindyoutodoyourhomework,
butyouendupdoingyourhomeworkearly,you’dwanttocancelthatalarm.Tocancelatimeout,use
thefunctionclearTimeoutonthetimeoutIDreturnedbysetTimeout.Forexample,saywecreatea
“doyourhomework”alarmlikethis:
vardoHomeworkAlarm=function(){
alert("Hey!Youneedtodoyourhomework!");
};
➊vartimeoutId=setTimeout(doHomeworkAlarm,60000);
ThefunctiondoHomeworkAlarmpopsupanalertdialogtellingyoutodoyourhomework.Whenwecall
setTimeout(doHomeworkAlarm,60000)we’retellingJavaScripttoexecutethatfunctionafter60,000
milliseconds(or60seconds)haspassed.At➊wemakethiscalltosetTimeoutandsavethetimeout
IDinanewvariablecalledtimeoutId.
Tocancelthetimeout,passthetimeoutIDtotheclearTimeoutfunctionlikethis:
clearTimeout(timeoutId);
NowsetTimeoutwon’tcallthedoHomeworkAlarmfunctionafterall.
CallingCodeMultipleTimeswithsetInterval
ThesetIntervalfunctionislikesetTimeout,exceptthatitrepeatedlycallsthesuppliedfunctionafter
regularpauses,orintervals.Forexample,ifyouwantedtoupdateaclockdisplayusingJavaScript,you
couldusesetIntervaltocallanupdatefunctioneverysecond.YoucallsetIntervalwithtwo
arguments:thefunctionyouwanttocallandthelengthoftheinterval(inmilliseconds),asshownin
Figure10-2.
Figure10-2.TheargumentsforsetInterval
Here’showwecouldwriteamessagetotheconsoleeverysecond:
➊varcounter=1;
➋varprintMessage=function(){
console.log("Youhavebeenstaringatyourconsolefor"+counter
+"seconds");
➌counter++;
};
➍varintervalId=setInterval(printMessage,1000);
Youhavebeenstaringatyourconsolefor1seconds
Youhavebeenstaringatyourconsolefor2seconds
Youhavebeenstaringatyourconsolefor3seconds
Youhavebeenstaringatyourconsolefor4seconds
Youhavebeenstaringatyourconsolefor5seconds
Youhavebeenstaringatyourconsolefor6seconds
➎clearInterval(intervalId);
At➊wecreateanewvariablecalledcounterandsetitto1.We’llbeusingthisvariabletokeeptrack
ofthenumberofsecondsyou’vebeenlookingatyourconsole.
At➋wecreateafunctioncalledprintMessage.Thisfunctiondoestwothings.First,itprintsouta
messagetellingyouhowlongyouhavebeenstaringatyourconsole.Then,at➌,itincrementsthe
countervariable.
Next,at➍,wecallsetInterval,passingtheprintMessagefunctionandthenumber1000.Calling
setIntervallikethismeans“callprintMessageevery1,000milliseconds.”JustassetTimeout
returnsatimeoutID,setIntervalreturnsanintervalID,whichwesaveinthevariableintervalId.
WecanusethisintervalIDtotellJavaScripttostopexecutingtheprintMessagefunction.Thisiswhat
wedoat➎,usingtheclearIntervalfunction.
TRYITOUT!
Modifytheprecedingexampletoprintthemessageeveryfivesecondsinsteadofeverysecond.
AnimatingElementswithsetInterval
Asitturnsout,wecanusesetIntervaltoanimateelementsinabrowser.Basically,weneedtocreate
afunctionthatmovesanelementbyasmallamount,andthenpassthatfunctiontosetIntervalwitha
shortintervaltime.Ifwemakethemovementssmallenoughandtheintervalshortenough,the
animationwilllookverysmooth.
Let’sanimatethepositionofsometextinanHTMLdocumentbymovingthetexthorizontallyinthe
browserwindow.Createadocumentcalledinteractive.html,andfillitwiththisHTML:
<!DOCTYPEhtml>
<html>
<head>
<title>Interactiveprogramming</title>
</head>
<body>
<h1id="heading">Helloworld!</h1>
<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
//We'llfillthisinnext
</script>
</body>
</html>
Nowlet’slookattheJavaScript.Asalways,putyourcodeinsidethe<script>tagsoftheHTML
document.
➊varleftOffset=0;
➋varmoveHeading=function(){
➌$("#heading").offset({left:leftOffset});
➍leftOffset++;
➎if(leftOffset>200){
leftOffset=0;
}
};
➏setInterval(moveHeading,30);
Whenyouopenthispage,youshouldseetheheadingelementgraduallymoveacrossthescreenuntilit
travels200pixels;atthatpoint,itwilljumpbacktothebeginningandstartagain.Let’sseehowthis
works.
At➊wecreatethevariableleftOffset,whichwe’lluselatertopositionourHelloworld!heading.
Itstartswithavalueof0,whichmeanstheheadingwillstartonthefarleftsideofthepage.
Next,at➋,wecreatethefunctionmoveHeading,whichwe’llcalllaterwithsetInterval.Insidethe
moveHeadingfunction,at➌,weuse$("#heading")toselecttheelementwiththeidof"heading"
(ourh1element)andusetheoffsetmethodtosettheleftoffsetoftheheading—thatis,howfaritis
fromtheleftsideofthescreen.
Theoffsetmethodtakesanobjectthatcancontainaleftproperty,whichsetstheleftoffsetofthe
element,oratopproperty,whichsetsthetopoffsetoftheelement.Inthisexampleweusetheleft
propertyandsetittoourleftOffsetvariable.Ifwewantedastaticoffset(thatis,anoffsetthatdoesn’t
change),wecouldsetthepropertytoanumericvalue.Forexample,calling$("#heading")
.offset({left:100})wouldplacetheheadingelement100pixelsfromtheleftsideofthepage.
At➍weincrementtheleftOffsetvariableby1.Tomakesuretheheadingdoesn’tmovetoofar,at➎
wechecktoseeifleftOffsetisgreaterthan200,andifitis,weresetitto0.Finally,at➏wecall
setInterval,andforitsargumentswepassinthefunctionmoveHeadingandthenumber30(for30
milliseconds).
ThiscodecallsthemoveHeadingfunctionevery30milliseconds,orabout33timeseverysecond.Each
timemoveHeadingiscalled,theleftOffsetvariableisincremented,andthevalueofthisvariableis
usedtosetthepositionoftheheadingelement.Becausethefunctionisconstantlybeingcalledand
leftOffsetisincrementedby1eachtime,theheadinggraduallymovesacrossthescreenby1pixel
every30milliseconds.
TRYITOUT!
YoucanspeedupthisanimationbyraisingtheamountthatleftOffsetisincreasedeverytimemoveHeadingiscalledorbyreducingthe
timethatsetIntervalwaitsbetweencallstomoveHeading.
Howwouldyoudoublethespeedthattheheadingmoves?Tryitwithbothtechniques.Whatdifferencedoyousee?
RespondingtoUserActions
Asyou’veseen,onewaytocontrolwhencodeisruniswiththefunctionssetTimeoutand
setInterval,whichrunafunctiononceafixedamountoftimehaspassed.Anotherwayistoruncode
onlywhenauserperformscertainactions,suchasclicking,typing,orevenjustmovingthemouse.This
willletusersinteractwithyourwebpagesothatyourpagerespondsaccordingtowhattheydo.
Inabrowser,everytimeyouperformanactionsuchasclicking,typing,ormovingyourmouse,
somethingcalledaneventistriggered.Aneventisthebrowser’swayofsaying,“Thisthinghappened!”
Youcanlistentotheseeventsbyaddinganeventhandlertotheelementwheretheeventhappened.
AddinganeventhandlerisyourwayoftellingJavaScript,“Ifthiseventhappensonthiselement,call
thisfunction.”Forexample,ifyouwantafunctiontobecalledwhentheuserclicksaheadingelement,
youcouldaddaclickeventhandlertotheheadingelement.We’lllookathowtodothatnext.
RespondingtoClicks
Whenauserclicksanelementinthebrowser,thistriggersaclickevent.jQuerymakesiteasytoadda
handlerforaclickevent.Opentheinteractive.htmldocumentyoucreatedearlier,useFile▸SaveAsto
saveitasclicks.html,andreplaceitssecondscriptelementwiththiscode:
➊varclickHandler=function(event){
➋console.log("Click!"+event.pageX+""+event.pageY);
};
➌$("h1").click(clickHandler);
At➊wecreatethefunctionclickHandlerwiththesingleargumentevent.Whenthisfunctionis
called,theeventargumentwillbeanobjectholdinginformationabouttheclickevent,suchasthe
locationoftheclick.At➋,insidethehandlerfunction,weuseconsole.logtooutputtheproperties
pageXandpageYfromtheeventobject.Thesepropertiestellustheevent’sx-andy-coordinates—in
otherwords,theysaywhereonthepagetheclickoccurred.
Finally,at➌weactivatetheclickhandler.Thecode$("h1")selectstheh1element,andcalling
$("h1").click(clickHandler)means“Whenthereisaclickontheh1element,callthe
clickHandlerfunctionandpassittheeventobject.”Inthiscase,theclickhandlerretrieves
informationfromtheeventobjecttooutputthex-andy-coordinatesoftheclicklocation.
Reloadyourmodifiedpageinyourbrowserandclicktheheadingelement.Eachtimeyouclickthe
heading,anewlineshouldbeoutputtotheconsole,asshowninthefollowinglisting.Eachlineshows
twonumbers:thex-andy-coordinatesoftheclickedlocation.
Click!8843
Click!6353
Click!2453
Click!12146
Click!9355
Click!10348
BROWSERCOORDINATES
Inthewebbrowserandinmostprogrammingandgraphicsenvironments,the0positionofthex-andy-coordinatesisatthetop-left
cornerofthescreen.Asthex-coordinateincreases,youmoverightacrossthepage,andasthey-coordinateincreases,youmovedown
thepage(seeFigure10-3).
Figure10-3.Coordinatesinthebrowser,showingaclickatthecoordinate(3,2)
ThemousemoveEvent
Themousemoveeventistriggeredeverytimethemousemoves.Totryitout,createafilecalled
mousemove.htmlandenterthiscode:
<!DOCTYPEhtml>
<html>
<head>
<title>Mousemove</title>
</head>
<body>
<h1id="heading">Helloworld!</h1>
<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
➊$("html").mousemove(function(event){
➋$("#heading").offset({
left:event.pageX,
top:event.pageY
});
});
</script>
</body>
</html>
At➊weaddahandlerforthemousemoveeventusing$("html").mousemove(handler).Inthiscase,
thehandleristheentirefunctionthatappearsaftermousemoveandbefore</script>.Weuse
$("html")toselectthehtmlelementsothatthehandleristriggeredbymousemovementsthatoccur
anywhereonthepage.Thefunctionthatwepassintotheparenthesesaftermousemovewillbecalled
everytimetheusermovesthemouse.
Inthisexample,insteadofcreatingtheeventhandlerseparatelyandpassingthefunctionnametothe
mousemovemethod(aswedidwithourclickHandlerfunctionearlier),we’repassingthehandler
functiondirectlytothemousemovemethod.Thisisaverycommonwayofwritingeventhandlers,so
it’sgoodtobefamiliarwiththistypeofsyntax.
At➋,insidetheeventhandlerfunction,weselecttheheadingelementandcalltheoffsetmethodon
it.AsImentionedbefore,theobjectpassedtooffsetcanhaveleftandtopproperties.Inthiscase,
wesettheleftpropertytoevent.pageXandthetoppropertytoevent.pageY.Now,everytimethe
mousemoves,theheadingwillmovetothatlocation.Inotherwords,whereveryoumovethemouse,
theheadingfollowsit!
WhatYouLearned
Inthischapter,youlearnedhowtowriteJavaScriptthatrunsonlywhenyouwantitto.The
setTimeoutandsetIntervalfunctionsaregreatfortimingcodetorunafteradelayoratcertain
intervals.Ifyouwanttoruncodewhentheuserdoessomethinginthebrowser,youcanuseeventslike
clickandmousemove,buttherearemanyothers.
Inthenextchapter,we’llputwhatyou’vejustlearnedtogoodusetomakeagame!
ProgrammingChallenges
Hereareafewchallengestoexploremorewaystouseinteractiveprogramming.
#1:FOLLOWTHECLICKS
Modifythepreviousmousemoveprogramsothatinsteadoffollowingyourmouse,theheadingwill
followjustyourclicks.Wheneveryouclickthepage,theheadingshouldmovetotheclicklocation.
#2:CREATEYOUROWNANIMATION
UsesetIntervaltoanimateanh1headingelementaroundthepage,inasquare.Itshouldmove200
pixelstotheright,200pixelsdown,200pixelstotheleft,200pixelsup,andthenstartagain.Hint:
You’llneedtokeeptrackofyourcurrentdirection(right,down,left,orup)sothatyouknowwhetherto
increaseordecreasetheleftortopoffsetoftheheading.You’llalsoneedtochangethedirectionwhen
youreachacornerofthesquare.
#3:CancelanAnimationwithaClick
BuildinguponChallenge#2,addaclickhandlertothemovingh1elementthatcancelstheanimation.
Hint:YoucancancelintervalswiththeclearIntervalfunction.
#4:MAKEA“CLICKTHEHEADER”GAME!
ModifyChallenge#3sothateverytimeaplayerclickstheheading,insteadofstopping,theheading
speedsup,makingitharderandhardertoclick.Keeptrackofthenumberoftimestheheadinghasbeen
clickedandupdatetheheadingtextsoitshowsthisnumber.Whentheplayerhasreached10clicks,
stoptheanimationandchangethetextoftheheadingto“YouWin.”Hint:Tospeedup,you’llhaveto
cancelthecurrentintervalandthenstartanewonewithashorterintervaltime.
Chapter11.FindtheBuriedTreasure!
Let’sputwhatwe’velearnedsofartogooduseandmakeagame!Theaimofthisgameistofindthe
hiddentreasure.Inthisgame,thewebpagewilldisplayatreasuremap.Insidethatmap,theprogram
willpickasinglepixellocation,whichrepresentswherethehiddentreasureisburied.Everytimethe
playerclicksthemap,thewebpagewilltellthemhowclosetothetreasuretheyare.Whentheyclick
thelocationofthetreasure(orveryclosetoit),thegamecongratulatesthemonfindingthetreasureand
sayshowmanyclicksittooktofindit.Figure11-1showswhatthegamewilllooklikeafteraplayer
clicksthemap.
Figure11-1.Theburiedtreasuregame
DesigningtheGame
Beforewestartwritingthecode,let’sbreakdowntheoverallstructureofthisgame.Hereisalistof
stepsweneedtotaketosetupthegamesoitcanrespondaccordinglywhenaplayerclicksthetreasure
map.
1. Createawebpagewithanimage(thetreasuremap)andaplacetodisplaymessagestotheplayer.
2. Pickarandomspotonthemappicturetohidethetreasure.
3. Createaclickhandler.Eachtimetheplayerclicksthemap,theclickhandlerwilldothefollowing:
a. Add1toaclickcounter.
b. Calculatehowfartheclicklocationisfromthetreasurelocation.
c. Displayamessageonthewebpagetotelltheplayerwhetherthey’rehotorcold.
d. Congratulatetheplayeriftheyclickonthetreasureorveryclosetoit,andsayhowmany
clicksittooktofindthetreasure.
I’llshowyouhowtoimplementeachofthesefeaturesinthegame,andthenwe’llgothroughthefull
code.
CreatingtheWebPagewithHTML
Let’slookattheHTMLforthegame.We’lluseanewelementcalledimgforthetreasuremapandadd
apelementwherewecandisplaymessagestotheplayer.Enterthefollowingcodeintoanewfilecalled
treasure.html.
<!DOCTYPEhtml>
<html>
<head>
<title>Findtheburiedtreasure!</title>
</head>
<body>
<h1id="heading">Findtheburiedtreasure!</h1>
➊<imgid="map"width=400height=400
➋src="http://nostarch.com/images/treasuremap.png">
➌<pid="distance"></p>
<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
//Gamecodegoeshere
</script>
</body>
</html>
TheimgelementisusedtoincludeimagesinHTMLdocuments.UnliketheotherHTMLelements
we’velookedat,imgdoesn’tuseaclosingtag.Allyouneedisanopeningtag,which,likeotherHTML
tags,cancontainvariousattributes.At➊we’veaddedanimgelementwithanidof"map".Wesetthe
widthandheightofthiselementusingthewidthandheightattributes,whicharebothsetto400.This
meansourimagewillbe400pixelstalland400pixelswide.
Totellthedocumentwhichimagewewanttodisplay,weusethesrcattributetoincludetheweb
addressoftheimageat➋.Inthiscase,we’relinkingtoanimagecalledtreasuremap.pngontheNo
StarchPresswebsite.
Followingtheimgelementisanemptypelementat➌,whichwegiveanidof"distance".We’lladd
texttothiselementbyusingJavaScripttotelltheplayerhowclosetheyaretothetreasure.
PickingaRandomTreasureLocation
Nowlet’sbuildtheJavaScriptforourgame.Firstweneedtopickarandomlocationforthehidden
treasureinsidethetreasuremapimage.Sincethedimensionsofthemapare400by400pixels,the
coordinatesofthetop-leftpixelwillbe{x:0,y:0},andthebottom-rightpixelwillbe{x:399,
y:399}.
PickingRandomNumbers
Tosetarandomcoordinatepointwithinthetreasuremap,wepickarandomnumberbetween0and399
forthexvalueandarandomnumberbetween0and399fortheyvalue.Togeneratetheserandom
values,we’llwriteafunctionthattakesasizeargumentasinputandpicksarandomnumberfrom0up
to(butnotincluding)size:
vargetRandomNumber=function(size){
returnMath.floor(Math.random()*size);
};
Thiscodeissimilartothecodewe’veusedtopickrandomwordsinearlierchapters.Wegeneratea
randomnumberbetween0and1usingMath.random,multiplythatbythesizeargument,andthenuse
Math.floortoroundthatnumberdowntoawholenumber.Thenweoutputtheresultasthereturn
valueofthefunction.CallinggetRandomNumber(400)willreturnarandomnumberfrom0to399,
whichisjustwhatweneed!
SettingtheTreasureCoordinates
Nowlet’susethegetRandomNumberfunctiontosetthetreasurecoordinates:
➊varwidth=400;
varheight=400;
➋vartarget={
x:getRandomNumber(width),
y:getRandomNumber(height)
};
Thesectionofcodeat➊setsthewidthandheightvariables,whichrepresentthewidthandheightof
theimgelementthatwe’reusingasatreasuremap.At➋wecreateanobjectcalledtarget,whichhas
twoproperties,xandy,thatrepresentthecoordinatesoftheburiedtreasure.Thexandypropertiesare
bothsetbygetRandomNumber.Eachtimewerunthiscode,wegetanewrandomlocationonthemap,
andthechosencoordinateswillbesavedinthexandypropertiesofthetargetvariable.
TheClickHandler
Theclickhandleristhefunctionthatwillbecalledwhentheplayerclicksthetreasuremap.Start
buildingthisfunctionwiththiscode:
$("#map").click(function(event){
//Clickhandlercodegoeshere
});
Firstweuse$("#map")toselectthetreasuremaparea(becausetheimgelementhasanidof"map"),
andthenwegointotheclickhandlerfunction.Eachtimetheplayerclicksthemap,thefunctionbody
betweenthecurlybracketswillbeexecuted.Informationabouttheclickispassedintothatfunction
bodyasanobjectthroughtheeventargument.
Thisclickhandlerfunctionneedstodoquiteabitofwork:ithastoincrementtheclickcounter,
calculatehowfareachclickisfromthetreasure,anddisplaymessages.Beforewefillinthecodefor
theclickhandlerfunction,we’lldefinesomevariablesandcreatesomeotherfunctionsthatwillhelp
executeallthesesteps.
CountingClicks
Thefirstthingourclickhandlerneedstodoistrackthetotalnumberofclicks.Tosetthisup,wecreate
avariablecalledclicksatthebeginningoftheprogram(outsidetheclickhandler)andinitializeitto
zero:
varclicks=0;
Insidetheclickhandler,we’llincludeclicks++sothatweincrementclicksby1eachtimetheplayer
clicksthemap.
CalculatingtheDistanceBetweentheClickandtheTreasure
Tofigureoutwhethertheplayerishotorcold(closetothetreasureorfaraway),weneedtomeasure
thedistancebetweenwheretheplayerclickedandthelocationofthehiddentreasure.Todothis,we’ll
writeafunctioncalledgetDistance,likeso:
vargetDistance=function(event,target){
vardiffX=event.offsetX-target.x;
vardiffY=event.offsetY-target.y;
returnMath.sqrt((diffX*diffX)+(diffY*diffY));
};
ThegetDistancefunctiontakestwoobjectsasarguments:eventandtarget.Theeventobjectisthe
objectpassedtotheclickhandler,anditcomeswithlotsofbuilt-ininformationabouttheplayer’sclick.
Inparticular,itcontainstwopropertiescalledoffsetXandoffsetY,whichtellusthex-andycoordinatesoftheclick,andthat’sexactlytheinformationweneed.
Insidethefunction,thevariablediffXstoresthehorizontaldistancebetweentheclickedlocationand
thetarget,whichwecalculatebysubtractingtarget.x(thex-coordinateofthetreasure)from
event.offsetX(thex-coordinateoftheclick).Wecalculatetheverticaldistancebetweenthepointsin
thesameway,andstoretheresultasdiffY.Figure11-2showshowwewouldcalculatediffXand
diffYfortwopoints.
Figure11-2.Calculatingthehorizontalandverticaldistancesbetweeneventandtarget
UsingthePythagoreanTheorem
Next,thegetDistancefunctionusesthePythagoreantheoremtocalculatethedistancebetweentwo
points.ThePythagoreantheoremsaysthatforarighttriangle,whereaandbrepresentthelengthsofthe
twosidesborderingtherightangleandcrepresentsthelengthofthediagonalside(thehypotenuse),a2
+b2=c2.Giventhelengthsofaandb,wecancalculatethelengthofthehypotenusebycalculatingthe
squarerootofa2+b2.
Tocalculatethedistancebetweentheeventandthetarget,wetreatthetwopointsasifthey’repartofa
righttriangle,asshowninFigure11-3.InthegetDistancefunction,diffXisthelengthofthe
horizontaledgeofthetriangle,anddiffYisthelengthoftheverticaledge.
Tocalculatethedistancebetweentheclickandthetreasure,weneedtocalculatethelengthofthe
hypotenuse,basedonthelengthsdiffXanddiffY.AsamplecalculationisshowninFigure11-3.
Figure11-3.Calculatingthehypotenusetofindoutthedistancebetweeneventandtarget
Togetthelengthofthehypotenuse,wefirsthavetosquarediffXanddiffY.Wethenaddthese
squaredvaluestogether,andgetthesquarerootusingtheJavaScriptfunctionMath.sqrt.Soour
completeformulaforcalculatingthedistancebetweentheclickandthetargetlookslikethis:
Math.sqrt((diffX*diffX)+(diffY*diffY))
ThegetDistancefunctioncalculatesthisandreturnstheresult.
TellingthePlayerHowCloseTheyAre
Onceweknowthedistancebetweentheplayer’sclickandthetreasure,wewanttodisplayahinttelling
theplayerhowclosetheyaretothetreasure,withouttellingthemexactlyhowfarawaythetreasureis.
Forthis,weusethegetDistanceHintfunctionshownhere:
vargetDistanceHint=function(distance){
if(distance<10){
return"Boilinghot!";
}elseif(distance<20){
return"Reallyhot";
}elseif(distance<40){
return"Hot";
}elseif(distance<80){
return"Warm";
}elseif(distance<160){
return"Cold";
}elseif(distance<320){
return"Reallycold";
}else{
return"Freezing!";
}
};
Thisfunctionreturnsdifferentstringsdependingonthecalculateddistancefromthetreasure.Ifthe
distanceislessthan10,thefunctionreturnsthestring"Boilinghot!".Ifthedistanceisbetween10
and20,thefunctionreturns"Reallyhot".Thestringsgetcolderasthedistanceincreases,uptothe
pointwherewereturn"Freezing!"ifthedistanceisgreaterthan320pixels.
Wedisplaythemessagetotheplayerbyaddingitastextinthepelementofthewebpage.The
followingcodewillgoinsideourclickhandlertocalculatethedistance,picktheappropriatestring,and
displaythatstringtotheplayer:
vardistance=getDistance(event,target);
vardistanceHint=getDistanceHint(distance);
$("#distance").text(distanceHint);
Asyoucansee,wefirstcallgetDistanceandthensavetheresultasthevariabledistance.Nextwe
passthatdistancetothegetDistanceHintfunctiontopicktheappropriatestringandsaveitas
distanceHint.
Thecode$("#distance").text(distanceHint);selectstheelementwiththeidof"distance"(in
thiscasethepelement)andsetsitstexttodistanceHintsothateachtimetheplayerclicksthemap,
ourwebpagetellsthemhowclosetheyaretothetarget.
CheckingIfthePlayerWon
Finally,ourclickhandlerneedstocheckwhethertheplayerhaswon.Becausepixelsaresosmall,
insteadofmakingtheplayerclicktheexactlocationofthetreasure,we’llletthemwiniftheyclick
within8pixels.
Thiscodechecksthedistancetothetreasureanddisplaysamessagetellingtheplayerthatthey’vewon:
if(distance<8){
alert("Foundthetreasurein"+clicks+"clicks!");
}
Ifthedistanceislessthan8pixels,thiscodeusesalerttotelltheplayertheyfoundthetreasureand
howmanyclicksittookthemtodoso.
PuttingItAllTogether
Nowthatwehaveallthepieces,let’scombinethemtomakeonescript.
//Getarandomnumberfrom0tosize
vargetRandomNumber=function(size){
returnMath.floor(Math.random()*size);
};
//Calculatedistancebetweenclickeventandtarget
vargetDistance=function(event,target){
vardiffX=event.offsetX-target.x;
vardiffY=event.offsetY-target.y;
returnMath.sqrt((diffX*diffX)+(diffY*diffY));
};
//Getastringrepresentingthedistance
vargetDistanceHint=function(distance){
if(distance<10){
return"Boilinghot!";
}elseif(distance<20){
return"Reallyhot";
}elseif(distance<40){
return"Hot";
}elseif(distance<80){
return"Warm";
}elseif(distance<160){
return"Cold";
}elseif(distance<320){
return"Reallycold";
}else{
return"Freezing!";
}
};
//Setupourvariables
➊varwidth=400;
varheight=400;
varclicks=0;
//Createarandomtargetlocation
➋vartarget={
x:getRandomNumber(width),
y:getRandomNumber(height)
};
//Addaclickhandlertotheimgelement
➌$("#map").click(function(event){
clicks++;
//Getdistancebetweenclickeventandtarget
➍vardistance=getDistance(event,target);
//Convertdistancetoahint
➎vardistanceHint=getDistanceHint(distance);
//Updatethe#distanceelementwiththenewhint
➏$("#distance").text(distanceHint);
//Iftheclickwascloseenough,tellthemtheywon
➐if(distance<8){
alert("Foundthetreasurein"+clicks+"clicks!");
}
});
First,wehavethethreefunctionsgetRandomNumber,getDistance,andgetDistanceHint,which
we’vealreadylookedat.Then,at➊,wesetupthevariableswe’llneed:width,height,andclicks.
Afterthat,at➋,wecreatetherandomlocationforthetreasure.
At➌wecreateaclickhandleronthemapelement.Thefirstthingthisdoesisincrementtheclicks
variableby1.Then,at➍,itworksoutthedistancebetweenevent(theclicklocation)andtarget(the
treasurelocation).At➎weusethefunctiongetDistanceHinttoconvertthisdistanceintoastring
representingthedistance("Cold","Warm",andsoon).Weupdatethedisplayat➏sotheusercansee
howfartheyare.Finally,at➐,wechecktoseewhetherthedistanceisunder8,andifso,wetellthe
playerthey’vewonandinhowmanyclicks.
ThisistheentireJavaScriptforourgame.Ifyouaddthistothesecond<script>tagintreasure.html,
youshouldbeabletoplayitinyourbrowser!Howmanyclicksdoesittakeyoutofindthetreasure?
WhatYouLearned
Inthischapter,youusedyournewevent-handlingskillstocreateagame.Youalsolearnedaboutthe
imgelement,whichcanbeusedtoaddimagestoawebpage.Finally,youlearnedhowtomeasurethe
distancebetweentwopointsusingJavaScript.
Inthenextchapter,we’lllearnaboutobject-orientedprogramming,whichwillgiveusmoretoolsfor
organizingourcode.
ProgrammingChallenges
Hereareafewwaysyoucouldchangethegameandaddmorefeatures.
#1:INCREASINGTHEPLAYINGAREA
Youcouldmakethegameharderbyincreasingthesizeoftheplayingarea.Howwouldyoumakeit800
pixelswideby800pixelstall?
#2:ADDINGMOREMESSAGES
Tryaddingsomeextramessagestodisplaytotheplayer(like"Reallyreallycold!"),andmodify
thedistancestomakethegameyourown.
#3:ADDINGACLICKLIMIT
Addalimittothenumberofclicksandshowthemessage"GAMEOVER"iftheplayerexceedsthislimit.
#4:DISPLAYINGTHENUMBEROFREMAININGCLICKS
Showthenumberofremainingclicksasanextrapieceoftextafterthedistancedisplaysotheplayer
knowsifthey’reabouttolose.
Chapter12.Object-OrientedProgramming
Chapter4discussedJavaScriptobjects—collectionsofkeyspairedwithvalues.Inthischapter,we’ll
lookatwaystocreateanduseobjectsasweexploreobject-orientedprogramming.Object-oriented
programmingisawaytodesignandwriteprogramssothatalloftheprogram’simportantpartsare
representedbyobjects.Forexample,whenbuildingaracinggame,youcoulduseobject-oriented
programmingtechniquestorepresenteachcarasanobjectandthencreatemultiplecarobjectsthat
sharethesamepropertiesandfunctionality.
ASimpleObject
InChapter4,youlearnedthatobjectsaremadeupofproperties,whicharesimplypairsofkeysand
values.Forexample,inthefollowingcodetheobjectdogrepresentsadogwiththepropertiesname,
legs,andisAwesome:
vardog={
name:"Pancake",
legs:4,
isAwesome:true
};
Oncewecreateanobject,wecanaccessitspropertiesusingdotnotation(discussedinAccessingValues
inObjects).Forexample,here’showwecouldaccessthenamepropertyofourdogobject:
dog.name;
"Pancake"
WecanalsousedotnotationtoaddpropertiestoaJavaScriptobject,likethis:
dog.age=6;
Thisaddsanewkey-valuepair(age:6)totheobject,asyoucanseebelow:
dog;
Object{name:"Pancake",legs:4,isAwesome:true,age:6}
AddingMethodstoObjects
Intheprecedingexample,wecreatedseveralpropertieswithdifferentkindsofvaluessavedtothem:a
string("Pancake"),numbers(4and6),andaBoolean(true).Inadditiontostrings,numbers,and
Booleans,youcansaveafunctionasapropertyinsideanobject.Whenyousaveafunctionasa
propertyinanobject,thatpropertyiscalledamethod.Infact,we’vealreadyusedseveralbuilt-in
JavaScriptmethods,likethejoinmethodonarraysandthetoUpperCasemethodonstrings.
Nowlet’sseehowtocreateourownmethods.Onewaytoaddamethodtoanobjectiswithdot
notation.Forexample,wecouldaddamethodcalledbarktothedogobjectlikethis:
➊dog.bark=function(){
➋console.log("Woofwoof!Mynameis"+this.name+"!");
};
➌dog.bark();
Woofwoof!MynameisPancake!
At➊weaddapropertytothedogobjectcalledbarkandassignafunctiontoit.At➋,insidethisnew
function,weuseconsole.logtologWoofwoof!MynameisPancake!.Noticethatthefunction
usesthis.name,whichretrievesthevaluesavedintheobject’snameproperty.Let’stakeacloserlook
athowthethiskeywordworks.
UsingthethisKeyword
Youcanusethethiskeywordinsideamethodtorefertotheobjectonwhichthemethodiscurrently
beingcalled.Forexample,whenyoucallthebarkmethodonthedogobject,thisreferstothedog
object,sothis.namereferstodog.name.Thethiskeywordmakesmethodsmoreversatile,allowing
youtoaddthesamemethodtomultipleobjectsandhaveitaccessthepropertiesofwhateverobjectit’s
currentlybeingcalledon.
SharingaMethodBetweenMultipleObjects
Let’screateanewfunctioncalledspeakthatwecanuseasamethodinmultipleobjectsthatrepresent
differentanimals.Whenspeakiscalledonanobject,itwillusetheobject’sname(this.name)andthe
soundtheanimalmakes(this.sound)tologamessage.
varspeak=function(){
console.log(this.sound+"!Mynameis"+this.name+"!");
};
Nowlet’screateanotherobjectsowecanaddspeaktoitasamethod:
varcat={
sound:"Miaow",
name:"Mittens",
➊speak:speak
};
Herewecreateanewobjectcalledcat,withsound,name,andspeakproperties.Wesetthespeak
propertyat➊andassignitthespeakfunctionwecreatedearlier.Nowcat.speakisamethodthatwe
cancallbyenteringcat.speak().Sinceweusedthethiskeywordinthemethod,whenwecalliton
cat,itwillaccessthecatobject’sproperties.Let’sseethatnow:
cat.speak();
Miaow!MynameisMittens!
Whenwecallthecat.speakmethod,itretrievestwopropertiesfromthecatobject:this.sound
(whichis"Miaow")andthis.name(whichis"Mittens").
Wecanusethesamespeakfunctionasamethodinotherobjectstoo:
varpig={
sound:"Oink",
name:"Charlie",
speak:speak
};
varhorse={
sound:"Neigh",
name:"Marie",
speak:speak
};
pig.speak();
Oink!MynameisCharlie!
horse.speak();
Neigh!MynameisMarie!
Again,eachtimethisappearsinsideamethod,itreferstotheobjectonwhichthemethodiscalled.In
otherwords,whenyoucallhorse.speak(),thiswillrefertohorse,andwhenyoucallpig.speak(),
thisreferstopig.
Tosharemethodsbetweenmultipleobjects,youcansimplyaddthemtoeachobject,aswejustdidwith
speak.Butifyouhavelotsofmethodsorobjects,addingthesamemethodstoeachobjectindividually
canbecomeannoying,anditcanmakeyourcodemessier,too.Justimagineifyouneededawholezoo
fullof100animalobjectsandyouwantedeachtoshareasetof10methodsandproperties.
JavaScriptobjectconstructorsofferabetterwaytosharemethodsandpropertiesbetweenobjects,as
we’llseenext.
CreatingObjectsUsingConstructors
AJavaScriptconstructorisafunctionthatcreatesobjectsandgivesthemasetofbuilt-inpropertiesand
methods.Thinkofitasaspecializedmachineforcreatingobjects,kindoflikeafactorythatcanchurn
outtonsofcopiesofthesameitem.Onceyou’vesetupaconstructor,youcanuseittomakeasmanyof
thesameobjectasyouwant.Totryitout,we’llbuildthebeginningsofaracinggame,usingaCar
constructortocreateafleetofcarswithsimilarbasicpropertiesandmethodsforsteeringand
acceleration.
AnatomyoftheConstructor
Eachtimeyoucallaconstructor,itcreatesanobjectandgivesthenewobjectbuilt-inproperties.Tocall
anormalfunction,youenterthefunctionnamefollowedbyapairofparentheses.Tocallaconstructor,
youenterthekeywordnew(whichtellsJavaScriptthatyouwanttouseyourfunctionasaconstructor),
followedbytheconstructornameandparentheses.Figure12-1showsthesyntaxforcallinga
constructor.
Figure12-1.ThesyntaxforcallingaconstructornamedCarwithtwoarguments
NOTE
MostJavaScriptprogrammersstartconstructornameswithacapitallettersoit’seasytoseeataglancethatthey’redifferentfrom
otherfunctions.
CreatingaCarConstructor
Nowlet’screateaCarconstructorthatwilladdanxandypropertytoeachnewobjectitcreates.These
propertieswillbeusedtoseteachcar’sonscreenpositionwhenwedrawit.
CreatingtheHTMLDocument
Beforewecanbuildourconstructor,weneedtocreateanewHTMLdocument.Makeanewfilecalled
cars.htmlandenterthisHTMLintoit:
<!DOCTYPEhtml>
<html>
<head>
<title>Cars</title>
</head>
<body>
<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
//Codegoeshere
</script>
</body>
</html>
TheCarConstructorfunction
Nowaddthiscodetotheempty<script>tagsincars.html(replacingthecomment//Codegoes
here)tocreatetheCarconstructorthatgiveseachcarasetofcoordinates.
<script>
varCar=function(x,y){
this.x=x;
this.y=y;
};
</script>
OurnewconstructorCartakestheargumentsxandy.We’veaddedthepropertiesthis.xandthis.y
tostorethexandyvaluespassedtoCarinournewobject.Thisway,eachtimewecallCarasa
constructor,anewobjectiscreatedwithitsxandypropertiessettotheargumentswespecify.
CallingtheCarConstructor
AsImentionedearlier,thekeywordnewtellsJavaScriptthatwe’recallingaconstructortocreateanew
object.Forexample,tocreateacarobjectnamedtesla,opencars.htmlinawebbrowserandthen
enterthiscodeintheChromeJavaScriptconsole:
vartesla=newCar(10,20);
tesla;
Car{x:10,y:20}
ThecodenewCar(10,20)tellsJavaScripttocreateanobjectusingCarasaconstructor,passinthe
arguments10and20foritsxandyproperties,andreturnthatobject.Weassignthereturnedobjectto
theteslavariablewithvartesla.
Thenwhenweentertesla,theChromeconsolereturnsthenameoftheconstructoranditsxandy
values:Car{x:10,y:20}.
DrawingtheCars
ToshowtheobjectscreatedbytheCarconstructor,we’llcreateafunctioncalleddrawCartoplacean
imageofacarateachcarobject’s(x,y)positioninabrowserwindow.Oncewe’veseenhowthis
functionworks,we’llrewriteitinamoreobject-orientedwayinAddingadrawMethodtotheCar
Prototype.Addthiscodebetweenthe<script>tagsincars.html:
<script>
varCar=function(x,y){
this.x=x;
this.y=y;
};
vardrawCar=function(car){
➊varcarHtml='<imgsrc="http://nostarch.com/images/car.png">';
➋varcarElement=$(carHtml);
➌carElement.css({
position:"absolute",
left:car.x,
top:car.y
});
➍$("body").append(carElement);
};
</script>
At➊wecreateastringcontainingHTMLthatpointstoanimageofacar.(Usingsinglequotestocreate
thisstringletsususedoublequotesintheHTML.)At➋wepasscarHTMLtothe$function,which
convertsitfromastringtoajQueryelement.ThatmeansthecarElementvariablenowholdsajQuery
elementwiththeinformationforour<img>tag,andwecantweakthiselementbeforeaddingittothe
page.
At➌weusethecssmethodoncarElementtosetthepositionofthecarimage.Thiscodesetstheleft
positionoftheimagetothecarobject’sxvalueanditstoppositiontotheyvalue.Inotherwords,the
leftedgeoftheimagewillbexpixelsfromtheleftedgeofthebrowserwindow,andthetopedgeofthe
imagewillbeypixelsdownfromthetopedgeofthewindow.
NOTE
Inthisexample,thecssmethodworksliketheoffsetmethodweusedinChapter10tomoveelementsaroundthepage.Unfortunately,
offsetdoesn’tworkaswellwithmultipleelements,andsincewewanttodrawmultiplecars,we’reusingcsshereinstead.
Finally,at➍weusejQuerytoappendthecarElementtothebodyelementofthewebpage.Thisfinal
stepmakesthecarElementappearonthepage.(Forareminderonhowappendworks,seeCreating
NewElementswithjQuery.)
TestingthedrawCarFunction
Let’stestthedrawCarfunctiontomakesureitworks.Addthiscodetoyourcars.htmlfile(afterthe
otherJavaScriptcode)tocreatetwocars.
$("body").append(carElement);
};
vartesla=newCar(20,20);
varnissan=newCar(100,200);
drawCar(tesla);
drawCar(nissan);
</script>
Here,weusetheCarconstructortocreatetwocarobjects,oneatthecoordinates(20,20)andtheother
at(100,200),andthenweusedrawCartodraweachoftheminthebrowser.Nowwhenyouopen
cars.html,youshouldseetwocarimagesinyourbrowserwindow,asshowninFigure12-2.
Figure12-2.DrawingcarsusingdrawCar
CustomizingObjectswithPrototypes
Amoreobject-orientedwaytodrawourcarswouldbetogiveeachcarobjectadrawmethod.Then,
insteadofwritingdrawCar(tesla),you’dwritetesla.draw().Inobject-orientedprogramming,we
wantobjectstohavetheirownfunctionalitybuiltinasmethods.Inthiscase,thedrawCarfunctionis
alwaysmeanttobeusedoncarobjects,soinsteadofsavingdrawCarasaseparatefunction,weshould
includeitaspartofeachcarobject.
JavaScriptprototypesmakeiteasytosharefunctionality(asmethods)betweendifferentobjects.All
constructorshaveaprototypeproperty,andwecanaddmethodstoit.Anymethodthatweaddtoa
constructor’sprototypepropertywillbeavailableasamethodtoallobjectscreatedbythat
constructor.
Figure12-3showsthesyntaxforaddingamethodtoaprototypeproperty.
Figure12-3.Thesyntaxforaddingamethodtoaprototypeproperty
AddingadrawMethodtotheCarPrototype
Let’saddadrawmethodtoCar.prototypesothatallobjectswecreateusingCarwillhavethedraw
method.UsingFile▸SaveAs,saveyourcars.htmlfileascars2.html.ThenreplacealloftheJavaScript
inyoursecondsetof<script>tagsincars2.htmlwiththiscode:
➊varCar=function(x,y){
this.x=x;
this.y=y;
};
➋Car.prototype.draw=function(){
varcarHtml='<imgsrc="http://nostarch.com/images/car.png">';
➌this.carElement=$(carHtml);
this.carElement.css({
position:"absolute",
➍left:this.x,
top:this.y
});
$("body").append(this.carElement);
};
vartesla=newCar(20,20);
varnissan=newCar(100,200);
tesla.draw();
nissan.draw();
AftercreatingourCarconstructorat➊,weaddanewmethodcalleddrawtoCar.prototypeat➋.
ThismakesthedrawmethodpartofalloftheobjectscreatedbytheCarconstructor.
ThecontentsofthedrawmethodareamodifiedversionofourdrawCarfunction.First,wecreatean
HTMLstringandsaveitascarHTML.At➌wecreateajQueryelementrepresentingthisHTML,but
thistimewesaveitasapropertyoftheobjectbyassigningittothis.carElement.Thenat➍,weuse
this.xandthis.ytosetthecoordinatesofthetop-leftcornerofthecurrentcarimage.(Insidea
constructor,thisreferstothenewobjectcurrentlybeingcreated.)
Whenyourunthiscode,theresultshouldlooklikeFigure12-2.Wehaven’tchangedthecode’s
functionality,onlyitsorganization.Theadvantagetothisapproachisthatthecodefordrawingthecar
ispartofthecar,insteadofaseparatefunction.
AddingamoveRightMethod
Nowlet’saddsomemethodstomovethecarsaround,beginningwithamoveRightmethodtomovethe
car5pixelstotherightofitscurrentposition.Addthefollowingcodeafteryourdefinitionof
Car.prototype.draw:
this.carElement.css({
position:"absolute",
left:this.x,
top:this.y
});
$("body").append(this.carElement);
};
Car.prototype.moveRight=function(){
this.x+=5;
this.carElement.css({
left:this.x,
top:this.y
});
};
WesavethemoveRightmethodinCar.prototypetoshareitwithallobjectscreatedbytheCar
constructor.Withthis.x+=5weadd5tothecar’sxvalue,whichmovesthecar5pixelstotheright.
Thenweusethecssmethodonthis.carElementtoupdatethecar’spositioninthebrowser.
TrythemoveRightmethodinthebrowserconsole.First,refreshcars2.html,andthenopentheconsole
andentertheselines:
tesla.moveRight();
tesla.moveRight();
tesla.moveRight();
Eachtimeyouentertesla.moveRight,thetopcarshouldmove5pixelstotheright.Youcouldusethis
methodinaracinggametoshowthecarmovingdowntheracetrack.
TRYITOUT!
Trymovingnissantotheright.HowmanytimesdoyouneedtocallmoveRightonnissantomakeitlineupwithtesla?
UsesetIntervalandmoveRighttoanimatenissansothatitdrivesacrossthebrowserwindow.
AddingtheLeft,Up,andDownmoveMethods
Nowwe’lladdtheremainingdirectionstoourcodesothatwecanmoveourcarsaroundthescreenin
anydirection.ThesemethodsarebasicallythesameasmoveRight,sowe’llwritethemallatonce.
Addthefollowingmethodstocars2.htmljustafterthecodeformoveRight:
Car.prototype.moveRight=function(){
this.x+=5;
this.carElement.css({
left:this.x,
top:this.y
});
};
Car.prototype.moveLeft=function(){
this.x-=5;
this.carElement.css({
left:this.x,
top:this.y
});
};
Car.prototype.moveUp=function(){
this.y-=5;
this.carElement.css({
left:this.x,
top:this.y
});
};
Car.prototype.moveDown=function(){
this.y+=5;
this.carElement.css({
left:this.x,
top:this.y
});
};
Eachofthesemethodsmovesthecarby5pixelsinthespecifieddirectionbyaddingorsubtracting5
fromeachcar’sxoryvalue.
WhatYouLearned
Inthischapter,youlearnedthebasicsofobject-orientedprogramminginJavaScript,includinghowto
createconstructorstobuildnewobjectsandhowtomodifytheprototypepropertyofthose
constructorstosharemethodsbetweenobjects.
Inobject-orientedprograms,mostfunctionsarewrittenasmethods.Forexample,todrawthecar,we
callthedrawmethodonthecar,andtomovethecartotheright,wecallthemoveRightmethod.
ConstructorsandprototypesareJavaScript’sbuilt-inwayoflettingyoucreateobjectsthatsharethe
samesetofmethods,buttherearemanywaystowriteobject-orientedJavaScript.(FormoreonobjectorientedJavaScript,seeNicholasC.Zakas’sThePrinciplesofObject-OrientedJavaScript[NoStarch
Press,2014].)
WritingJavaScriptinanobject-orientedwaycanhelpyoustructureyourcode.Havingwell-structured
codemeansthatwhenyoucomebacktoitlatertomakechanges,itshouldbeeasiertofigureouthow
yourprogramworksifyoudon’tremember(thisisparticularlyimportantwithbiggerprogramsorwhen
youstarttoworkwithotherprogrammerswhomayneedtoaccessyourcode).Forexample,inthefinal
projectinthisbook,we’llbuildaSnakegamethatrequiresquiteabitofcode,andwe’lluseobjectsand
methodstoorganizeourgameandhandlealotoftheimportantfunctionality.
Inthenextchapter,we’llgooverhowtodrawandanimatelinesandshapesonawebpageusingthe
canvaselement.
ProgrammingChallenges
Trythesechallengestopracticeworkingwithobjectsandprototypes.
#1:DRAWINGINTHECARCONSTRUCTOR
AddacalltothedrawmethodfrominsidetheCarconstructorsothatcarobjectsautomaticallyappear
inthebrowserassoonasyoucreatethem.
#2:ADDINGASPEEDPROPERTY
ModifytheCarconstructortoaddanewspeedpropertywithavalueof5totheconstructedobjects.
Thenusethispropertyinsteadofthevalue5insidethemovementmethods.
Nowtryoutdifferentvaluesforspeedtomakethecarsmovefasterorslower.
#3:RACINGCARS
ModifythemoveLeft,moveRight,moveUp,andmoveDownmethodssotheytakeasingledistance
argument,thenumberofpixelstomove,insteadofalwaysmoving5pixels.Forexample,tomovethe
nissancar10pixelstotheright,youwouldcallnissan.moveRight(10).
Now,usesetIntervaltomovethetwocars(nissanandtesla)totherightevery30millisecondsby
adifferentrandomdistancebetween0and5.Youshouldseethetwocarsanimateacrossthescreen,
jumpingalongatvaryingspeeds.Canyouguesswhichcarwillmakeittotheedgeofthewindowfirst?
PartIII.Canvas
Chapter13.TheCanvasElement
JavaScriptisn’tallaboutplayingwithtextandnumbers.YoucanalsouseJavaScripttodrawpictures
withtheHTMLcanvaselement,whichyoucanthinkofasablankcanvasorsheetofpaper.Youcan
drawalmostanythingthatyouwantonthiscanvas,suchaslines,shapes,andtext.Theonlylimitis
yourimagination!
Inthischapter,you’lllearnthebasicsofdrawingonthecanvas.Inthefollowingchapters,we’llbuild
onourknowledgetocreateacanvas-basedJavaScriptgame.
CreatingaBasicCanvas
Asourfirststepinusingthecanvas,createanewHTMLdocumentforthecanvaselement,asshownin
thefollowinglisting.Savethisdocumentascanvas.html:
<!DOCTYPEhtml>
<html>
<head>
<title>Canvas</title>
</head>
<body>
➊<canvasid="canvas"width="200"height="200"></canvas>
<script>
//We'llfillthisinnext
</script>
</body>
</html>
Asyoucanseeat➊,wecreateacanvaselementandgiveitanidpropertyof"canvas",whichwe’ll
usetoselecttheelementinourcode.Thewidthandheightpropertiessetthedimensionsofthe
canvaselementinpixels.Herewesetbothdimensionsto200.
DrawingontheCanvas
Nowthatwe’vebuiltapagewithacanvaselement,let’sdrawsomerectangleswithJavaScript.Enter
thisJavaScriptbetweenthe<script>tagsincanvas.html.
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.fillRect(0,0,10,10);
We’llgooverthiscodelinebylineinthefollowingsections.
SelectingandSavingthecanvasElement
First,weselectthecanvaselementusingdocument.getElementById("canvas").Aswesawin
Chapter9,thegetElementByIdmethodreturnsaDOMobjectrepresentingtheelementwiththe
suppliedid.Thisobjectisassignedtothecanvasvariablewiththecodevarcanvas=
document.getElementById("canvas").
GettingtheDrawingContext
Next,wegetthedrawingcontextfromthecanvaselement.AdrawingcontextisaJavaScriptobject
thatincludesallthemethodsandpropertiesfordrawingonacanvas.Togetthisobject,wecall
getContextoncanvasandpassitthestring"2d"asanargument.Thisargumentsaysthatwewantto
drawatwo-dimensionalimageonourcanvas.Wesavethisdrawingcontextobjectinthevariablectx
usingthecodevarctx=canvas.getContext("2d").
DrawingaSquare
Finally,onthethirdline,wedrawarectangleonthecanvasbycallingthemethodfillRectonthe
drawingcontext.ThefillRectmethodtakesfourarguments.Inorder,thesearethex-andycoordinatesofthetop-leftcorneroftherectangle(0,0)andthewidthandheightoftherectangle(10,
10).Inthiscase,we’resaying,“Drawa10-pixel-by-10-pixelrectangleatcoordinates(0,0),”whichare
atthetop-leftcornerofthecanvas.
Whenyourunthiscode,youshouldseeasmallblacksquareonyourscreen,asshowninFigure13-1.
Figure13-1.Ourfirstcanvasdrawing
DrawingMultipleSquares
Howabouttryingsomethingabitmoreinteresting?Ratherthandrawingjustonesquare,let’susea
looptodrawmultiplesquaresrunningdiagonallydownthescreen.Replacethecodeinthe<script>
tagswiththefollowing.Whenyourunthiscode,youshouldseeasetofeightblacksquares,asshown
inFigure13-2:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
for(vari=0;i<8;i++){
ctx.fillRect(i*10,i*10,10,10);
}
Thefirsttwolinesarethesameasintheearlierlisting.Inthethirdline,wecreateaforloopthatruns
from0to8.Next,insidethisloop,wecallfillRectonthedrawingcontext.
Figure13-2.Drawingmultiplesquaresusingaforloop
Thexandypositionsforthetop-leftcornerofeachsquarearebasedontheloopvariable,i.Thefirst
timearoundtheloop,wheniis0,thecoordinatesare(0,0)because0×10isequalto0.Thismeans
thatwhenwerunthecodectx.fillRect(i*10,i*10,10,10),wewilldrawasquareatthe
coordinates(0,0),withawidthandheightof10pixelsby10pixels.Thisisthetop-leftsquarein
Figure13-2.
Thesecondtimearoundtheloop,wheniis1,thecoordinatesare(10,10)because1×10isequalto10.
Thistime,thecodectx.fillRect(i*10,i*10,10,10)drawsasquareatthecoordinates(10,
10),butthesquare’ssizeisstill10pixelsby10pixels(becausewe’renotchangingthewidthand
heightarguments).ThisisthesecondsquaredowninFigure13-2.
Sinceiincrementsby1eachtimethroughtheloop,thex-andy-coordinateskeepincreasingby10
pixelseachtimethroughtheloop,butthewidthandheightofthesquarestayfixedat10.Theremaining
sixsquaresaredrawnovertheremainingsixtimesaroundtheloop.
TRYITOUT!
Nowthatyouknowhowtodrawsquaresandrectanglesonthecanvas,trydrawingthislittlerobotusingthefillRectmethod.
Hint:You’llneedtodrawsixseparaterectangles.Imadetheheadusinga50-pixel-by-50-pixelrectangle.Theneck,arms,andlegsare
all10pixelswide.
ChangingtheDrawingColor
Bydefault,whenyoucallfillRect,JavaScriptdrawsablackrectangle.Touseadifferentcolor,you
canchangethefillStylepropertyofthedrawingcontext.WhenyousetfillStyletoanewcolor,
everythingyoudrawwillbedrawninthatcoloruntilyouchangefillStyleagain.
TheeasiestwaytosetacolorforfillStyleistogiveitthenameofacolorasastring.Forexample:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
➊ctx.fillStyle="Red";
ctx.fillRect(0,0,100,100);
At➊wetellthedrawingcontextthateverythingwedrawfromnowonshouldbecoloredred.Running
thiscodeshoulddrawabrightredsquareonthescreen,asshowninFigure13-3.
Figure13-3.Aredsquare
NOTE
JavaScriptunderstandsmorethan100colornames,includingGreen,Blue,Orange,Red,Yellow,Purple,White,Black,Pink,Turquoise,
Violet,SkyBlue,PaleGreen,Lime,Fuchsia,DeepPink,Cyan,andChocolate.You’llfindafulllistontheCSS-Trickswebsite:http://csstricks.com/snippets/css/named-colors-and-hex-equivalents/.
TRYITOUT!
LookattheCSS-Trickswebsite(http://css-tricks.com/snippets/css/named-colors-and-hex-equivalents/)andchoosethreecolorsyou
like.Drawthreerectanglesusingthesecolors.Eachrectangleshouldbe50pixelswideand100pixelstall.Don’tincludeanyspace
betweenthem.Youshouldendupwithsomethinglikethis:
...althoughI’msureyoucanfindsomemoreinterestingcolorsthanred,green,andblue!
DrawingRectangleOutlines
Aswe’veseen,thefillRectmethoddrawsafilled-inrectangle.That’sfineifthat’swhatyouwant,but
sometimesyoumightwanttodrawjusttheoutline,asifyouwereusingapenorpencil.Todrawjust
theoutlineofarectangle,weusethestrokeRectmethod.(Thewordstrokeisanotherwordfor
outline.)Forexample,runningthiscodeshoulddrawtheoutlineofsmallrectangle,asshownin
Figure13-4:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.strokeRect(10,10,100,20);
Figure13-4.UsingstrokeRecttodrawtheoutlineofarectangle
ThestrokeRectmethodtakesthesameargumentsasfillRect:firstthex-andy-coordinatesofthe
top-leftcorner,followedbythewidthandheightoftherectangle.Inthisexample,weseethata
rectangleisdrawnstartingat10pixelsfromthetopleftofthecanvas,anditis100pixelswideby20
pixelstall.
UsethestrokeStylepropertytochangethecoloroftherectangle’soutline.Tochangethethicknessof
theline,usethelineWidthproperty.Forexample:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
➊ctx.strokeStyle="DeepPink";
➋ctx.lineWidth=4;
ctx.strokeRect(10,10,100,20);
Here,wesetthecolorofthelinetoDeepPinkat➊andthewidthofthelineto4pixelsat➋.Figure135showstheresultingrectangle.
Figure13-5.Adeeppinkrectanglewitha4-pixel-wideoutline
DrawingLinesorPaths
Linesonthecanvasarecalledpaths.Todrawapathwiththecanvas,youusex-andy-coordinatestoset
whereeachlineshouldbeginandend.Byusingacarefulcombinationofstartingandstopping
coordinates,youcandrawspecificshapesonthecanvas.Forexample,here’showyoumightdrawthe
turquoiseXshowninFigure13-6:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
➊ctx.strokeStyle="Turquoise";
➋ctx.lineWidth=4;
➌ctx.beginPath();
➍ctx.moveTo(10,10);
➎ctx.lineTo(60,60);
➏ctx.moveTo(60,10);
➐ctx.lineTo(10,60);
➑ctx.stroke();
Figure13-6.AturquoiseX,drawnwithmoveToandlineTo
At➊and➋wesetthecolorandwidthoftheline.At➌wecallthebeginPathmethodonthedrawing
context(savedasctx)totellthecanvasthatwewanttostartdrawinganewpath.At➍wecallthe
moveTomethodwithtwoarguments:x-andy-coordinates.CallingmoveTopicksupourvirtual
JavaScriptpenoffthecanvaspaperandmovesittothosecoordinateswithoutdrawingaline.
Tostartdrawingaline,wecallthelineTomethodat➎withx-andy-coordinates,whichplacesthe
virtualpenbackonthecanvasandtracesapathtothesenewcoordinates.Here,wedrawalinefromthe
point(10,10)tothepoint(60,60)—adiagonallinefromthetopleftofthecanvastothebottomright,
formingthefirstlineoftheX.
At➏wecallmoveToagain,whichsetsanewlocationtodrawfrom.At➐wecalllineToagain,to
drawalinefrom(60,10)to(10,60)—adiagonallinefromthetoprightofthecanvastothebottom
left,completingtheXshape.
Butwe’renotdoneyet!Sofarwe’veonlytoldthecanvaswhatwe’dliketodraw;wehaven’tactually
drawnanything.Soat➑,wecallthestrokemethod,whichfinallymakesthelinesappearonthe
screen.
TRYITOUT!
TrydrawingthishappystickmanusingthebeginPath,moveTo,lineTo,andstrokemethods.YoucanusethestrokeRectmethodfor
thehead.Theheadisa20-pixel-by-20-pixelsquare,andthelinewidthis4pixels.
FillingPaths
Sofarwe’velookedatstrokeRectfordrawingrectangleoutlines,fillRectforfillingrectangleswith
color,andstrokeforoutliningapath.TheequivalentoffillRectforpathsiscalledfill.Tofilla
closedpathwithcolorinsteadofjustdrawinganoutline,youcanusethefillmethodinsteadof
stroke.Forexample,youcouldusethiscodetodrawthesimpleskybluehouseshowninFigure13-7.
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
ctx.fillStyle="SkyBlue";
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(100,60);
ctx.lineTo(130,30);
ctx.lineTo(160,60);
ctx.lineTo(160,100);
ctx.lineTo(100,100);
➊ctx.fill();
Figure13-7.Askybluehouse,drawnwithapathandfilledwiththefillmethod
Here’showthiscodeworks.AftersettingourdrawingcolortoSkyBlue,webeginourpathwith
beginPathandthenmovetoourstartingpointof(100,100)usingmoveTo.NextwecalllineTofive
timesforeachcornerofthehouse,usingfivesetsofcoordinates.ThefinalcalltolineTocompletesthe
pathbygoingbacktothestartingpointof(100,100).
Figure13-8showsthesamehouse,butwitheachcoordinatelabeled.
Figure13-8.ThehousefromFigure13-7withcoordinateslabeled
Finally,at➊wecallthefillmethod,whichfillsourpathwiththechosenfillcolor,SkyBlue.
DrawingArcsandCircles
Inadditiontodrawingstraightlinesonthecanvas,youcanusethearcmethodtodrawarcsandcircles.
Todrawacircle,yousetthecircle’scentercoordinatesandradius(thedistancebetweenthecircle’s
centerandouteredge)andtellJavaScripthowmuchofthecircletodrawbyprovidingastartingangle
andendingangleasarguments.Youcandrawafullcircle,orjustaportionofacircletocreateanarc.
Thestartingandendinganglesaremeasuredinradians.Whenmeasuredinradians,afullcirclestartsat
0(attherightsideofthecircle)andgoesuptoπ×2radians.Sotodrawafullcircle,youtellarcto
drawfrom0radianstoπ×2radians.Figure13-9showsacirclelabeledwithradiansandtheir
equivalentindegrees.Thevalues360°andπ×2radiansbothmeanafullcircle.
Figure13-9.Degreesandradians,startingfromtherightsideofthecircleandmovingclockwise
Forexample,thefollowingcodewillcreateaquartercircle,ahalfcircle,andafullcircle,asshownin
Figure13-10.
ctx.lineWidth=2;
ctx.strokeStyle="Green";
ctx.beginPath();
➊ctx.arc(50,50,20,0,Math.PI/2,false);
ctx.stroke();
ctx.beginPath();
➋ctx.arc(100,50,20,0,Math.PI,false);
ctx.stroke();
ctx.beginPath();
➌ctx.arc(150,50,20,0,Math.PI*2,false);
ctx.stroke();
Figure13-10.Drawingaquartercircle,ahalfcircle,andafullcircle
We’llgooverallthreeshapesinthefollowingsections.
DrawingaQuarterCircleoranArc
Thefirstblockofcodedrawsaquartercircle.At➊,aftercallingbeginPath,wecallthearcmethod.
Wesetthecenterofthecircleatthepoint(50,50)andtheradiusto20pixels.Thestartingangleis0
(whichdrawsthearcstartingfromtherightofthecircle),andtheendingangleisMath.PI/2.
Math.PIishowJavaScriptreferstothenumberπ(pi).Becauseafullcircleisπ×2radians,πradians
meansahalfcircle,andπ÷2radians(whichwe’reusingforthisfirstarc)givesusaquartercircle.
Figure13-11showsthestartandendangles.
Figure13-11.Thestartangle(0radians,or0°)andendangle(π÷2radians,or90°)ofthequarter-circle
Wepassfalseforthefinalargument,whichtellsarctodrawinaclockwisedirection.Ifyouwantto
drawinacounterclockwisedirection,passtrueforthisfinalargument.
DrawingaHalfCircle
Nextwedrawahalfcircle.Thearcat➋hasacenterat(100,50),whichplacesit50pixelstotheright
ofthefirstarc,whichwasat(50,50).Theradiusisagain20pixels.Wealsostartat0radiansagain,but
thistimeweendatMath.PI,drawingahalfcircle.Figure13-12showsthestartandendangles.
Figure13-12.Thestartangle(0radians,or0°)andendangle(πradians,or180°)ofthehalfcircle
DrawingaFullCircle
At➌wedrawafullcircle.Thecenterisat(150,50),andtheradiusis20pixels.Forthiscircle,westart
thearcat0radiansandenditatMath.PI*2radians,drawingafullcircle.Figure13-13showsthe
startandendangles.
Figure13-13.Thestartangle(0radians,or0°)andendangle(π×2radians,or360°)ofthefullcircle
DrawingLotsofCircleswithaFunction
Ifyoujustwanttodrawcircles,thearcmethodisabitcomplicated.Forcircles,you’realwaysgoingto
wanttostartthearcat0andendatπ×2,andthedirection(clockwiseorcounterclockwise)doesn’t
matter.Also,toactuallydrawthecircleyoualwaysneedtocallctx.beginPathandctx.stroke
beforeandaftercallingthearcmethod.Wecanmakeafunctiontodrawcirclesthatletsusignorethose
detailssothatwehavetosupplyonlythex,y,andradiusarguments.Let’sdothatnow.
varcircle=function(x,y,radius){
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
ctx.stroke();
};
Aswiththearcmethod,insidethisfunctionthefirstthingwehavetodoiscallctx.beginPathtotell
thecanvaswewanttodrawapath.Then,wecallctx.arc,passingthex,y,andradiusvariablesfrom
thefunctionarguments.Asbefore,weuse0forthestartangle,Math.PI*2fortheendangle,and
falsetodrawthecircleclockwise.
Nowthatwehavethisfunction,wecandrawlotsofcirclessimplybyfillinginthecentercoordinates
andradiusasarguments.Forexample,thiscodewoulddrawsomecolorfulconcentriccircles:
ctx.lineWidth=4;
ctx.strokeStyle="Red";
circle(100,100,10);
ctx.strokeStyle="Orange";
circle(100,100,20);
ctx.strokeStyle="Yellow";
circle(100,100,30);
ctx.strokeStyle="Green";
circle(100,100,40);
ctx.strokeStyle="Blue";
circle(100,100,50);
ctx.strokeStyle="Purple";
circle(100,100,60);
YoucanseewhatthisshouldlooklikeinFigure13-14.First,wesetthelinewidthtoathick4pixels.
ThenwesetthestrokeStyleto"Red"andusethecirclefunctiontodrawacircleatthecoordinates
(100,100),witharadiusof10pixels.Thisistheredcenterring.
Figure13-14.Colorfulconcentriccircles,drawnusingourcirclefunction
Wethenusethesametechniquetodrawanorangecircleatthesamelocationbutwitharadiusof20
pixels;wefollowthatwithayellowcircle,againinthesamelocationbutwitharadiusof30pixels.The
lastthreecirclesarealsointhesamelocation,butwithincreasinglylargerradiiandingreen,blue,and
purple.
TRYITOUT!
Howwouldyoumodifyourcirclefunctiontomakeitfillthecircleinsteadofoutlineit?Addafourthargument,aBoolean,thatsays
whetherthecircleshouldbefilledoroutlined.Passingtrueindicatesthatyouwantthecircletobefilled.Youcancalltheargument
fillCircle.
Usingyourmodifiedfunction,drawthissnowman,usingamixofoutlinedandfilledcircles.
WhatYouLearned
Inthischapter,youlearnedaboutanewHTMLelementcalledcanvas.Usingthecanvas’sdrawing
context,wecaneasilydrawrectangles,lines,andcircles,withfullcontrolovertheirlocation,line
width,color,andsoon.
Inthenextchapter,we’lllearnhowtoanimateourdrawings,usingsomeofthetechniqueswelearned
inChapter9.
ProgrammingChallenges
Trythesechallengestopracticedrawingtothecanvas.
#1:ASNOWMAN-DRAWINGFUNCTION
Buildingonyourcodefordrawingasnowman(Figure13-14),writeafunctionthatdrawsasnowmanat
aspecifiedlocation,sothatcallingthis...
drawSnowman(50,50);
woulddrawasnowmanatthepoint(50,50).
#2:DRAWINGANARRAYOFPOINTS
Writeafunctionthatwilltakeanarrayofpointslikethis:
varpoints=[[50,50],[50,100],[100,100],[100,50],
[50,50]];
drawPoints(points);
anddrawalineconnectingthepoints.Inthisexample,thefunctionwoulddrawalinefrom(50,50)to
(50,100)to(100,100)to(100,50)andbackto(50,50).
Nowusethisfunctiontodrawthefollowingpoints:
varmysteryPoints=[[50,50],[50,100],[25,120],
[100,50],[70,90],[100,90],[70,120]];
drawPoints(mysteryPoints);
Hint:Youcanusepoints[0][0]togetthefirstx-coordinateandpoints[0][1]togetthefirstycoordinate.
#3:PAINTINGWITHYOURMOUSE
UsingjQueryandthemousemoveevent,drawafilledcirclewitharadiusof3pixelsatthemouse
positionwheneveryoumoveyourmouseoverthecanvas.Becausethiseventistriggeredbyeverytiny
movementofthemouse,thesecircleswilljoinintoalineasyoumovethemouseoverthecanvas.
Hint:RefertoChapter10forareminderofhowtorespondtomousemoveevents.
#4:DRAWINGTHEMANINHANGMAN
InChapter7wecreatedourownversionofthegameHangman.Nowyoucanmakeitclosertothereal
gamebydrawingpartofastickmaneverytimetheplayergetsaletterwrong.
Hint:Keeptrackofthenumberoftimestheplayerhasguessedincorrectly.Writeafunctionthattakes
thisnumberasanargumentanddrawsadifferentpartofthebodydependingonthenumberpassedin.
Chapter14.MakingThingsMoveontheCanvas
CreatingcanvasanimationsinJavaScriptisalotlikecreatingastop-motionanimation.Youdrawa
shape,pause,erasetheshape,andthenredrawitinanewposition.Thismaysoundlikealotofsteps,
butJavaScriptcanupdatethepositionoftheshapeveryquicklyinordertocreateasmoothanimation.
InChapter10,welearnedhowtoanimateDOMelements.Inthischapter,we’llanimateourcanvas
drawings.
MovingAcrossthePage
Let’susecanvasandsetIntervaltodrawasquareandmoveitslowlyacrossapage.Createanew
filecalledcanvasanimation.htmlandaddthefollowingHTML:
<!DOCTYPEhtml>
<html>
<head>
<title>CanvasAnimation</title>
</head>
<body>
<canvasid="canvas"width="200"height="200"></canvas>
<script>
//We'llfillthisinnext
</script>
</body>
</html>
NowaddthefollowingJavaScripttothescriptelement:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
varposition=0;
setInterval(function(){
➊ctx.clearRect(0,0,200,200);
➋ctx.fillRect(position,0,20,20);
➌position++;
➍if(position>200){
position=0;
}
➎},30);
Thefirsttwolinesinthiscodecreatethecanvasandthecontext.Next,wecreatethevariableposition
andsetitto0,withthecodevarposition=0.We’llusethisvariabletocontroltheleft-to-right
movementofthesquare.
NowwecallsetIntervaltostartouranimation.ThefirstargumenttosetIntervalisafunction,
whichdrawsanewsquareeachtimeit’scalled.
ClearingtheCanvas
InsidethefunctionwepassedtosetInterval,wecallclearRectat➊,whichclearsarectangulararea
onthecanvas.TheclearRectmethodtakesfourarguments,whichsetthepositionandsizeofthe
rectangletobecleared.AswithfillRect,thefirsttwoargumentsrepresentthex-andy-coordinatesof
thetop-leftcorneroftherectangle,andthelasttworepresentthewidthandheight.Calling
ctx.clearRect(0,0,200,200)erasesa200-by-200-pixelrectangle,startingattheverytop-left
cornerofthecanvas.Becauseourcanvasisexactly200by200pixels,thiswillcleartheentirecanvas.
DrawingtheRectangle
Oncewe’veclearedthecanvas,at➋weusectx.fillRect(position,0,20,20)todrawa20pixelsquareatthepoint(position,0).Whenourprogramstarts,thesquarewillbedrawnat(0,0)
becausepositionstartsoffsetto0.
ChangingthePosition
Next,weincreasepositionby1,usingposition++at➌.Thenat➍weensurethatpositiondoesn’t
getlargerthan200withthecheckif(position>200).Ifitis,weresetitto0.
ViewingtheAnimationintheBrowser
Whenyouloadthispageinyourbrowser,setIntervalwillcallthesuppliedfunctiononceevery30
milliseconds,orabout33timesasecond(thistimeintervalissetbythesecondargumentto
setInterval,at➎).Eachtimethesuppliedfunctioniscalled,itclearsthecanvas,drawsasquareat
(position,0),andincrementsthevariableposition.Asaresult,thesquaregraduallymovesacross
thecanvas.Whenthesquarereachestheendofthecanvas(200pixelstotheright),itspositionisreset
to0.
Figure14-1showsthefirstfourstepsoftheanimation,zoomedintothetop-leftcornerofthecanvas.
Figure14-1.Aclose-upofthetop-leftcornerofthecanvasforthefirstfourstepsoftheanimation.Ateachstep,positionis
incrementedby1andthesquaremoves1pixeltotheright.
AnimatingtheSizeofaSquare
Bymakingonlythreechangestothecodeintheprevioussection,wecancreateasquarethatgrows
largerinsteadofmoving.Here’swhatthatcodewouldlooklike:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
varsize=0;
setInterval(function(){
ctx.clearRect(0,0,200,200);
ctx.fillRect(0,0,size,size);
size++;
if(size>200){
size=0;
}
},30);
Asyoucansee,we’vedonetwothings.First,insteadofapositionvariable,wenowhaveavariable
namedsize,whichwillcontrolthedimensionsofthesquare.Second,insteadofusingthisvariableto
setthesquare’shorizontalposition,we’reusingittosetthesquare’swidthandheightwiththecode
ctx.fillRect(0,0,size,size).Thiswilldrawasquareatthetop-leftcornerofthecanvas,with
thewidthandheightbothsettomatchsize.Becausesizestartsat0,thesquarewillstartoutinvisible.
Thenexttimethefunctioniscalled,sizewillbe1,sothesquarewillbe1pixelwideandtall.Each
timethesquareisdrawn,itgrowsapixelwiderandapixeltaller.Whenyourunthiscode,youshould
seeasquareappearatthetop-leftcornerofthecanvasandgrowuntilitfillstheentirecanvas.Onceit
fillstheentirecanvas—thatis,if(size>200)—thesquarewilldisappearandstartgrowingagain
fromthetop-leftcorner.
Figure14-2showsaclose-upofthetop-leftcornerofthecanvasforthefirstfourstepsofthis
animation.
Figure14-2.Ineachstepofthisanimation,sizeisincrementedby1andthewidthandheightofthesquaregrowby1pixel.
ARandomBee
Nowthatweknowhowtomoveandgrowobjectsonourscreen,let’strysomethingabitmorefun.
Let’smakeabeethatfliesrandomlyaroundthecanvas!We’lldrawourbeeusinganumberofcircles,
likethis:
Theanimationwillworkverysimilarlytothemovingsquareanimation:we’llsetaposition,andthen
foreverystepoftheanimation,we’llclearthecanvas,drawthebeeatthatposition,andmodifythe
position.Thedifferenceisthattomakethebeemoverandomly,we’llneedtousemorecomplexlogic
forupdatingthebee’spositionthanweusedforthesquareanimation.We’llbuildupthecodeforthis
animationinafewsections.
ANewcircleFunction
We’lldrawourbeeusingafewcircles,sofirstwe’llmakeacirclefunctiontofilloroutlinecircles:
varcircle=function(x,y,radius,fillCircle){
ctx.beginPath();
➊ctx.arc(x,y,radius,0,Math.PI*2,false);
➋if(fillCircle){
➌ctx.fill();
}else{
➍ctx.stroke();
}
};
Thefunctiontakesfourarguments:x,y,radius,andfillCircle.Weusedasimilarcirclefunction
inChapter13,butherewe’veaddedfillCircleasanextraargument.Whenwecallthisfunction,this
argumentshouldbesettotrueorfalse,whichdetermineswhetherthefunctiondrawsafilledcircleor
justanoutline.
Insidethefunction,weusethearcmethodat➊tocreatethecirclewithitscenterattheposition(x,y)
andaradiusofradius.Afterthis,wechecktoseeifthefillCircleargumentistrueat➋.Ifitis
true,wefillthecircleusingctx.fillat➌.Otherwise,weoutlinethecircleusingctx.strokeat➍.
DrawingtheBee
Next,wecreatethedrawBeefunctiontodrawthebee.ThedrawBeefunctionusesthecirclefunction
todrawabeeatthecoordinatesspecifiedbyitsxandyarguments.Itlookslikethis:
vardrawBee=function(x,y){
➊ctx.lineWidth=2;
ctx.strokeStyle="Black";
ctx.fillStyle="Gold";
➋circle(x,y,8,true);
circle(x,y,8,false);
circle(x-5,y-11,5,false);
circle(x+5,y-11,5,false);
circle(x-2,y-1,2,false);
circle(x+2,y-1,2,false);
};
Inthefirstsectionofthiscodeat➊,wesetthelineWidth,strokeStyle,andfillStylepropertiesfor
ourdrawing.WesetthelineWidthto2pixelsandthestrokeStyletoBlack.Thismeansthatour
outlinedcircles,whichwe’lluseforthebee’sbody,wings,andeyes,willhavethickblackborders.The
fillStyleissettoGold,whichwillfillthecircleforourbeebodywithaniceyellowcolor.
Inthesecondsectionofthecodeat➋,wedrawaseriesofcirclestocreateourbee.Let’sgothrough
thoseoneatatime.
Thefirstcircledrawsthebee’sbodyusingafilledcirclewithacenteratthepoint(x,y)andaradiusof
8pixels:
circle(x,y,8,true);
BecausewesetthefillStyletoGold,thiscirclewillbefilledinwithyellowlikeso:
Thissecondcircledrawsablackoutlinearoundthebee’sbodythat’sthesamesizeandinthesame
placeasthefirstcircle:
circle(x,y,8,false);
Addedtothefirstcircle,itlookslikethis:
Next,weusecirclestodrawthebee’swings.Thefirstwingisanoutlinedcirclewithitscenter5pixels
totheleftand11pixelsabovethecenterofthebody,witharadiusof5pixels.Thesecondwingisthe
same,exceptit’s5pixelstotherightofthebody’scenter.
circle(x-5,y-11,5,false);
circle(x+5,y-11,5,false);
Withthosecirclesadded,ourbeelookslikethis:
Finally,wedrawtheeyes.Thefirstoneis2pixelstotheleftofthecenterofthebodyand1pixelabove,
witharadiusof2pixels.Thesecondoneisthesame,exceptit’s2pixelsrightofcenter.
circle(x-2,y-1,2,false);
circle(x+2,y-1,2,false);
Together,thesecirclescreateabee,withitsbodycenteredaroundthe(x,y)coordinatepassedintothe
drawBeefunction.
UpdatingtheBee’sLocation
We’llcreateanupdatefunctiontorandomlychangethebee’sx-andy-coordinatesinordertomakeit
appeartobuzzaroundthecanvas.Theupdatefunctiontakesasinglecoordinate;weupdatethexandy-coordinatesoneatatimesothatthebeewillmoverandomlyleftandrightandupanddown.The
updatefunctionlookslikethis:
varupdate=function(coordinate){
➊varoffset=Math.random()*4-2;
➋coordinate+=offset;
➌if(coordinate>200){
coordinate=200;
}
➍if(coordinate<0){
coordinate=0;
}
➎returncoordinate;
};
ChangingtheCoordinatewithanOffsetValue
At➊,wecreateavariablecalledoffset,whichwilldeterminehowmuchtochangethecurrent
coordinate.WegeneratetheoffsetvaluebycalculatingMath.random()*4-2.Thiswillgiveusa
randomnumberbetween–2and2.Here’show:callingMath.random()onitsowngivesusarandom
numberbetween0and1,soMath.random()*4producesarandomnumberbetween0and4.Then
wesubtract2togetarandomnumberbetween–2and2.
At➋weusecoordinate+=offsettomodifyourcoordinatewiththisoffsetnumber.Ifoffsetisa
positivenumber,coordinatewillincrease,andifit’sanegativenumber,coordinatewilldecrease.
Forexample,ifcoordinateissetto100andoffsetis1,thenafterwerunthelineat➋,coordinate
willbe101.However,ifcoordinateis100andoffsetis-1,thiswouldchangecoordinateto99.
CheckingiftheBeeReachestheEdge
At➌and➍wepreventthebeefromleavingthecanvasbymakingsurecoordinateneverincreases
above200orshrinksbelow0.Ifcoordinategetsbiggerthan200,wesetitbackto200,andifitgoes
below0,weresetitto0.
ReturningtheUpdatedCoordinate
Finally,at➎wereturncoordinate.Returningthenewvalueofcoordinateletsususethatvaluein
therestofourcode.Laterwe’llusethisreturnvaluefromtheupdatemethodtomodifythexandy
valueslikethis:
x=update(x);
y=update(y);
AnimatingOurBuzzingBee
Nowthatwehavethecircle,drawBee,andupdatefunctions,wecanwritetheanimationcodeforour
buzzingbee.
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
varx=100;
vary=100;
setInterval(function(){
➊ctx.clearRect(0,0,200,200);
➋drawBee(x,y);
➌x=update(x);
y=update(y);
➍ctx.strokeRect(0,0,200,200);
},30);
Asusual,westartwiththevarcanvasandvarctxlinestogetthedrawingcontext.Next,wecreate
thevariablesxandyandsetbothto100.Thissetsthebee’sstartingpositionatthepoint(100,100),
whichputsitinthemiddleofthecanvas,asshowninFigure14-3.
NextwecallsetInterval,passingafunctiontocallevery30milliseconds.Insidethisfunction,the
firstthingwedoiscallclearRectat➊toclearthecanvas.Next,at➋wedrawthebeeatthepoint(x,
y).Thefirsttimethefunctioniscalled,thebeeisdrawnatthepoint(100,100),asyoucanseein
Figure14-3,andeachtimethefunctioniscalledafterthat,itwilldrawthebeeatanew,updated(x,y)
position.
Nextweupdatethexandyvaluesstartingat➌.Theupdatefunctiontakesanumber,addsarandom
numberbetween–2and2toit,andreturnsthatupdatednumber.Sothecodex=update(x)basically
means“changexbyasmall,randomamount.”
Figure14-3.Thebeedrawnatthepoint(100,100)
Finally,wecallstrokeRectat➍todrawalinearoundtheedgeofthecanvas.Thismakesiteasierfor
ustoseewhenthebeeisgettingclosetoit.Withouttheborder,theedgeofthecanvasisinvisible.
Whenyourunthiscode,youshouldseetheyellowbeerandomlybuzzaroundthecanvas.Figure14-4
showsafewframesfromouranimation.
Figure14-4.Therandombeeanimation
BouncingaBall!
Nowlet’smakeaballthatbouncesaroundthecanvas.Whenevertheballhitsoneofthewalls,itwill
bounceoffatanangle,asarubberballwould.
First,we’llcreateaJavaScriptobjecttorepresentourballwithaBallconstructor.Thisobjectwillstore
theball’sspeedanddirectionusingtwoproperties,xSpeedandySpeed.Theball’shorizontalspeedwill
becontrolledbyxSpeed,andtheverticalspeedwillbecontrolledbyySpeed.
We’llmakethisanimationinanewfile.CreateanewHTMLfilecalledball.html,andaddthe
followingHTML:
<!DOCTYPEhtml>
<html>
<head>
<title>ABouncingBall</title>
</head>
<body>
<canvasid="canvas"width="200"height="200"></canvas>
<script>
//We'llfillthisinnext
</script>
</body>
</html>
TheBallConstructor
Firstwe’llcreatetheBallconstructor,whichwe’llusetocreateourbouncingball.Typethefollowing
codeintothe<script>tagsinball.html:
varBall=function(){
this.x=100;
this.y=100;
this.xSpeed=-2;
this.ySpeed=3;
};
Ourconstructorisverystraightforward:itsimplysetsthestartingpositionoftheball(this.xand
this.y),theball’shorizontalspeed(this.xSpeed),anditsverticalspeed(this.ySpeed).Wesetthe
startingpositiontothepoint(100,100),whichisthecenterofour200-by-200-pixelcanvas.
this.xSpeedissetto-2.Thiswillmaketheballmove2pixelstotheleftforeverystepofthe
animation.this.ySpeedissetto3.Thiswillmaketheballmove3pixelsdownforeverystepofthe
animation.Therefore,theballwillmovediagonallydown(3pixels)andtotheleft(2pixels)between
everyframe.
Figure14-5showsthestartingpositionoftheballanditsdirectionofmovement.
Figure14-5.Thestartingpositionoftheball,withanarrowindicatingitsdirection
DrawingtheBall
Nextwe’lladdadrawmethodtodrawtheball.We’lladdthismethodtotheBallprototypesothatany
objectscreatedbytheBallconstructorcanuseit:
varcircle=function(x,y,radius,fillCircle){
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
if(fillCircle){
ctx.fill();
}else{
ctx.stroke();
}
};
Ball.prototype.draw=function(){
circle(this.x,this.y,3,true);
};
Firstweincludeourcirclefunction,thesameoneweusedearlierinANewcircleFunction.Wethen
addthedrawmethodtoBall.prototype.Thismethodsimplycallscircle(this.x,this.y,3,
true)todrawacircle.Thecircle’scenterwillbeat(this.x,this.y):thelocationoftheball.Itwill
havearadiusof3pixels.Wepasstrueasthefinalargumenttotellthecirclefunctiontofillthe
circle.
MovingtheBall
Tomovetheball,wejusthavetoupdatethexandypropertiesbasedonthecurrentspeed.We’lldothat
usingthefollowingmovemethod:
Ball.prototype.move=function(){
this.x+=this.xSpeed;
this.y+=this.ySpeed;
};
Weusethis.x+=this.xSpeedtoaddthehorizontalspeedoftheballtothis.x.Thenthis.y+=
this.ySpeedaddstheverticalspeedtothis.y.Forexample,atthebeginningoftheanimation,the
ballwillbeatthepoint(100,100),withthis.xSpeedsetto-2andthis.ySpeedsetto3.Whenwe
callthemovemethod,itsubtracts2fromthexvalueandadds3totheyvalue,whichplacestheballat
thepoint(98,103).Thismovestheball’slocationtotheleft2pixelsanddown3pixels,asillustratedin
Figure14-6.
Figure14-6.Thefirstthreestepsoftheanimation,showinghowthexandypropertieschange
BouncingtheBall
Ateverystepoftheanimation,wechecktoseeiftheballhashitoneofthewalls.Ifithas,weupdate
thexSpeedorySpeedpropertybynegatingit(multiplyingitby–1).Forexample,iftheballhitsthe
bottomwall,wenegatethis.ySpeed.Soifthis.ySpeedis3,negatingitwillmakeit-3.If
this.ySpeedis-3,negatingitwillsetitbackto3.
We’llcallthismethodcheckCollision,becauseitcheckstoseeiftheballhascollidedwith(hit)the
wall.
Ball.prototype.checkCollision=function(){
➊if(this.x<0||this.x>200){
this.xSpeed=-this.xSpeed;
}
➋if(this.y<0||this.y>200){
this.ySpeed=-this.ySpeed;
}
};
At➊,wedeterminewhethertheballhashittheleftwallortherightwallbycheckingtoseeifitsx
propertyiseitherlessthan0(meaningithittheleftedge)orgreaterthan200(meaningithittheright
edge).Ifeitheroftheseistrue,theballhasstartedtomoveofftheedgeofthecanvas,sowehaveto
reverseitshorizontaldirection.Wedothisbysettingthis.xSpeedequalto-this.xSpeed.For
example,ifthis.xSpeedwas-2andtheballhittheleftwall,this.xSpeedwouldbecome2.
At➋,wedothesamethingforthetopandbottomwalls.Ifthis.yislessthan0orgreaterthan200,
weknowtheballhashitthetopwallorthebottomwall,respectively.Inthatcase,wesetthis.ySpeed
tobeequalto-this.ySpeed.
Figure14-7showswhathappenswhentheballhitstheleftwall.this.xSpeedstartsas-2,butafterthe
collisionitischangedto2.However,this.ySpeedremainsunchangedat3.
Figure14-7.Howthis.xSpeedchangesafteracollisionwiththeleftwall
AsyoucanseeinFigure14-7,inthiscasethecenteroftheballgoesofftheedgeofthecanvasatstep3
whenitcollideswithawall.Duringthatstep,partoftheballwilldisappear,butthishappenssoquickly
thatit’sbarelynoticeablewhentheanimationisrunning.
AnimatingtheBall
Nowwecanwritethecodethatgetstheanimationrunning.Thiscodesetsuptheobjectthatrepresents
theball,anditusessetIntervaltocallthemethodsthatdrawandupdatetheballforeachanimation
step.
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
➊varball=newBall();
➋setInterval(function(){
➌ctx.clearRect(0,0,200,200);
➍ball.draw();
ball.move();
ball.checkCollision();
➎ctx.strokeRect(0,0,200,200);
➏},30);
Wegetthecanvasanddrawingcontextasusualonthefirsttwolines.Thenwecreateaballobjectusing
newBall()andsaveitinthevariableballat➊.Next,wecallsetIntervalat➋,passingafunction
andthenumber30at➏.Asyou’veseenbefore,thismeans“callthisfunctionevery30milliseconds.”
ThefunctionwepasstosetIntervaldoesseveralthings.First,itclearsthecanvas,using
ctx.clearRect(0,0,200,200)at➌.Afterthis,itcallsthedraw,move,andcheckCollision
methodsat➍ontheballobject.Thedrawmethoddrawstheballatitscurrentx-andy-coordinates.
ThemovemethodupdatesthepositionoftheballbasedonitsxSpeedandySpeedproperties.Finally,
thecheckCollisionmethodupdatesthedirectionoftheball,ifithitsawall.
ThelastthingwedointhefunctionpassedtosetIntervaliscallctx.strokeRect(0,0,200,200)
at➎todrawalinearoundtheedgeofthecanvas,sowecanseethewallstheballishitting.
Whenyourunthiscode,theballshouldimmediatelystartmovingdownandtotheleft.Itshouldhitthe
bottomwallfirst,andbounceupandtotheleft.Itwillcontinuetobouncearoundthecanvasaslongas
youleavethebrowserwindowopen.
WhatYouLearned
Inthischapter,wecombinedourknowledgeofanimationfromChapter11withourknowledgeofthe
canvaselementtocreatevariouscanvas-basedanimations.Webegansimplybymovingandgrowing
squaresonthecanvas.Next,wemadeabeebuzzrandomlyaroundthescreen,andweendedwithan
animationofabouncingball.
Alloftheseanimationsworkinbasicallythesameway:wedrawashapeofaparticularsizeina
particularposition,thenweupdatethatsizeorposition,andthenweclearthecanvasanddrawthe
shapeagain.Forelementsmovingarounda2Dcanvas,wegenerallyhavetokeeptrackofthex-andycoordinatesoftheelement.Forthebeeanimation,weaddedorsubtractedarandomnumberfromthexandy-coordinates.Forthebouncingball,weaddedthecurrentxSpeedandySpeedtothex-andycoordinates.Inthenextchapter,we’lladdinteractivitytoourcanvas,whichwillletuscontrolwhat’s
drawntothecanvasusingthekeyboard.
ProgrammingChallenges
Herearesomewaysyoucanbuildonthebouncingballanimationfromthischapter.
#1:BOUNCINGTHEBALLAROUNDALARGERCANVAS
Our200-by-200-pixelcanvasisabitsmall.Whatifyouwantedtoincreasethecanvassizeto400by
400pixelsorsomeotherarbitrarysize?
Insteadofenteringthewidthandheightofthecanvasmanuallythroughoutyourprogram,youcan
createwidthandheightvariablesandsetthevariablesusingthecanvasobject.Usethefollowing
code:
varwidth=canvas.width;
varheight=canvas.height;
Nowifyouusethesevariablesthroughoutyourprogram,youonlyhavetochangethepropertiesonthe
canvaselementintheHTMLifyouwanttotryoutanewsize.Trychangingthesizeofthecanvasto
500pixelsby300pixels.Doesyourprogramstillwork?
#2:RANDOMIZINGTHIS.XSPEEDANDTHIS.YSPEED
Tomaketheanimationmoreinteresting,setthis.xSpeedandthis.ySpeedtodifferentrandom
numbers(between–5and5)intheBallconstructor.
#3:ANIMATINGMOREBALLS
Insteadofcreatingjustoneball,createanemptyarrayofballs,anduseaforlooptoadd10ballstothe
array.Now,inthesetIntervalfunction,useaforlooptodraw,move,andcheckcollisionsoneachof
theballs.
#4:MAKINGTHEBALLSCOLORFUL
Howaboutmakingsomecoloredbouncingballs?SetanewpropertyintheBallconstructorcalled
coloranduseitinthedrawmethod.UsethepickRandomWordfunctionfromChapter8togiveeach
ballarandomcolorfromthisarray:
varcolors=["Red","Orange","Yellow","Green","Blue",
"Purple"];
Chapter15.ControllingAnimationswiththe
Keyboard
Nowthatyouknowhowtoworkwiththecanvas;drawandcolorobjects;andmakeobjectsmove,
bounce,andgrowinsize,let’sliventhingsupbyaddingsomeinteractivity!
Inthischapter,you’lllearnhowtomakeyourcanvasanimationsrespondwhenauserpressesakeyon
thekeyboard.Thisway,aplayercancontrolananimationbypressinganarrowkeyoroneofafew
assignedlettersontheirkeyboard(liketheclassicW,A,S,Dgamecontrols).Forexample,insteadof
justhavingaballbounceacrossascreen,wecanhaveaplayercontrolthemovementoftheballusing
thearrowkeys.
KeyboardEvents
JavaScriptcanmonitorthekeyboardthroughkeyboardevents.Eachtimeauserpressesakeyonthe
keyboard,theygenerateakeyboardevent,whichisalotlikethemouseeventswesawinChapter10.
Withmouseevents,weusedjQuerytodeterminewherethecursorwaswhentheeventtookplace.With
keyboardevents,youcanusejQuerytodeterminewhichkeywaspressedandthenusethatinformation
inyourcode.Forexample,inthischapterwe’llmakeaballmoveleft,right,up,ordownwhentheuser
pressestheleft,right,up,ordownarrowkey.
We’llusethekeydownevent,whichistriggeredwheneverauserpressesakey,andwe’llusejQueryto
addaneventhandlertothekeydownevent.Thatway,everytimeakeydowneventoccurs,ourevent
handlerfunctioncanfindoutwhichkeywaspressedandrespondaccordingly.
SettingUptheHTMLFile
Tobegin,createacleanHTMLfilecontainingthefollowingcodeandsaveitaskeyboard.html.
<!DOCTYPEhtml>
<html>
<head>
<title>Keyboardinput</title>
</head>
<body>
<canvasid="canvas"width="400"height="400"></canvas>
<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
<script>
//We'llfillthisinnext
</script>
</body>
</html>
AddingthekeydownEventHandler
Nowlet’saddsomeJavaScripttorespondtokeydownevents.Enterthiscodeinsidetheempty
<script>tagsinyourkeyboard.htmlfile.
$("body").keydown(function(event){
console.log(event.keyCode);
});
Inthefirstline,weusethejQuery$functiontoselectthebodyelementinourHTMLandthencallthe
keydownmethod.Theargumenttothekeydownmethodisafunctionthatwillbecalledwheneverakey
ispressed.Informationaboutthekeydowneventispassedintothefunctionthroughtheeventobject.
Forthisprogram,wewanttoknowwhichkeywaspressed,andthatinformationisstoredintheevent
objectasevent.keyCode.
Insidethefunction,weuseconsole.logtooutputtheeventobject’skeyCodeproperty:anumber
representingthepressedkey.Eachkeyonyourkeyboardhasauniquekeycode.Forexample,the
keycodeforthespacebaris32,andtheleftarrowis37.
Onceyou’veeditedyourkeyboard.htmlfile,saveitandthenopenitinabrowser.Nowopentheconsole
soyoucanseetheoutput,andclickinthemainbrowserwindowtohaveJavaScriptregisteryour
keypresses.Now,ifyoustartpressingkeys,thecorrespondingkeycodesshouldbeprintedtothe
console.
Forexample,ifyoutypehithere,youshouldseethefollowingoutputintheconsole:
72
73
32
84
72
69
82
69
Everykeyyoupresshasadifferentkeycode.TheHkeyis72,theIkeyis73,andsoon.
TRYITOUT!
Pressvariouskeystoseetheirkeycodes.Whatarethekeycodesfortheup,down,left,andrightarrows?WhataboutSHIFTandENTER?
Thenumberandletterkeyseachhavetheirownkeycodestoo.
UsinganObjecttoConvertKeycodesintoNames
Tomakeiteasiertoworkwithkeys,we’lluseanobjecttoconvertthekeycodesintonamessothatthe
keypresseswillbeeasiertorecognize.Inthisnextexample,wecreateanobjectcalledkeyNames,where
theobjectkeysarekeycodesandthevaluesarethenamesofthosekeys.DeletetheJavaScriptin
keyboard.htmlandreplaceitwiththis:
varkeyNames={
32:"space",
37:"left",
38:"up",
39:"right",
40:"down"
};
$("body").keydown(function(event){
➊console.log(keyNames[event.keyCode]);
});
First,wecreatethekeyNamesobjectandfillitwiththekeycodes32,37,38,39,and40.ThekeyNames
objectuseskey-valuepairstomatchkeycodes(suchas32,37,andsoon)withcorrespondinglabels
(suchas"space"forthespacebarand"left"fortheleftarrow).
Wecanthenusethisobjecttofindoutthenameofakeybasedonitskeycode.Forexample,tolookup
thekeycode32,enterkeyNames[32].Thatreturnsthestring"space".
At➊,weusethekeyNamesobjectinthekeydowneventhandlertogetthenameofthekeythatwasjust
pressed.Iftheeventkeycodereferencedbyevent.keyCodematchesoneofthekeysinthekeyNames
object,thisfunctionwilllogthenameofthatkey.Ifnokeymatches,thiscodewilllogundefined.
Loadkeyboard.htmlinyourbrowser.Opentheconsole,clickinthemainbrowserwindow,andtry
pressingafewkeys.IfyoupressoneofthefivekeysinthekeyNameobject(thearrowkeysor
spacebar),theprogramshouldprintthenameofthekey.Otherwise,itwillprintundefined.
TRYITOUT!
Addmorekey-valuepairstothekeyNamesobjectsothatitcanconvertmorekeystonames.InsertthekeycodesandnamesforSHIFT,
ENTER/RETURN,andALT/OPTION.
MovingaBallwiththeKeyboard
Nowthatwecandeterminewhichkeyisbeingpressed,wecanwriteaprogramtousethekeyboardto
controlthemovementofaball.Ourprogramwilldrawaballandmoveittotheright.Pressingthe
arrowkeyswillchangetheball’sdirection,andpressingthespacebarwillstopit.Iftheballgoesoffthe
edgeofthecanvas,itwillwraparoundtotheoppositeside.Forexample,iftheballgoesofftheright
edgeofthecanvas,itwillshowupagainontheleftedgewhilecontinuingtomoveinthesame
direction,asshowninFigure15-1.
Figure15-1.Iftheballmovesofftherightsideofthecanvas,itwillreappearontheleft.
We’lluseanobjectcalledkeyActionstofindoutwhichkeywaspressedandthenusethatinformation
tosetthedirectionoftheball’smovement.We’llusesetIntervaltocontinuallyupdatetheball’s
positionandredrawitatitsnewposition.
SettingUptheCanvas
Firstweneedtosetupthecanvasandthecontextobject.Openkeyboard.htmlandreplacethe
JavaScriptbetweenthesecondsetof<script>tagswiththiscode:
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
varwidth=canvas.width;
varheight=canvas.height;
Onthefirstline,weusedocument.getElementByIdtoselectthecanvaselement.Onthesecondline,
wecallgetContextonthecanvastogetthecontextobject.Then,inthevarwidthandvarheight
lines,westorethewidthandheightofthecanvaselementinthevariableswidthandheight.This
way,whenweneedthecanvasdimensions,wecanusethesevariablesinsteadofhavingtoenterthe
numbersmanually.Now,ifwechoosetochangethesizeofthecanvas,wecansimplyedittheHTML,
andtheJavaScriptcodeshouldstillwork.
DefiningthecircleFunction
Next,wedefinethesamecirclefunctionfortheballthatweusedinChapter14.Addthisfunction
afterthecodefromtheprevioussection:
varcircle=function(x,y,radius,fillCircle){
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
if(fillCircle){
ctx.fill();
}else{
ctx.stroke();
}
};
CreatingtheBallConstructor
Nowwe’llcreateaBallconstructor.We’llusethisconstructortocreatethemovingballobject.We’ll
beusingthesametechniqueformovingthisballaswedidinChapter14—usingthexSpeedand
ySpeedpropertiestocontrolthehorizontalandverticalspeedoftheball.Addthiscodeafterthecircle
function:
varBall=function(){
this.x=width/2;
this.y=height/2;
this.xSpeed=5;
this.ySpeed=0;
};
Wesetthexandyvalues(theball’sposition)towidth/2andheight/2sothattheballwillstartat
thecenterofthecanvas.Wealsosetthis.xSpeedto5andthis.ySpeedto0.Thismeansthattheball
willstarttheanimationbymovingtotheright(thatis,witheachanimationstep,itsxpositionwill
increaseby5pixelsanditsypositionwillstaythesame).
DefiningthemoveMethod
Inthissection,we’lldefinethemovemethod.We’lladdthismethodtoBall.prototypetomovethe
balltoanewlocationbasedonitscurrentlocation,xSpeedandySpeed.AddthismethodaftertheBall
constructor:
Ball.prototype.move=function(){
this.x+=this.xSpeed;
this.y+=this.ySpeed;
➊if(this.x<0){
this.x=width;
}elseif(this.x>width){
this.x=0;
}elseif(this.y<0){
this.y=height;
}elseif(this.y>height){
this.y=0;
}
};
Firstweupdatethis.xandthis.yusingthis.xSpeedandthis.ySpeed,justaswedidinChapter14
(seeMovingtheBall).Afterthatisthecodeforwhentheballreachestheedgeofthecanvas.
Theif...elsestatementat➊checkstheball’spositiontoseeifithasmovedofftheedgeofthe
canvas.Ifithas,thiscodemakestheballwraparoundtotheothersideofthecanvas.Forexample,if
theballgoesofftheleftedgeofthecanvas,itshouldreappearfromtherightsideofthecanvas.Inother
words,ifthis.xislessthan0,wesetthis.xtowidth,whichplacesitattheveryrightedgeofthe
canvas.Therestoftheif...elsestatementdealswiththeotherthreeedgesofthecanvasinasimilar
way.
DefiningthedrawMethod
We’llusethedrawmethodtodrawtheball.Addthisafterthedefinitionofthemovemethod:
Ball.prototype.draw=function(){
circle(this.x,this.y,10,true);
};
Thismethodcallsthecirclefunction.
Itusestheball’sxandyvaluestosetthecenteroftheball,setstheradiusto10,andsetsfillCircleto
true.Figure15-2showstheresultingball.
Figure15-2.Theballisafilledcirclewitharadiusof10.
CreatingasetDirectionMethod
Nowwehavetocreateawaytosetthedirectionoftheball.We’lldothatwithamethodcalled
setDirection.Thismethodwillbecalledbyourkeydowneventhandler,whichyou’llseeinthenext
section.ThekeydownhandlerwilltellsetDirectionwhichkeywaspressedbypassingitastring
("left","up","right","down",or"stop").Basedonthatstring,setDirectionwillchangethe
xSpeedandySpeedpropertiesoftheballtomakeitmoveinthedirectionthatmatchesthekeypress.
Forexample,ifthestring"down"ispassed,wesetthis.xSpeedto0andthis.ySpeedto5.Addthis
codeafterthedrawmethod:
Ball.prototype.setDirection=function(direction){
if(direction==="up"){
this.xSpeed=0;
this.ySpeed=-5;
}elseif(direction==="down"){
this.xSpeed=0;
this.ySpeed=5;
}elseif(direction==="left"){
this.xSpeed=-5;
this.ySpeed=0;
}elseif(direction==="right"){
this.xSpeed=5;
this.ySpeed=0;
}elseif(direction==="stop"){
this.xSpeed=0;
this.ySpeed=0;
}
};
Theentirebodyofthismethodisonelongif...elsestatement.Thenewdirectionispassedintothe
methodasthedirectionargument.Ifdirectionisequalto"up",wesettheball’sxSpeedpropertyto
0anditsySpeedpropertyto-5.Theotherdirectionsarehandledinthesameway.Finally,ifthe
directionissettothestring"stop",wesetboththis.xSpeedandthis.ySpeedto0,whichmeansthat
theballwillstopmoving.
ReactingtotheKeyboard
ThisnextsnippetofcodecreatesaballobjectusingtheBallconstructor,anditlistensforkeydown
eventsinordertosettheball’sdirection.AddthiscodeafterthesetDirectionmethod:
➊varball=newBall();
➋varkeyActions={
32:"stop",
37:"left",
38:"up",
39:"right",
40:"down"
};
➌$("body").keydown(function(event){
➍vardirection=keyActions[event.keyCode];
➎ball.setDirection(direction);
});
At➊,wecreateaballobjectbycallingnewBall().At➋wecreateakeyActionsobject,whichwe’ll
usetoconvertkeycodestotheircorrespondingdirection.ThisobjectisthesameasthekeyNamesobject
wecreatedinUsinganObjecttoConvertKeycodesintoNames,exceptthatfor32(thekeycodeforthe
spacebar)wereplacethelabel"space"with"stop"sincewewantthespacebartostoptheballfrom
moving.
At➌weusethejQuery$functiontoselectthebodyelementandthencallthekeydownmethodto
listenforkeydownevents.Thefunctionpassedtothekeydownmethodiscalledeverytimeakeyis
pressed.
Insidethisfunction,weusekeyActions[event.keyCode]at➍tolookupthelabelforthekeythat
waspressedandassignthatlabeltothedirectionvariable.Thissetsthedirectionvariabletoa
direction:"left"iftheleftarrowispressed,"right"iftherightarrowispressed,"up"fortheup
arrow,"down"forthedownarrow,and"stop"forthespacebar.Ifanyotherkeyispressed,direction
issettoundefined,andtheanimationwon’tbeaffected.
Finally,at➎wecallthesetDirectionmethodontheballobject,passingthedirectionstring.Asyou
sawbefore,setDirectionupdatestheball’sxSpeedandySpeedpropertiesbasedonthenewdirection.
AnimatingtheBall
Allwehavelefttodonowisanimatetheball.Thefollowingcodeshouldlookfamiliar,sinceit’squite
similartowhatweusedinChapter14.ItusesthesetIntervalfunctionthatwe’veseeninthe
animationcodeinpreviouschapterstoupdatetheball’spositionatregularintervals.Addthiscodeafter
thecodefromtheprevioussection:
setInterval(function(){
ctx.clearRect(0,0,width,height);
ball.draw();
ball.move();
ctx.strokeRect(0,0,width,height);
},30);
WeusesetIntervaltocallouranimationfunctionevery30milliseconds.Thefunctionfirstclearsthe
entirecanvaswithclearRectandthencallsthedrawandmovemethodsontheball.Aswe’veseen,the
drawmethodsimplydrawsacircleattheball’scurrentlocation,andthemovemethodupdatestheball’s
positionbasedonitsxSpeedandySpeedproperties.Finally,itdrawsaborderwithstrokeRectsowe
canseetheedgeofthecanvas.
PuttingItAllTogether
Nowthatwe’vegonethroughallthecode,here’sthefulllistingforyourconvenience.
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
varwidth=canvas.width;
varheight=canvas.height;
varcircle=function(x,y,radius,fillCircle){
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
if(fillCircle){
ctx.fill();
}else{
ctx.stroke();
}
};
//TheBallconstructor
varBall=function(){
this.x=width/2;
this.y=height/2;
this.xSpeed=5;
this.ySpeed=0;
};
//Updatetheball'spositionbasedonitsspeed
Ball.prototype.move=function(){
this.x+=this.xSpeed;
this.y+=this.ySpeed;
if(this.x<0){
this.x=width;
}elseif(this.x>width){
this.x=0;
}elseif(this.y<0){
this.y=height;
}elseif(this.y>height){
this.y=0;
}
};
//Drawtheballatitscurrentposition
Ball.prototype.draw=function(){
circle(this.x,this.y,10,true);
};
//Settheball'sdirectionbasedonastring
Ball.prototype.setDirection=function(direction){
if(direction==="up"){
this.xSpeed=0;
this.ySpeed=-5;
}elseif(direction==="down"){
this.xSpeed=0;
this.ySpeed=5;
}elseif(direction==="left"){
this.xSpeed=-5;
this.ySpeed=0;
}elseif(direction==="right"){
this.xSpeed=5;
this.ySpeed=0;
}elseif(direction==="stop"){
this.xSpeed=0;
this.ySpeed=0;
}
};
//Createtheballobject
varball=newBall();
//Anobjecttoconvertkeycodesintoactionnames
varkeyActions={
32:"stop",
37:"left",
38:"up",
39:"right",
40:"down"
};
//Thekeydownhandlerthatwillbecalledforeverykeypress
$("body").keydown(function(event){
vardirection=keyActions[event.keyCode];
ball.setDirection(direction);
});
//Theanimationfunction,calledevery30ms
setInterval(function(){
ctx.clearRect(0,0,width,height);
ball.draw();
ball.move();
ctx.strokeRect(0,0,width,height);
},30);
RunningtheCode
Nowourprogramiscomplete.Whenyouruntheprogram,youshouldseeablackballmovingacross
thecanvastotheright,asshowninFigure15-3.Whenitreachestherightsideofthecanvas,itshould
wraparoundtotheleftsideandkeepmovingtotheright.Whenyoupressthearrowkeys,theball
shouldchangedirection,andpressingthespacebarshouldmaketheballstop.
Figure15-3.Ascreenshotfromthemovingballanimation
NOTE
Iftheanimationdoesn’trespondtokeysasexpected,clickthepagetomakesuretheprogramcanaccessyourkeypresses.
WhatYouLearned
Inthischapter,youlearnedhowtomakeprogramsthatreacttokeyboardevents.Weusedthis
knowledgetocreateamovingball,wheretheball’sdirectionissetbythekeyboard.
Nowthatwecandrawtothecanvas,createanimations,andupdatethoseanimationsbasedonuser
input,wecancreateasimplecanvas-basedgame!Inthenextchapter,we’llre-createtheclassicSnake
game,combiningeverythingwe’velearnedupuntilnow.
ProgrammingChallenges
Hereareafewwaysyoucanbuildonthefinalanimationtomakeitmoresophisticated.
#1:BOUNCINGOFFTHEWALLS
Modifythecodesotheballbouncesoffthesideandtopwallsinsteadofwrappingaroundtotheother
side.Hint:Justreversethedirectionwhentheballhitsthewall.
#2:CONTROLLINGTHESPEED
Theballcurrentlymoves5pixelsforeverystepoftheanimation.ThisisbecausesetDirection
alwayssetsxSpeedorySpeedto-5or5.CreateanewpropertyintheBallconstructorcalledspeed
andsetitto5.Thenusethisinsteadofthenumber5insetDirection.
Now,changeyourcodesothatyoucanusethenumberkeystosetthespeedfrom1to9.Hint:Create
anobjectcalledspeeds,anduseittodeterminethenewspeed,ifany,basedonthekeydownevent.
#3:FLEXIBLECONTROLS
ModifyyourcodesothatwhenyoupresstheZkey,theballslowsdown,andwhenyoupresstheXkey,
itspeedsup.Oncethat’sworking,useCtomaketheballsmallerandVtomakeitlarger.
Whathappensifthespeedgoesbelow0?Whataboutthesize?Addacheckinthecodetomakesure
thespeedandsizenevergobelow0.
Chapter16.MakingaSnakeGame:Part1
Inthischapterandthenext,we’llbuildourownversionoftheclassicarcadegameSnake.InSnake,the
playerusesthekeyboardtocontrolasnakebydirectingitsmovementup,down,left,orright.Asthe
snakemovesaroundtheplayingarea,applesappear.Whenthesnakereachesanapple,iteatstheapple
andgrowslonger.Butifthesnakehitsawallorrunsintopartofitsownbody,thegameisover.
Asyoucreatethisgame,you’llcombinemanyofthetoolsandtechniquesyou’velearnedsofar,
includingjQueryandthecanvasaswellasanimationandinteractivity.Inthischapter,we’lllookatthe
generalstructureofthegameandgothroughthecodefordrawingtheborderandthescoreandending
thegame.InChapter17,we’llwritethecodeforthesnakeandtheappleandthenputeverything
togethertocompletethegame.
TheGamePlay
Figure16-1showswhatourfinishedgamewilllooklike.We’llneedtokeeptrackofanddrawfour
itemsonthescreenasthegameruns:theborder(ingray),thescore(inblack),thesnake(inblue),and
theapple(inlimegreen).
Figure16-1.OurSnakegame
TheStructureoftheGame
Beforewestartwritingcode,let’stakealookattheoverallstructureofthegame.Thispseudocode
describeswhatourprogramneedstodo:
Setupthecanvas
Setscoretozero
Createsnake
Createapple
Every100milliseconds{
Clearthecanvas
Drawcurrentscoreonthescreen
Movesnakeincurrentdirection
Ifsnakecollideswithwalloritself{
Endthegame
}ElseIfsnakeeatsanapple{
Addonetoscore
Moveappletonewlocation
Makesnakelonger
}
Foreachsegmentofthesnake{
Drawthesegment
}
Drawapple
Drawborder
}
Whentheuserpressesakey{
Ifthekeyisanarrow{
Updatethedirectionofthesnake
}
}
Overthecourseofthischapterandthenext,we’llwritethecodetoexecuteeachofthesesteps.But
first,let’stalkthroughsomeofthemajorpartsofthisprogramandplanoutsomeoftheJavaScripttools
we’lluseforthem.
UsingsetIntervaltoAnimatetheGame
Asyoucanseeinthepseudocode,every100millisecondsweneedtocallaseriesoffunctionsand
methodsthatupdateanddraweverythingtothegameboard.Justaswe’vedoneinChapter14and
Chapter15,we’llusesetIntervaltoanimatethegamebycallingthosefunctionsatregularintervals.
ThisiswhatourcalltosetIntervalwilllooklikeinthefinalprogram:
varintervalId=setInterval(function(){
ctx.clearRect(0,0,width,height);
drawScore();
snake.move();
snake.draw();
apple.draw();
drawBorder();
},100);
InthefunctionthatwepasstosetInterval,thefirstlineclearsthecanvaswithclearRectsothatwe
candrawthenextstepintheanimation.Nextweseeseveralfunctionandmethodcalls.Noticethat
theseallroughlymatchupwiththestepsinthepseudocodelistingonthepreviouspage.
AlsonoticethatwesavetheintervalIDinthevariableintervalId.We’llneedthatintervalIDwhen
thegameisoverandwewanttostoptheanimation(seeEndingtheGame).
CreatingtheGameObjects
Forthisprogram,we’llusetheobject-orientedprogrammingstylewelearnedaboutinChapter12to
representthetwomainobjectsinthegame:thesnakeandtheapple.We’llcreateaconstructorforeach
oftheseobjects(calledSnakeandApple),andwe’lladdmethods(likemoveanddraw)tothe
prototypesoftheseconstructors.
We’llalsodividethegameboardintoagridandthencreateaconstructorcalledBlock,whichwe’lluse
tocreateobjectsthatrepresentsquaresinthegrid.We’llusetheseblockobjectstorepresentthelocation
ofsegmentsofthesnake,andwe’lluseasingleblockobjecttostoretheapple’scurrentlocation.These
blockswillalsohavemethodstoletusdrawthesegmentsofthesnakeandtheapple.
SettingUpKeyboardControl
Intheearlierpseudocode,there’sasectiondevotedtorespondingtokeypressesbytheuser.Toallow
theplayertocontrolthesnakeusingthearrowkeysonthekeyboard,we’llusejQuerytorespondto
keypresses,aswedidinChapter15.We’llidentifythekeythatwaspressedbylookingupthekeycode,
andthenwe’llsetthesnake’sdirectionaccordingly.
GameSetup
Nowthatwe’vegonethroughanoverviewofhowtheprogramwillwork,let’sstartwritingsomecode!
Inthischapter,we’llstartbysettinguptheHTML,thecanvas,andsomevariableswe’llneed
throughouttheprogram.Thenwe’lltackleafewofthemorestraightforwardfunctionsweneedforthis
game:onetodrawtheborderaroundtheboard,onetodrawthescoreonthescreen,andonetoendthe
game.Inthenextchapter,we’llcreatetheconstructorsandmethodsforthesnakeandapple,createan
eventhandlerforarrowkeypresses,andputitalltogethertocompletethegame.
CreatingtheHTML
Tobegincodingourgame,enterthefollowingintoyourtexteditorandsaveitassnake.html.
<!DOCTYPEhtml>
<html>
<head>
<title>Snake!</title>
</head>
<body>
➊<canvasid="canvas"width="400"height="400"></canvas>
➋<scriptsrc="https://code.jquery.com/jquery-2.1.0.js"></script>
➌<script>
//We'llfillthisinnext
</script>
</body>
</html>
At➊wecreateacanvaselementthatis400×400pixels.Thisiswherewe’lldraweverythingforour
game.WeincludethejQuerylibraryat➋,followedbyanotherpairof<script>tagsat➌,wherewe’ll
addourJavaScriptcodetocontrolthegame.Let’sstartwritingthatJavaScriptnow.
Definingthecanvas,ctx,width,andheightVariables
Firstwe’lldefinethevariablescanvasandctx,whichwillletusdrawonthecanvas,andthevariables
widthandheight,togetthewidthandheightofthecanvaselement.
varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
varwidth=canvas.width;
varheight=canvas.height;
ThecodeintheHTMLsetsthewidthandheightto400pixels;ifyouchangethosedimensionsinthe
HTML,widthandheightwillmatchthenewdimensions.
DividingtheCanvasintoBlocks
Next,we’llcreatevariablestohelpusthinkaboutourcanvasasagridof10-by-10-pixelblocks,as
showninFigure16-2.Althoughthegridwillbeinvisible(thatis,thegamewon’tactuallydisplayit),
everythinginthegamewillbedrawntolineupwithit.
Figure16-2.A10-pixelgridshowingtheblocklayoutofthegame
Thesnakeandapplewillbothbeoneblockwidesothattheyfitwithinthisgrid.Foreverystepofthe
animation,thesnakewillmoveexactlyoneblockinitscurrentdirection.
We’llusethesevariablestocreatetheblocksonourcanvas:
➊varblockSize=10;
➋varwidthInBlocks=width/blockSize;
varheightInBlocks=height/blockSize;
At➊wecreateavariablecalledblockSizeandsetitto10,sincewewantourblockstobe10pixels
tallandwide.At➋wecreatethevariableswidthInBlocksandheightInBlocks.Weset
widthInBlocksequaltothewidthofthecanvasdividedbytheblocksize,whichtellsushowmany
blockswidethecanvasis.Similarly,heightInBlockstellsushowmanyblockstallthecanvasis.At
themomentthecanvasis400pixelswideandtall,sowidthInBlocksandheightInBlockswillboth
be40.IfyoucountthenumberofsquaresinFigure16-2(includingtheborder),you’llseethatit’s40
blockswideandtall.
DefiningthescoreVariable
Finally,wedefinethescorevariable.
varscore=0;
We’llusethescorevariabletokeeptrackoftheplayer’sscore.Becausethisisthebeginningofthe
program,wesetscoreequalto0.We’llincrementitby1everytimethesnakeeatsanapple.
DrawingtheBorder
Next,we’llcreateadrawBorderfunctiontodrawaborderaroundthecanvas.We’llmakethisborder
oneblock(10pixels)thick.
Ourfunctionwilldrawfourlong,thinrectangles,oneforeachedgeoftheborder.Eachrectanglewill
beblockSize(10pixels)thickandthefullwidthorheightofthecanvas.
vardrawBorder=function(){
ctx.fillStyle="Gray";
➊ctx.fillRect(0,0,width,blockSize);
➋ctx.fillRect(0,height-blockSize,width,blockSize);
➌ctx.fillRect(0,0,blockSize,height);
➍ctx.fillRect(width-blockSize,0,blockSize,height);
};
FirstwesetthefillStyletogray,becausewewantthebordertobegray.Then,at➊,wedrawthetop
edgeoftheborder.Herewe’redrawingarectanglestartingat(0,0)—thetop-leftcornerofthecanvas
—withawidthofwidth(400pixels)andaheightofblockSize(10pixels).
Next,at➋,wedrawthebottomedgeoftheborder.Thiswillbearectangleatthecoordinates(0,
height-blockSize),or(0,390).Thisis10pixelsupfromthebottomofthecanvas,ontheleft.Like
thetopborder,thisrectanglehasawidthofwidthandaheightofblockSize.
Figure16-3showswhatthetopandbottomborderslooklike.
Figure16-3.Thetopandbottomborders
At➌wedrawtheleftborder,andat➍wedrawtherightone.Figure16-4showstheadditionofthese
twoedges.
Figure16-4.Theleftandrightborders(withthetopandbottombordersshowninalightergray)
DisplayingtheScore
Nowlet’swriteadrawScorefunctiontodisplaythescoreatthetopleftofthecanvas,asshownin
Figure16-1.ThisfunctionwillusethefillTextcontextmethodtoaddtexttothecanvas.The
fillTextmethodtakesatextstringandthex-andy-coordinateswhereyouwanttodisplaythattext.
Forexample,
ctx.fillText("Helloworld!",50,50);
wouldwritethestringHelloworld!atthecoordinates(50,50)onyourcanvas.Figure16-5shows
howthatwouldlook.
Figure16-5.ThestringHelloworld!drawnatthepoint(50,50)
Heylook,we’veprintedtexttothecanvas!Butwhatifwewanttohavemorecontroloverhowthetext
looksbytweakingthesizeandfontorchangingthealignment?ForthescoreinourSnakegame,we
mightwanttouseadifferentfont,makethetextbigger,andmakesurethetextappearspreciselyinthe
top-leftcorner,justbelowtheborder.SobeforewewriteourdrawScorefunction,let’slearnalittle
moreaboutthefillTextmethodandlookatsomewaystocustomizehowtextappearsonthecanvas.
SettingtheTextBaseline
Thecoordinatelocationthatdetermineswherethetextappearsiscalledthebaseline.Bydefault,the
bottom-leftcornerofthetextislinedupwiththebaselinepointsothatthetextappearsaboveandtothe
rightofthatpoint.
Tochangewherethetextappearsinrelationtothebaseline,wecanchangethetextBaselineproperty.
Thedefaultvalueforthispropertyis"bottom",butyoucanalsosetthetextBaselinepropertyto
"top"or"middle".Figure16-6showshowthetextisalignedforeachoftheseoptions,inrelationto
thebaselinepoint(shownasareddot)thatyoupasstofillText.
Figure16-6.TheeffectofchangingtextBaseline
Forexample,torunyourtextbelowthebaseline,enter:
ctx.textBaseline="top";
ctx.fillText("Helloworld!",50,50);
Now,whenyoucallfillText,thetextwillbebelowthepoint(50,50),asyoucanseeinFigure16-7.
Figure16-7.ThestringHelloworld!withtextBaselinesetto"top"
Similarly,tochangethehorizontalpositionofthetextrelativetothebaselinepoint,youcansetthe
textAlignpropertyto"left","center",or"right".Figure16-8showstheresults.
Figure16-8.TheeffectofchangingtextAlign
SettingtheSizeandFont
Wecanchangethesizeandfontofthetextwedrawbysettingthefontpropertyofthedrawing
context.Thislistingshowssomeexamplesofdifferentfontswecoulduse:
➊ctx.font="20pxCourier";
ctx.fillText("Courier",50,50);
ctx.font="24pxComicSansMS";
ctx.fillText("ComicSans",50,100);
ctx.font="18pxArial";
ctx.fillText("Arial",50,150);
Thefontpropertytakesastringthatincludesthesizeandthenameofthefontyouwanttouse.For
example,at➊wesetthefontpropertyto"20pxCourier",whichmeansthetextwillbedrawnata
sizeof20pixelsinthefontCourier.Figure16-9showshowthesedifferentfontslookwhendrawnon
thecanvas.
Figure16-9.20pxCourier,24pxComicSans,and18pxArial
WritingthedrawScoreFunction
NowwecangoaheadandwritethedrawScorefunction,whichdrawsastringshowingthecurrent
scoreonthecanvas.
vardrawScore=function(){
ctx.font="20pxCourier";
ctx.fillStyle="Black";
ctx.textAlign="left";
ctx.textBaseline="top";
ctx.fillText("Score:"+score,blockSize,blockSize);
};
Thisfunctionsetsthefontto20-pixelCourier(20pxCourier),setsitscolortoblackusingfillStyle,
left-alignsthetextwiththetextAlignproperty,andthensetsthetextBaselinepropertyto"top".
Next,wecallfillTextwiththestring"Score:"+score.
Thescorevariableholdstheplayer’scurrentscoreasanumber.Wesetthestartingscoreto0atthe
beginningofthegame(inDefiningthescoreVariable),soatfirstthiswilldisplay"Score:0".
WhenwecallfillText,wesetthex-andy-coordinatestoblockSize.SincewesetblockSizeto10,
thissetsthescore’sbaselinepointto(10,10),whichisjustinsidethetop-leftcorneroftheborder.And
sincewesettextBaselineto"top",thetextwillappearjustbelowthatbaselinepoint,asshownin
Figure16-10.
Figure16-10.Thepositionofthescoretext
EndingtheGame
We’llcallthegameOverfunctiontoendthegamewhenthesnakehitsthewallorrunsintoitself.The
gameOverfunctionusesclearIntervaltostopthegameandwritesthetext“GameOver”onthe
canvas.Here’swhatthegameOverfunctionlookslike:
vargameOver=function(){
clearInterval(intervalId);
ctx.font="60pxCourier";
ctx.fillStyle="Black";
ctx.textAlign="center";
ctx.textBaseline="middle";
ctx.fillText("GameOver",width/2,height/2);
};
FirstwestopthegamebycallingclearIntervalandpassinginthevariableintervalId.Thiscancels
thesetIntervalanimationfunctionthatwecreatedinUsingsetIntervaltoAnimatetheGame).
Next,wesetourfontto60-pixelCourierinblack,centerthetext,andsetthetextBaselinepropertyto
"middle".WethencallfillTextandtellittodrawthestring"GameOver"withwidth/2forthexpositionandheight/2forthey-position.Theresulting“GameOver”textwillbecenteredinthe
canvas,asshowninFigure16-11.
Figure16-11.The“GameOver”screen,afterthesnakehashittheleftwall
WhatYouLearned
Inthischapter,welookedatthegeneraloutlineofourSnakegameandsomeofthefunctionswe’llneed
tomakethegame.Youlearnedhowtodrawtextontoacanvasandhowtocustomizeitssize,font,and
position.
Inthenextchapter,we’llfinishoffourgamebywritingthecodeforthesnakeandtheappleandto
handlekeyboardevents.
ProgrammingChallenges
Hereareafewexercisesyoucantrybeforeyougoontofinishprogrammingthegame.
#1:PUTTINGITTOGETHER
AlthoughIhaven’tshownallthecodeforthegameyet,youcanrunthecodefordrawingtheborder
andthescore.TakeyourHTMLfile(fromCreatingtheHTML)andaddthecodeforsettingupthe
canvas,creatingthescore,drawingtheborder,anddrawingthescore.Nowyoujustneedtocall
drawBorderanddrawScoretoseetheborderandscore.ItshouldlookjustlikeFigure16-10.Youcan
tryoutthegameOverfunction,too,butbeforeyoucallthatfunction,you’llneedtodeletethe
clearInterval(intervalId);line.Youhaven’tcreatedtheintervalIdvariableyet,sofornow,if
youcallthefunctionwithoutremovingthatline,itwillproduceanerror.
#2:ANIMATINGTHESCORE
WriteyourowncalltosetIntervalwithafunctionthatincreasesthescoreby1andthendrawsthe
updatedscoreusingthedrawScorefunctionevery100milliseconds.Rememberthatyou’llneedto
clearthecanvaseachtime,usingtheclearRectmethodonthecanvascontext.
#3:ADDINGTEXTTOHANGMAN
Programmingchallenge#4inChapter13wastodrawthemaninourHangmangameusingcanvas.Try
extendingyourHangmangamebyusingthefillTextmethodtodrawthecurrentwordunderneaththe
hangman,asshown.
Hint:Tounderlineeachletter,I’veused30-pixel-longstrokedlines,with10pixelsbetweeneachone.
Forevenmoreofachallenge,drawtheincorrectguessescrossedout,asshowntotheright.
Chapter17.MakingaSnakeGame:Part2
Inthischapter,we’llfinishbuildingourSnakegame.InChapter16,wesetuptheplayingareaand
coveredhowthegamewouldworkingeneral.Nowwe’llcreatetheobjectsthatrepresentthesnakeand
appleinthegame,andwe’llprogramakeyboardeventhandlersothattheplayercancontrolthesnake
withthearrowkeys.Finally,we’lllookatthecompletecodelistingfortheprogram.
Aswecreatethesnakeandappleobjectsforthisgame,we’llusetheobject-orientedprogramming
techniqueswelearnedinChapter12tocreateconstructorsandmethodsforeachobject.Bothoursnake
andappleobjectswillrelyonamorebasicblockobject,whichwe’llusetorepresentoneblockonthe
gameboardgrid.Let’sstartbybuildingaconstructorforthatsimpleblockobject.
BuildingtheBlockConstructor
Inthissection,we’lldefineaBlockconstructorthatwillcreateobjectsthatrepresentindividualblocks
onourinvisiblegamegrid.Eachblockwillhavethepropertiescol(shortforcolumn)androw,which
willstorethelocationofthatparticularblockonthegrid.Figure17-1showsthisgridwithsomeofthe
columnsandrowsnumbered.Althoughthisgridwon’tactuallyappearonthescreen,ourgameis
designedsothattheappleandthesnakesegmentswillalwayslineupwithit.
Figure17-1.ThecolumnandrownumbersusedbytheBlockconstructor
InFigure17-1,theblockcontainingthegreenappleisatcolumn10,row10.Theheadofthesnake(to
theleftoftheapple)isatcolumn8,row10.
Here’sthecodefortheBlockconstructor:
varBlock=function(col,row){
this.col=col;
this.row=row;
};
ColumnandrowvaluesarepassedintotheBlockconstructorasargumentsandsavedinthecoland
rowpropertiesofthenewobject.
Nowwecanusethisconstructortocreateanobjectrepresentingaparticularblockonthegamegrid.
Forexample,here’showwe’dcreateanobjectthatrepresentstheblockincolumn5,row5:
varsampleBlock=newBlock(5,5);
AddingthedrawSquareMethod
Sofarthisblockobjectletsusrepresentalocationonthegrid,buttoactuallymakesomethingappearat
thatlocation,we’llneedtodrawitonthecanvas.Next,we’lladdtwomethods,drawSquareand
drawCircle,thatwillletusdrawasquareoracircle,respectively,inaparticularblockonthegrid.
First,here’sthedrawSquaremethod:
Block.prototype.drawSquare=function(color){
➊varx=this.col*blockSize;
➋vary=this.row*blockSize;
ctx.fillStyle=color;
ctx.fillRect(x,y,blockSize,blockSize);
};
InChapter12welearnedthatifyouattachmethodstotheprototypepropertyofaconstructor,those
methodswillbeavailabletoanyobjectscreatedwiththatconstructor.SobyaddingthedrawSquare
methodtoBlock.protoype,wemakeitavailabletoanyblockobjects.
Thismethoddrawsasquareatthelocationgivenbytheblock’scolandrowproperties.Ittakesasingle
argument,color,whichdeterminesthecolorofthesquare.Todrawasquarewithcanvas,weneedto
providethex-andy-positionsofthetop-leftcornerofthesquare.At➊and➋wecalculatethesex-and
y-valuesforthecurrentblockbymultiplyingthecolandrowpropertiesbyblockSize.Wethensetthe
fillStylepropertyofthedrawingcontexttothemethod’scolorargument.
Finally,wecallctx.fillRect,passingourcomputedx-andy-valuesandblockSizeforboththe
widthandheightofthesquare.
Here’showwewouldcreateablockincolumn3,row4,anddrawit:
varsampleBlock=newBlock(3,4);
sampleBlock.drawSquare("LightBlue");
Figure17-2showsthissquaredrawnonthecanvasandhowthemeasurementsforthesquareare
calculated.
Figure17-2.Calculatingthevaluesfordrawingasquare
AddingthedrawCircleMethod
NowforthedrawCirclemethod.ItisverysimilartothedrawSquaremethod,butitdrawsafilled
circleinsteadofasquare.
Block.prototype.drawCircle=function(color){
varcenterX=this.col*blockSize+blockSize/2;
varcenterY=this.row*blockSize+blockSize/2;
ctx.fillStyle=color;
circle(centerX,centerY,blockSize/2,true);
};
Firstwecalculatethelocationofthecircle’scenterbycreatingtwonewvariables,centerXand
centerY.Asbefore,wemultiplythecolandrowpropertiesbyblockSize,butthistimewealsohave
toaddblockSize/2,becauseweneedthepixelcoordinatesforthecircle’scenter,whichisinthe
middleofablock(asshowninFigure17-3).
WesetthecontextfillStyletothecolorargumentasindrawSquareandthencallourtrustycircle
function,passingcenterXandcenterYforthex-andy-coordinates,blockSize/2fortheradius,and
truetotellthefunctiontofillthecircle.ThisisthesamecirclefunctionwedefinedinChapter14,so
we’llhavetoincludethedefinitionforthatfunctiononceagaininthisprogram(asyoucanseeinthe
finalcodelisting).
Here’showwecoulddrawacircleincolumn4,row3:
varsampleCircle=newBlock(4,3);
sampleCircle.drawCircle("LightGreen");
Figure17-3showsthecircle,withthecalculationsforthecenterpointandradius.
Figure17-3.Calculatingthevaluesfordrawingacircle
AddingtheequalMethod
Inourgame,we’llneedtoknowwhethertwoblocksareinthesamelocation.Forexample,iftheapple
andthesnake’sheadareinthesamelocation,thatmeansthesnakehaseatentheapple.Ontheother
hand,ifthesnake’sheadandtailareinthesamelocation,thenthesnakehascollidedwithitself.
Tomakeiteasiertocompareblocklocations,we’lladdamethod,equal,totheBlockconstructor
prototype.Whenwecallequalononeblockobjectandpassanotherobjectasanargument,itwill
returntrueiftheyareinthesamelocation(andfalseifnot).Here’sthecode:
Block.prototype.equal=function(otherBlock){
returnthis.col===otherBlock.col&&this.row===otherBlock.row;
};
Thismethodisprettystraightforward:ifthetwoblocks(thisandotherBlock)havethesamecoland
rowproperties(thatis,ifthis.colisequaltootherBlock.colandthis.rowisequalto
otherBlock.row),thentheyareinthesameplace,andthemethodreturnstrue.
Forexample,let’screatetwonewblockscalledappleandheadandseeifthey’reinthesamelocation:
varapple=newBlock(2,5);
varhead=newBlock(3,5);
head.equal(apple);
false
Althoughappleandheadhavethesamerowproperty(5),theircolpropertiesaredifferent.Ifweset
theheadtoanewblockobjectonecolumntotheleft,nowthemethodwilltellusthatthetwoobjects
areinthesamelocation:
head=newBlock(2,5);
head.equal(apple);
true
Notethatitdoesn’tmakeanydifferencewhetherwewritehead.equal(apple)or
apple.equal(head);inbothcaseswe’remakingthesamecomparison.
We’llusetheequalmethodlatertocheckwhetherthesnakehaseatentheappleorcollidedwithitself.
CreatingtheSnake
Nowwe’llcreatethesnake.We’llstorethesnake’spositionasanarraycalledsegments,whichwill
containaseriesofblockobjects.Tomovethesnake,we’lladdanewblocktothebeginningofthe
segmentsarrayandremovetheblockattheendofthearray.Thefirstelementofthesegmentsarray
willrepresenttheheadofthesnake.
WritingtheSnakeConstructor
Firstweneedaconstructortocreateoursnakeobject:
varSnake=function(){
➊this.segments=[
newBlock(7,5),
newBlock(6,5),
newBlock(5,5)
];
➋this.direction="right";
➌this.nextDirection="right";
};
DefiningtheSnakeSegments
Thesegmentspropertyat➊isanarrayofblockobjectsthateachrepresentasegmentofthesnake’s
body.Whenwestartthegame,thisarraywillcontainthreeblocksat(7,5),(6,5),and(5,5).Figure174showstheseinitialthreesegmentsofthesnake.
Figure17-4.Theinitialblocksthatmakeupthesnake
SettingtheDirectionofMovement
Thedirectionpropertyat➋storesthecurrentdirectionofthesnake.Ourconstructoralsoaddsthe
nextDirectionpropertyat➌,whichstoresthedirectioninwhichthesnakewillmoveforthenext
animationstep.Thispropertywillbeupdatedbyourkeydowneventhandlerwhentheplayerpressesan
arrowkey(seeAddingthekeydownEventHandler).Fornow,theconstructorsetsbothofthese
propertiesto"right",soatthebeginningofthegameoursnakewillmovetotheright.
DrawingtheSnake
Todrawthesnake,wesimplyhavetoloopthrougheachoftheblocksinitssegmentsarray,callingthe
drawSquaremethodwecreatedearlieroneachblock.Thiswilldrawasquareforeachsegmentofthe
snake.
Snake.prototype.draw=function(){
for(vari=0;i<this.segments.length;i++){
this.segments[i].drawSquare("Blue");
}
};
Thedrawmethodusesaforlooptooperateoneachblockobjectinthesegmentsarray.Eachtime
aroundtheloop,thiscodetakesthecurrentsegment(this.segments[i])andcalls
drawSquare("Blue")onit,whichdrawsabluesquareinthecorrespondingblock.
Ifyouwanttotestoutthedrawmethod,youcanrunthefollowingcode,whichcreatesanewobject
usingtheSnakeconstructorandcallsitsdrawmethod:
varsnake=newSnake();
snake.draw();
MovingtheSnake
We’llcreateamovemethodtomovethesnakeoneblockinitscurrentdirection.Tomovethesnake,we
addanewheadsegment(byaddinganewblockobjecttothebeginningofthesegmentsarray)and
thenremovethetailsegmentfromtheendofthesegmentsarray.
Themovemethodwillalsocallamethod,checkCollision,toseewhetherthenewheadhascollided
withtherestofthesnakeorwiththewall,andwhetherthenewheadhaseatentheapple.Ifthenew
headhascollidedwiththebodyorthewall,weendthegamebycallingthegameOverfunctionwe
createdinChapter16.Ifthesnakehaseatentheapple,weincreasethescoreandmovetheappletoa
newlocation.
AddingthemoveMethod
Themovemethodlookslikethis:
Snake.prototype.move=function(){
➊varhead=this.segments[0];
➋varnewHead;
➌this.direction=this.nextDirection;
➍if(this.direction==="right"){
newHead=newBlock(head.col+1,head.row);
}elseif(this.direction==="down"){
newHead=newBlock(head.col,head.row+1);
}elseif(this.direction==="left"){
newHead=newBlock(head.col-1,head.row);
}elseif(this.direction==="up"){
newHead=newBlock(head.col,head.row-1);
}
➎if(this.checkCollision(newHead)){
gameOver();
return;
}
➏this.segments.unshift(newHead);
➐if(newHead.equal(apple.position)){
score++;
apple.move();
}else{
this.segments.pop();
}
};
Let’swalkthroughthismethodpiecebypiece.
CreatingaNewHead
At➊wesavethefirstelementofthethis.segmentsarrayinthevariablehead.We’llrefertothisfirst
segmentofthesnakemanytimesinthismethod,sousingthisvariablewillsaveussometypingand
makethecodeabiteasiertoread.Now,insteadofrepeatingthis.segments[0]overandoveragain,
wecanjusttypehead.
At➋wecreatethevariablenewHead,whichwe’llusetostoretheblockrepresentingthenewheadof
thesnake(whichwe’reabouttoadd).
At➌wesetthis.directionequaltothis.nextDirection,whichupdatesthedirectionofthe
snake’smovementtomatchthemostrecentlypressedarrowkey.(We’llseehowthisworksinmore
detailwhenwelookatthekeydowneventhandler.)
DIRECTIONANDNEXTDIRECTION
Thesnake’sdirectionpropertywillbeupdatedexactlyonceforeachstepintheanimation,sincethemovemethodiscalledonceper
animationstep.ThenextDirectionproperty,ontheotherhand,willbeupdatedanytimetheplayerpressesanarrowkey(soifthey
pressthekeysreallyfast,thispropertycouldtheoreticallychangemultipletimesperanimationstep).Bykeepingthesetwoproperties
separate,wemakesurethesnakecan’tturnbackonitselfiftheplayerpressestwoarrowkeysveryquicklybetweentwostepsinthe
animation.
Beginningat➍,weuseachainofif...elsestatementstodeterminethesnake’sdirection.Ineach
case,wecreateanewheadforthesnakeandsaveitinthevariablenewHead.Dependingonthe
directionofmovement,weaddorsubtractonefromtheroworcolumnoftheexistingheadtoplacethis
newheaddirectlynexttotheoldone(eitherright,left,up,ordowndependingonthesnake’sdirection
ofmovement).Forexample,Figure17-5showshowthenewheadisaddedtothesnakewhen
this.nextDirectionissetto"down".
Figure17-5.CreatingnewHeadwhenthis.nextDirectionis"down"
CheckingforCollisionsandAddingtheHead
At➎wecallthecheckCollisionmethodtofindoutwhetherthesnakehascollidedwithawallor
withitself.We’llseethecodeforthismethodinamoment,butasyoumightguess,thismethodwill
returntrueifthesnakehascollidedwithsomething.Ifthathappens,thebodyoftheifstatementcalls
thegameOverfunctiontoendthegameandprint“GameOver”onthecanvas.
ThereturnkeywordthatfollowsthecalltogameOverexitsthemovemethodearly,skippinganycode
thatcomesafterit.WereachthereturnkeywordonlyifcheckCollisionreturnstrue,soifthesnake
hasn’tcollidedwithanything,weexecutetherestofthemethod.
Aslongasthesnakehasn’tcollidedwithsomething,weaddthenewheadtothefrontofthesnakeat➏
byusingunshifttoaddnewHeadtothebeginningofthesegmentsarray.Formoreabouthowthe
unshiftmethodworksonarrays,seeAddingElementstoanArray.
EatingtheApple
At➐,weusetheequalmethodtocomparenewHeadandapple.position.Ifthetwoblocksareinthe
samelocation,theequalmethodwillreturntrue,whichmeansthatthesnakehaseatentheapple.
Ifthesnakehaseatentheapple,weincreasethescoreandthencallmoveontheappletomoveittoa
newlocation.Ifthesnakehasnoteatentheapple,wecallpoponthis.segments.Thisremovesthe
snake’stailwhilekeepingthesnakethesamesize(sincemovealreadyaddedasegmenttothesnake’s
head).Whenthesnakeeatsanapple,itgrowsbyonesegmentbecauseweaddasegmenttoitshead
withoutremovingthetail.
Wehaven’tdefinedappleyet,sothismethodwon’tfullyworkinitscurrentform.Ifyouwanttotestit
out,youcandeletethewholeif...elsestatementat➐andreplaceitwiththisline:
this.segments.pop();
ThenallyouneedtodoisdefinethecheckCollisionmethod,whichwe’lldonext.
AddingthecheckCollisionMethod
Eachtimewesetanewlocationforthesnake’shead,wehavetocheckforcollisions.Collision
detection,averycommonstepingamemechanics,isoftenoneofthemorecomplexaspectsofgame
programming.Fortunately,it’srelativelystraightforwardinourSnakegame.
WecareabouttwotypesofcollisionsinourSnakegame:collisionswiththewallandcollisionswiththe
snakeitself.Awallcollisionhappensifthesnakehitsawall.Thesnakecancollidewithitselfifyou
turntheheadsothatitrunsintothebody.Atthestartofthegame,thesnakeistooshorttocollidewith
itself,butaftereatingafewapples,itcan.
HereisthecheckCollisionmethod:
Snake.prototype.checkCollision=function(head){
➊varleftCollision=(head.col===0);
vartopCollision=(head.row===0);
varrightCollision=(head.col===widthInBlocks-1);
varbottomCollision=(head.row===heightInBlocks-1);
➋varwallCollision=leftCollision||topCollision||
rightCollision||bottomCollision;
➌varselfCollision=false;
➍for(vari=0;i<this.segments.length;i++){
if(head.equal(this.segments[i])){
➎selfCollision=true;
}
}
➏returnwallCollision||selfCollision;
};
CheckingforWallCollisions
At➊wecreatethevariableleftCollisionandsetittothevalueofhead.col===0.Thisvariable
willbetrueifthesnakecollideswiththeleftwall;thatis,whenitisincolumn0.Similarly,the
variabletopCollisioninthenextlinecheckstherowofthesnake’sheadtoseeifithasrunintothe
topwall.
Afterthat,wecheckforacollisionwiththerightwallbycheckingwhetherthecolumnvalueofthe
headisequaltowidthInBlocks-1.SincewidthInBlocksissetto40,thischeckswhetherthehead
isincolumn39,whichcorrespondstotherightwall,asyoucanseebackinFigure17-1.Thenwedo
thesamethingforbottomCollision,checkingwhetherthehead’srowpropertyisequalto
heightInBlocks-1.
At➋,wedeterminewhetherthesnakehascollidedwithawallbycheckingtoseeifleftCollisionor
topCollisionorrightCollisionorbottomCollisionistrue,usingthe||(or)operator.Wesave
theBooleanresultinthevariablewallCollision.
CheckingforSelf-Collisions
Todeterminewhetherthesnakehascollidedwithitself,wecreateavariableat➌called
selfCollisionandinitiallysetittofalse.Thenat➍weuseaforlooptoloopthroughallthe
segmentsofthesnaketodeterminewhetherthenewheadisinthesameplaceasanysegment,using
head.equal(this.segments[i]).Theheadandalloftheothersegmentsareblocks,sowecanusethe
equalmethodthatwedefinedforblockobjectstoseewhethertheyareinthesameplace.Ifwefind
thatanyofthesnake’ssegmentsareinthesameplaceasthenewhead,weknowthatthesnakehas
collidedwithitself,andwesetselfCollisiontotrue(at➎).
Finally,at➏,wereturnwallCollision||selfCollision,whichwillbetrueifthesnakehas
collidedwitheitherthewalloritself.
SettingtheSnake’sDirectionwiththeKeyboard
Nextwe’llwritethecodethatletstheplayersetthesnake’sdirectionusingthekeyboard.We’lladda
keydowneventhandlertodetectwhenanarrowkeyhasbeenpressed,andwe’llsetthesnake’sdirection
tomatchthatkey.
AddingthekeydownEventHandler
Thiscodehandleskeyboardevents:
➊vardirections={
37:"left",
38:"up",
39:"right",
40:"down"
};
➋$("body").keydown(function(event){
varnewDirection=directions[event.keyCode];
➌if(newDirection!==undefined){
snake.setDirection(newDirection);
}
});
At➊wecreateanobjecttoconvertthearrowkeycodesintostringsindicatingthedirectionthey
represent(thisobjectisquitesimilartothekeyActionsobjectweusedinReactingtotheKeyboard).
At➋weattachaneventhandlertothekeydowneventonthebodyelement.Thishandlerwillbecalled
whentheuserpressesakey(aslongasthey’veclickedinsidethewebpagefirst).
Thishandlerfirstconvertstheevent’skeycodeintoadirectionstring,andthenitsavesthestringinthe
variablenewDirection.Ifthekeycodeisnot37,38,39,or40(thekeycodesforthearrowkeyswecare
about),directions[event.keyCode]willbeundefined.
At➌wechecktoseeifnewDirectionisnotequaltoundefined.Ifit’snotundefined,wecallthe
setDirectionmethodonthesnake,passingthenewDirectionstring.(Becausethereisnoelsecase
inthisifstatement,ifnewDirectionisundefined,thenwejustignorethekeypress.)
Thiscodewon’tworkyetbecausewehaven’tdefinedthesetDirectionmethodonthesnake.Let’sdo
thatnow.
AddingthesetDirectionMethod
ThesetDirectionmethodtakesthenewdirectionfromthekeyboardhandlerwejustlookedatand
usesittoupdatethesnake’sdirection.Thismethodalsopreventstheplayerfrommakingturnsthat
wouldhavethesnakeimmediatelyrunintoitself.Forexample,ifthesnakeismovingright,andthenit
suddenlyturnsleftwithoutmovingupordowntogetoutofitsownway,itwillcollidewithitself.We’ll
calltheseillegalturnsbecausewedonotwanttoallowtheplayertomakethem.Forexample,
Figure17-6showsthevaliddirectionsandtheoneillegaldirectionwhenthesnakeismovingright.
Figure17-6.Validnewdirectionsbasedonthecurrentdirection
ThesetDirectionmethodcheckswhethertheplayeristryingtomakeanillegalturn.Iftheyare,the
methodusesreturntoendearly;otherwise,itupdatesthenextDirectionpropertyonthesnake
object.
Here’sthecodeforthesetDirectionmethod.
Snake.prototype.setDirection=function(newDirection){
➊if(this.direction==="up"&&newDirection==="down"){
return;
}elseif(this.direction==="right"&&newDirection==="left"){
return;
}elseif(this.direction==="down"&&newDirection==="up"){
return;
}elseif(this.direction==="left"&&newDirection==="right"){
return;
}
➋this.nextDirection=newDirection;
};
Theif...elsestatementat➊hasfourpartstodealwiththefourillegalturnswewanttoprevent.The
firstpartsaysthatifthesnakeismovingup(this.directionis"up")andtheplayerpressesthedown
arrow(newDirectionis"down"),weshouldexitthemethodearlywithreturn.Theotherpartsofthe
statementdealwiththeotherillegalturnsinthesameway.
ThesetDirectionmethodwillreachthefinallineonlyifnewDirectionisavalidnewdirection;
otherwise,oneofthereturnstatementswillstopthemethod.
IfnewDirectionisallowed,wesetitasthesnake’snextDirectionproperty,at➋.
CreatingtheApple
Inthisgame,we’llrepresenttheappleasanobjectwiththreecomponents:apositionproperty,which
holdstheapple’spositionasablockobject;adrawmethod,whichwe’llusetodrawtheapple;anda
movemethod,whichwe’llusetogivetheappleanewpositiononceit’sbeeneatenbythesnake.
WritingtheAppleConstructor
Theconstructorsimplysetstheapple’spositionpropertytoanewblockobject.
varApple=function(){
this.position=newBlock(10,10);
};
Thiscreatesanewblockobjectincolumn10,row10,andassignsittotheapple’spositionproperty.
We’llusethisconstructortocreateanappleobjectatthebeginningofthegame.
DrawingtheApple
We’llusethisdrawmethodtodrawtheapple:
Apple.prototype.draw=function(){
this.position.drawCircle("LimeGreen");
};
Theapple’sdrawmethodisverysimple,asallthehardworkisdonebythedrawCirclemethod
(createdinAddingthedrawCircleMethod).Todrawtheapple,wesimplycallthedrawCirclemethod
ontheapple’spositionproperty,passingthecolor"LimeGreen"totellittodrawagreencircleinthe
givenblock.
Totestoutdrawingtheapple,runthefollowingcode:
varapple=newApple();
apple.draw();
MovingtheApple
Themovemethodmovestheappletoarandomnewpositionwithinthegamearea(thatis,anyblockon
thecanvasotherthantheborder).We’llcallthismethodwheneverthesnakeeatstheapplesothatthe
applereappearsinanewlocation.
Apple.prototype.move=function(){
➊varrandomCol=Math.floor(Math.random()*(widthInBlocks-2))+1;
varrandomRow=Math.floor(Math.random()*(heightInBlocks-2))+1;
➋this.position=newBlock(randomCol,randomRow);
};
At➊wecreatethevariablesrandomColandrandomRow.Thesevariableswillbesettoarandom
columnandrowvaluewithintheplayablearea.AsyousawinFigure17-1,thecolumnsandrowsfor
theplayablearearangefrom1to38,soweneedtopicktworandomnumbersinthatrange.
Togeneratetheserandomnumbers,wecancallMath.floor(Math.random()*38),whichgivesus
arandomnumberfrom0to37,andthenadd1totheresulttogetanumberbetween1and38(formore
abouthowMath.floorandMath.randomwork,seeDecisionMaker).
Thisisexactlywhatwedoat➊tocreateourrandomcolumnvalue,butinsteadofwriting38,wewrite
(widthInBlocks-2).Thismeansthatifwelaterchangethesizeofthegame,wewon’talsohaveto
changethiscode.Wedothesamethingtogetarandomrowvalue,usingMath.floor(Math.random()
*(heightInBlocks-2))+1.
Finally,at➋wecreateanewblockobjectwithourrandomcolumnandrowvaluesandsavethisblock
inthis.position.Thismeansthatthepositionoftheapplewillbeupdatedtoanewrandomlocation
somewherewithintheplayingarea.
Youcantestoutthemovemethodlikethis:
varapple=newApple();
apple.move();
apple.draw();
PuttingItAllTogether
Ourfullcodeforthegamecontainsalmost200linesofJavaScript!Afterweassemblethewholething,
itlookslikethis.
//Setupcanvas
➊varcanvas=document.getElementById("canvas");
varctx=canvas.getContext("2d");
//Getthewidthandheightfromthecanvaselement
varwidth=canvas.width;
varheight=canvas.height;
//Workoutthewidthandheightinblocks
varblockSize=10;
varwidthInBlocks=width/blockSize;
varheightInBlocks=height/blockSize;
//Setscoreto0
varscore=0;
//Drawtheborder
➋vardrawBorder=function(){
ctx.fillStyle="Gray";
ctx.fillRect(0,0,width,blockSize);
ctx.fillRect(0,height-blockSize,width,blockSize);
ctx.fillRect(0,0,blockSize,height);
ctx.fillRect(width-blockSize,0,blockSize,height);
};
//Drawthescoreinthetop-leftcorner
vardrawScore=function(){
ctx.font="20pxCourier";
ctx.fillStyle="Black";
ctx.textAlign="left";
ctx.textBaseline="top";
ctx.fillText("Score:"+score,blockSize,blockSize);
};
//CleartheintervalanddisplayGameOvertext
vargameOver=function(){
clearInterval(intervalId);
ctx.font="60pxCourier";
ctx.fillStyle="Black";
ctx.textAlign="center";
ctx.textBaseline="middle";
ctx.fillText("GameOver",width/2,height/2);
};
//Drawacircle(usingthefunctionfromChapter14)
varcircle=function(x,y,radius,fillCircle){
ctx.beginPath();
ctx.arc(x,y,radius,0,Math.PI*2,false);
if(fillCircle){
ctx.fill();
}else{
ctx.stroke();
}
};
//TheBlockconstructor
➌varBlock=function(col,row){
this.col=col;
this.row=row;};
//Drawasquareattheblock'slocation
Block.prototype.drawSquare=function(color){varx=this.col*blockSize;
vary=this.row*blockSize;
ctx.fillStyle=color;
ctx.fillRect(x,y,blockSize,blockSize);
};
//Drawacircleattheblock'slocation
Block.prototype.drawCircle=function(color){
varcenterX=this.col*blockSize+blockSize/2;
varcenterY=this.row*blockSize+blockSize/2;
ctx.fillStyle=color;
circle(centerX,centerY,blockSize/2,true);};
//Checkifthisblockisinthesamelocationasanotherblock
Block.prototype.equal=function(otherBlock){
returnthis.col===otherBlock.col&&this.row===otherBlock.row;
};
//TheSnakeconstructor
➍varSnake=function(){
this.segments=[
newBlock(7,5),
newBlock(6,5),
newBlock(5,5)
];
this.direction="right";
this.nextDirection="right";
};
//Drawasquareforeachsegmentofthesnake'sbody
Snake.prototype.draw=function(){
for(vari=0;i<this.segments.length;i++){
this.segments[i].drawSquare("Blue");
}
};
//Createanewheadandaddittothebeginningof
//thesnaketomovethesnakeinitscurrentdirection
Snake.prototype.move=function(){
varhead=this.segments[0];
varnewHead;
this.direction=this.nextDirection;
if(this.direction==="right"){
newHead=newBlock(head.col+1,head.row);
}elseif(this.direction==="down"){
newHead=newBlock(head.col,head.row+1);
}elseif(this.direction==="left"){
newHead=newBlock(head.col-1,head.row);
}elseif(this.direction==="up"){
newHead=newBlock(head.col,head.row-1);
}
if(this.checkCollision(newHead)){
gameOver();
return;
}
this.segments.unshift(newHead);
if(newHead.equal(apple.position)){
score++;
apple.move();
}else{
this.segments.pop();
}
};
//Checkifthesnake'snewheadhascollidedwiththewalloritself
Snake.prototype.checkCollision=function(head){
varleftCollision=(head.col===0);
vartopCollision=(head.row===0);
varrightCollision=(head.col===widthInBlocks-1);
varbottomCollision=(head.row===heightInBlocks-1);
varwallCollision=leftCollision||topCollision||
rightCollision||bottomCollision;
varselfCollision=false;
for(vari=0;i<this.segments.length;i++){
if(head.equal(this.segments[i])){
selfCollision=true;
}
}
returnwallCollision||selfCollision;
};
//Setthesnake'snextdirectionbasedonthekeyboard
Snake.prototype.setDirection=function(newDirection){
if(this.direction==="up"&&newDirection==="down"){
return;
}elseif(this.direction==="right"&&newDirection==="left"){
return;
}elseif(this.direction==="down"&&newDirection==="up"){
return;
}elseif(this.direction==="left"&&newDirection==="right"){
return;
}
this.nextDirection=newDirection;
};
//TheAppleconstructor
➎varApple=function(){
this.position=newBlock(10,10);
};
//Drawacircleattheapple'slocation
Apple.prototype.draw=function(){
this.position.drawCircle("LimeGreen");
};
//Movetheappletoanewrandomlocation
Apple.prototype.move=function(){
varrandomCol=Math.floor(Math.random()*(widthInBlocks-2))+1;
varrandomRow=Math.floor(Math.random()*(heightInBlocks-2))+1;
this.position=newBlock(randomCol,randomRow);
};
//Createthesnakeandappleobjects
➏varsnake=newSnake();
varapple=newApple();
//PassananimationfunctiontosetInterval
varintervalId=setInterval(function(){
ctx.clearRect(0,0,width,height);
drawScore();
snake.move();
snake.draw();
apple.draw();
drawBorder();
},100);
//Convertkeycodestodirections
➐vardirections={
37:"left",
38:"up",
39:"right",
40:"down"
};
//Thekeydownhandlerforhandlingdirectionkeypresses
$("body").keydown(function(event){
varnewDirection=directions[event.keyCode];
if(newDirection!==undefined){
snake.setDirection(newDirection);
}
});
Thiscodeismadeupofanumberofsections.Thefirstsection,at➊,iswhereallthevariablesforthe
gamearesetup,includingthecanvas,context,width,andheight(welookedattheseinChapter16).
Next,at➋,comealltheindividualfunctions:drawBorder,drawScore,gameOver,andcircle.
At➌comesthecodefortheBlockconstructor,followedbyitsdrawSquare,drawCircle,andequal
methods.Then,at➍,wehavetheSnakeconstructorandallofitsmethods.Afterthat,at➎,isthe
Appleconstructoranditsdrawandmovemethods.
Finally,at➏,youcanseethecodethatstartsthegameandkeepsitrunning.Firstwecreatethesnake
andappleobjects.ThenweusesetIntervaltogetthegameanimationgoing.Noticethatwhenwe
callsetInterval,wesavetheintervalIDinthevariableintervalIdsowecancancelitlaterinthe
gameOverfunction.
ThefunctionpassedtosetIntervaliscalledforeverystepofthegame.Itisresponsiblefordrawing
everythingonthecanvasandforupdatingthestateofthegame.Itclearsthecanvasandthendrawsthe
score,thesnake,theapple,andtheborder.Italsocallsthemovemethodonthesnake,which,asyou
sawearlier,movesthesnakeonestepinitscurrentdirection.AfterthecalltosetInterval,at➐,we
endwiththecodeforlisteningtokeyboardeventsandsettingthesnake’sdirection.
Asalways,you’llneedtotypeallthiscodeinsidethescriptelementinyourHTMLdocument.To
playthegame,justloadsnake.htmlinyourbrowserandusethearrowstocontrolthesnake’sdirection.
Ifthearrowkeysdon’twork,youmightneedtoclickinsidethebrowserwindowtomakesureitcan
pickupthekeyevents.
Ifthegamedoesn’twork,theremightbeanerrorinyourJavaScript.Anyerrorwillbeoutputinthe
console,solookthereforanyhelpfulmessages.Ifyoucan’tdeterminewhythingsaren’tworking,
checkeachlinecarefullyagainsttheprecedinglisting.
Nowthatyouhavethegamerunning,whatdoyouthink?Howhighascorecanyouget?
WhatYouLearned
Inthischapter,wemadeafullgameusingthecanvaselement.Thisgamecombinesmanyofthedata
types,concepts,andtechniquesyoulearnedthroughoutthisbook:numbers,strings,Booleans,arrays,
objects,controlstructures,functions,object-orientedprogramming,eventhandlers,setInterval,and
drawingwithcanvas.
Nowthatyou’veprogrammedthisSnakegame,therearelotsofothersimpletwo-dimensionalgames
thatyoucouldwriteusingJavaScript.Youcouldmakeyourownversionofclassicgameslike
Breakout,Asteroids,SpaceInvaders,orTetris.Oryoucouldmakeupyourowngame!
Ofcourse,youcanuseJavaScriptforprogramsbesidesgames.Nowthatyou’veusedJavaScripttodo
somecomplicatedmath,youcoulduseittohelpwithyourmathhomework.Ormaybeyouwantto
createawebsitetoshowoffyourprogrammingskillstotheworld.Thepossibilitiesareendless!
ProgrammingChallenges
Hereareafewwaysyoucouldimproveandaddfeaturestothegame.
#1:MAKINGTHEGAMEBIGGER
Changethesizeofthegameto500pixelssquare.Wheredoyouneedtomodifythecodetomakeit
workat500pixels?
#2:COLORINGTHESNAKE
Oursnakeisabitboring:everysegmentofthebodyisblue.Itmightlookabitmorelikearealsnakeif
youalternatedthecolorstocreatestripes.Forexample,maketheheadgreenandthenalternatebetween
blueandyellowfortherestofthebody,orchooseyourowncolors.
#3:MAKINGTHEGAMESPEEDUPASYOUPLAY
Modifythegamesothateverytimethesnakeeatsanapple,thegamespeedsup.Todothis,you’llhave
tochangethecodetousesetTimeoutinsteadofsetInterval,becausesetIntervalkeepscallinga
functionataregularintervalthatcannotbechanged.Instead,youcanrepeatedlycallafunctionwith
setTimeoutandchangethetimeoutdelayeachtimeyoucallit:
varanimationTime=100;
vargameLoop=function(){
//Thecodethatdrawsandupdatesthegameshouldgohere
setTimeout(gameLoop,animationTime);
};
gameLoop();
InsteadofusingsetIntervaltocallafunctionrepeatedly,thegameLoopfunctioncalls
setTimeout(gameLoop,animationTime),whichmeans“callgameLoopagainafteranimationTime
milliseconds.”LikesetInterval,thisisawaytocallafunctionoverandoveragain,withashort
pausebetweeneachfunctioncall.Thedifferenceisthatyoucaneasilymodifytheanimationtimefrom
anywhereinyourcodebychanginganimationTime,andtheprogramwillusethatvalueforsubsequent
callstosetTimeout.
(Oneotherthingtobearinmindhereisthatyouneedtofindanewwaytostopthegamefromlooping
whenthegameisover.Howwouldyoudothat?)
#4:FIXINGTHEAPPLE.MOVEMETHOD
Everytimeyoumovetheapple,itmovestoanewrandomlocation,butaswrittenthere’snothingto
stoptheapplefrommovingtoablockthatpartofthesnakeisalreadyoccupying.Topreventthis,
modifythemovemethodtotakeintoaccountthecurrentlocationsofthesnake’ssegments.(Hint:Usea
whilelooptokeepcallingmoveuntilitpicksalocationthat’snotoccupiedbythesnake.)
Afterword:WhereToGoFromHere
Nowthatyou’velearnedthebasicsofJavaScript,you’rereadytoventureoutintoawhole,wideworld
ofprogramming.Youcouldlearnanotherprogramminglanguage,oryoucouldchoosetobuildonyour
knowledgeofJavaScript,takingyourskillstothenextlevel.Whereyougonextisentirelyuptoyou,
butherearesomeideas.
MoreJavaScript
We’velookedatalotofJavaScriptinthisbook,butthere’smuchmoreyoucanlearnaboutthe
language.HerearesomebooksandwebsitesthatwillhelpyoulearnmoreofthedetailsofJavaScript:
JavaScript:TheGoodPartsbyDouglasCrockford(O’ReillyMedia,2008)
EloquentJavaScript,2ndEdition,byMarijnHaverbeke(NoStarchPress,2014)
JavaScript:TheDefinitiveGuide,4thEdition,byDavidFlanagan(O’ReillyMedia,2001)
TheMozillaDeveloperNetwork’sJavaScriptresources:https://developer.mozilla.org/enUS/docs/Web/JavaScript/
CodecademyJavaScriptcourses:http://www.codecademy.com/en/tracks/javascript/
WebProgramming
Tocreatewebsites,youneedtousesomeHTMLandCSS,alongwithJavaScript.
HTML
HTMListhemarkuplanguageusedforcreatingwebpages.WelearnedsomebasicHTMLin
Chapter5,butthere’smuchmoretolearn.HerearesomeplacesyoucanlearnmoreaboutHTML:
TheMozillaDeveloperNetwork’sIntroductiontoHTML:https://developer.mozilla.org/enUS/docs/Web/Guide/HTML/Introduction/
CodecademyHTML&CSScourse:http://www.codecademy.com/tracks/web/
MozillaWebmaker:https://webmaker.org/
CSS
CSS(shortforCascadingStyleSheets)isthelanguageusedtocontroltheappearanceofwebpages.
LearnmoreaboutCSShere:
TheMozillaDeveloperNetwork’sGettingStartedwithCSS:https://developer.mozilla.org/enUS/docs/Web/Guide/CSS/Getting_started/
CodecademyHTML&CSScourse:http://www.codecademy.com/tracks/web/
Server-SideCodewithNode.js
Webpagesliveonwebservers.AserverstoresalltheHTML,CSS,andJavaScriptforawebpage,and
itallowspeopletoaccessthepagefromtheInternet.Youcanalsowriteprogramsfortheserver(called
server-sidecode)tomaketheservergeneratenewHTMLfileseachtimeawebpageisloaded.For
example,whenyouvisithttp://twitter.com/,aprogramrunsonaserverthatfindsthelatesttweetsfor
yourfeed,generatesanHTMLfilecontainingthosetweets,andsendsthatfiletoyourbrowser.
Node.jsletsyouwriteserver-sidecodeinJavaScript.FindoutmoreaboutNode.jswiththeselinks:
Node.jsdocumentation:http://nodejs.org/
TheNodeBeginnerBook:http://www.nodebeginner.org/
GraphicalProgramming
IfyouwanttomakeinteractivegraphicsinJavaScript,youhavetwomainoptions:thecanvaselement
andSVG.
Canvas
Welearnedthebasicsofthecanvaselementinthisbook,butthere’smuchmoreyoucandowithit.
Herearesometutorialsandgamesyoucanusetolearnmore:
TheMozillaDeveloperNetwork’sCanvasTutorial:https://developer.mozilla.org/enUS/docs/Web/API/Canvas_API/Tutorial/
CodeMonsterfromCrunchzilla:http://www.crunchzilla.com/code-monster/
SVGUsingRaphaël
SVGisanimageformatthatletsyoudrawshapesandanimatethemwithoutredrawingfromscratchfor
eachanimationstep.SVGprogrammingcanbedifficulttogetthehangof,butit’smucheasierifyou
usetheJavaScriptlibrarycalledRaphaël.HerearesomeresourcesforlearningRaphaël:
Raphaëlwebsite:http://raphaeljs.com/
AnIntroductiontotheRaphaëlJSLibrary:http://code.tutsplus.com/tutorials/an-introduction-tothe-raphael-js-library--net-7186/
3DProgramming
RememberhowinChapter13wetoldcanvaswewantedtomakea2Ddrawingcontextbycalling
canvas.getContext("2d")?It’salsopossibletodo3Dgraphicsusingcanvas.Thisisanotheroneof
thoseareaswhereit’seasiertousealibrary,soI’drecommendusingthelibrarythree.js.Herearesome
resourcesforlearningthree.js:
three.jsManual:http://threejs.org/docs/index.html#Manual
TheBeginner’sGuidetothree.js:http://blog.teamtreehouse.com/the-beginners-guide-to-three-js/
ProgrammingRobots
YoucanevencontrolrobotsusingJavaScript!Forexample,theParrotAR.Droneisasmallflying
helicopterthatyoucancontrolusingNode.js.OryoucancheckoutJohnny-Five,aJavaScriptlibrary
thatletsyouuseNode.jstocontroldevicessuchastheArduino(apopularmicrocontrollerthat’susedin
lotsofhomemadeelectronicsandroboticsprojects).Herearesomeresourcesforlearninghowto
controlrobotsandotherdeviceswithJavaScript:
node-ar-drone:https://github.com/felixge/node-ar-drone/
NodeCopter:http://nodecopter.com/
NodeBots:http://nodebots.io/
Johnny-Five:https://github.com/rwaldron/johnny-five/
AudioProgramming
JavaScriptalsoallowsyoutodoadvancedaudioprogramminginwebbrowsersusingtheWebAudio
API(shortforapplicationprogramminginterface).YoucanusetheWebAudioAPItomakesound
effectsorevencreateyourownmusic!HerearesomeresourcesforlearningmoreabouttheWebAudio
API:
TheMozillaDeveloperNetwork’sWebAudioAPI:https://developer.mozilla.org/enUS/docs/Web/API/Web_Audio_API/
HTML5Rocks:GettingStartedwithWebAudioAPI:
http://www.html5rocks.com/en/tutorials/webaudio/intro/
GameProgramming
IfyouwanttodomoregameprogramminginJavaScript,youmightwanttotryusingagameengine.A
gameengineisacollectionofcodethathandlesalotofthelower-levelconcernsofthegame(like
keyboardandmouseinput),allowingyoutoconcentrateonthepartsthatmakeyourgamedifferent.
Herearesomeresourcesyoucancheckouttolearnmoreaboutgameprogrammingandgameengines:
Craftygameengine:http://craftyjs.com/
PixiRenderer:https://github.com/GoodBoyDigital/pixi.js
HTML5GameEngines:http://html5gameengine.com/
UdacityHTML5GameDevelopment:https://www.udacity.com/course/cs255
3DGameProgrammingforKidsbyChrisStrom(PragmaticProgrammers,2013)
SharingYourCodeUsingJSFiddle
WhatifyouwanttoshareallthegreatJavaScriptyou’vewrittenwiththeworld?Therearemanyways
todothat.OneoftheeasieronesisJSFiddle(http://jsfiddle.net/).JusttypeyourJavaScriptinthe
JavaScriptbox,addanyHTMLyouwantintheHTMLbox,andthenclickRuntorunyourprogram.
Toshareit,clickSave,whichgivesyouaURLthatyoucanthensharewithanyone.
Glossary
Theworldofcomputerprogramminghasallkindsofspecialtermsanddefinitionsthatcantakesome
timetogetthehangof.Inthisglossary,you’llfinddefinitionsformanyoftheprogrammingtermsused
inthisbook.Asyou’rereadingthisbook,ifyoucomeacrossatermthatyoudon’tquiteunderstand,
youcanlookhereforabriefexplanation.
argument
Avaluethatcanbepassedintoafunction.
array
AlistofJavaScriptvalues.Inanarray,eachvaluehasanindex,whichisthenumberedpositionof
thatvalueinthearray.Thefirstvalueisatindex0,thenextvalueisatindex1,andsoon.
attribute
Akey-valuepairinanHTMLelement.YoucanuseHTMLattributestocontrolcertainaspectsofan
element,likewheretheelementlinkstoorthesizeoftheelement.
Boolean
Avaluethatcanbeeithertrueorfalse.
call
Toexecuteorrunafunction.TocallfunctionsinJavaScript,youenterthefunctionnamefollowedby
apairofparentheses(withanyargumentsinsidetheparentheses).
camelcase
Acommonwaytonamevariablesinwhichyoucapitalizethefirstletterofeachword(exceptthe
firstword)andthenjoinallthewordstomakeonelongword,likeso:myCamelCaseVariable.
comment
TextinaprogramthatisnotexecutedbytheJavaScriptinterpreter—commentsarejustthereto
describetheprogramforthepersonreadingthecode.
conditionalstatement
Astatementthatexecutescodeaftercheckingacondition.Iftheconditionistrue,thestatementwill
executeonebitofcode;iftheconditionisfalse,itwillexecuteadifferentbitofcodeorstop
altogether.Examplesincludeifstatementsandif...elsestatements.
constructor
Akindoffunctionthat’susedtocreatemultipleobjectssothattheysharebuilt-inproperties.
controlstructure
Awaytocontrolwhenapieceofcodeisrunandhowoftenit’srun.Examplesincludeconditional
statements(whichcontrolwhencodeisrunbycheckingacondition)andloops(whichrepeatapiece
ofcodeacertainnumberoftimes).
data
Theinformationwestoreandmanipulateincomputerprograms.
decrement
Todecreasethevalueofavariable(usuallyby1).
dialog
Asmallpop-upwindow.YoucanuseJavaScripttoopendifferentkindsofdialogsinabrowser,such
asanalert(todisplayamessage)oraprompt(toaskaquestionandreceiveinput).
documentobjectmodel(DOM)
ThewaythatwebbrowsersorganizeandkeeptrackofHTMLelementsonawebpage.These
elementsareorganizedinatreelikestructurecalledtheDOMtree.JavaScriptandjQueryprovide
methodsthatworkwiththeDOMtocreateandmodifyelements.
element
PartofanHTMLpage,suchasaheader,aparagraph,orthebody.Anelementismarkedbystartand
endtags(whichdeterminewhattypeofelementitis)andincludeseverythinginbetween.TheDOM
treeismadeupoftheseelements.
event
Anactionthathappensinthebrowser,suchasamouseclickorakeyboardpressbytheuser.Wecan
detectandrespondtotheseeventswitheventhandlers.
eventhandler
AfunctionthatiscalledwheneveracertaineventhappensinacertainHTMLelement.Forexample,
inChapter11game,wecreateaneventhandlerfunctionthatiscalledwhenevertheuserclicksona
mapimage.
execute
Torunapieceofcode,suchasaprogramorfunction.
function
Apieceofcodethatbundlesmultiplestatementssothattheyareallexecutedtogether.Afunction
makesiteasytorepeatacertainactionindifferentpartsofaprogram.Afunctioncantakearguments
asinput,anditwilloutputareturnvalue.
increment
Toincreasethevalueofavariable(usuallyby1).
index
Anumberthatindicatesthepositionofavalueinsideanarray.Theindexcanbeusedtoaccessa
specificvalueinanarray.
infiniteloop
Aloopthatneverstopsrepeating(oftencausingtheinterpretertocrash).Thiserrorcanoccurifthe
conditionsofalooparesetupincorrectly.
interpreter
Apieceofsoftwarethatreadsandrunscode.WebbrowserscontainaJavaScriptinterpreter,which
weusetorunourJavaScriptthroughoutthisbook.
jQuery
AJavaScriptlibrarythatprovidesmanyusefulmethodsformodifyingandworkingwithDOM
elementsonawebpage.
key-valuepair
Apairmadeupofastring(calledakey)thatismatchedupwithaparticularvalue(whichcanbeany
typeofvalue).Key-valuepairsgoinsideJavaScriptobjects,andtheyareusedtodefineanobject’s
propertiesandmethods.
keyword
AwordwithaspecialmeaninginJavaScript(forexample,for,return,orfunction).Keywords
can’tbeusedasvariablenames.
library
AcollectionofJavaScriptcodethatwecanloadintoourwebpagestoprovideadditionalfunctions
andmethods.InthisbookweusethejQuerylibrary,whichgivesusfunctionsandmethodsfor
workingwiththeDOMmoreeasily.
loop
Awaytoexecuteapieceofcodemultipletimes.
method
Afunctionthatisapropertyofanobject.
null
Aspecialvaluethatcanbeusedtoindicatethatavariableispurposelyleftempty.
object
Asetofkey-valuepairs.EachkeyisastringthatcanbepairedwithanyJavaScriptvalue.Youcan
thenusethekeytoretrievewhatevervalueit’spairedwithintheobject.
object-orientedprogramming
Astyleofprogrammingthattakesadvantageofobjectsandmethodstoorganizethecodeand
representthemostimportantfeaturesoftheprogram.
programminglanguage
Alanguagethatprogrammerscanusetotellcomputerswhattodo.JavaScriptisoneprogramming
language,buttherearemanyothers.
property
Anameforakey-valuepairinanobject.
prototype
Apropertyofaconstructor.Anymethodsaddedtoaconstructor’sprototypewillbeavailabletoall
objectscreatedbythatconstructor.
return
Theactofleavingafunctionandreturningtothecodethatcalledthefunction.Afunctionreturns
whenitreachestheendofitsbodyorwhenitreachesareturnkeyword(whichcanbeusedtoleave
afunctionearly).Whenafunctionreturns,itoutputsareturnvalue(ifnoparticularreturnvalueis
specified,itsimplyreturnstheemptyvalueundefined).
selectorstring
AstringthatrepresentsoneormoreHTMLelements.WecanpassthisstringtojQuery’s$function
toselectthoseelements.
string
Alistofcharacterssurroundedbyquotes,usedtorepresenttextincomputerprograms.
syntax
Howkeywords,punctuation,andothercharactersarecombinedtomakeworkingJavaScript
programs.
tag
AmarkerusedtocreateHTMLelements.Allelementsbeginwithastarttag,andmostendwithan
endtag.Thesetagsdeterminewhattypeofelementiscreated,andthestarttagcanincludeattributes
fortheelement.
texteditor
Acomputerprogramusedtowriteandeditplaintext,withoutanyspecialformattinglikefontstyleor
color.Agoodtexteditorishelpfulforwritingprograms,whicharewritteninplaintext.
undefined
AvaluethatJavaScriptuseswhensomethinglikeapropertyorvariabledoesn’thaveanyparticular
valueassignedtoit.
variable
AwayofgivingaJavaScriptvalueaname.Afteryouassignavaluetoavariable,youcanusethe
variablenamelatertoretrievethevalue.
whitespace
Invisiblecharacterslikespaces,newlines,andtabs.
Updates
Visithttp://www.nostarch.com/javascriptforkidsforupdates,errata,andotherinformation.
MoreSmartBooksforCuriousKids!
PYTHONFORKIDS
APlayfulIntroductiontoProgramming
byJASONR.BRIGGS
DEC2012,344PP.,$34.95
ISBN978-1-59327-407-8
fullcolor
RUBYWIZARDRY
AnIntroductiontoProgrammingforKids
byERICWEINSTEIN
DEC2014,360PP.,$29.95
ISBN978-1-59327-566-2
twocolor
LAURENIPSUM
AStoryAboutComputerScienceandOtherImprobableThings
byCARLOSBUENO
DEC2014,192PP.,$16.95
ISBN978-1-59327-574-7
fullcolor
SURVIVE!INSIDETHEHUMANBODY,VOL.1
TheDigestiveSystem
byGOMDORICO.and
HYUN-DONGHAN
OCT2013,184PP.,$17.95
ISBN978-1-59327-471-9
fullcolor
ELOQUENTJAVASCRIPT,2NDEDITION
AModernIntroductiontoProgramming
byMARIJNHAVERBEKE
DEC2014,400PP.,$39.95
ISBN978-1-59327-584-6
THEMANGAGUIDETODATABASES
byMANATAKAHASHI,SHOKO
AZUMA,andTREND-PROCO.,LTD.
JAN2009,224PP.,$19.95
ISBN978-1-59327-190-9
800.420.7240or415.863.9900|[email protected]|www.nostarch.com
Index
ANOTEONTHEDIGITALINDEX
Alinkinanindexentryisdisplayedasthesectiontitleinwhichthatentryappears.Becausesomesectionshavemultipleindexmarkers,
itisnotunusualforanentrytohaveseverallinkstothesamesection.Clickingonanylinkwilltakeyoudirectlytotheplaceinthetext
inwhichthemarkerappears.
Symbols
!(not),WhatIsJavaScript?
"(doublequotationmark),+=(plus-equals)and–=(minus-equals),CreatingObjects
#(idinselectorstrings),ReplacingtheHeadingTextUsingjQuery
$(jQueryfunction),ReplacingtheHeadingTextUsingjQuery
(seealsojQuery)
&&(and),ChangingStringstoAllCapitalorAllLowercaseLetters,Combininglogicaloperators
'(singlequotationmark),Strings
()(parentheses),NumbersandOperators,GettingaSingleCharacterfromaString,Callinga
Function
*(multiplication),NumbersandOperators
*=(multiplyandassign),+=(plus-equals)and–=(minus-equals),ProgrammingChallenges
+(addition),NumbersandOperators,JoiningStrings,ProgrammingChallenges,CreatingaPrompt
withstrings,JoiningStrings,ProgrammingChallenges,CreatingaPrompt
++(increment),AgeinSeconds
+=(addandassign),IncrementingandDecrementing,KeepingTrackofOwedMoney
,(comma),PassingMultipleArgumentstoaFunction
-(subtraction),NumbersandOperators
--(decrement),AgeinSeconds
-=(subtractandassign),IncrementingandDecrementing
.(period),KeysWithoutQuotes(seedotnotation)
/(division),NumbersandOperators
/=(divideandassign),+=(plus-equals)and–=(minus-equals)
:(colon),CreatingObjects
;(semicolon),DataTypesandVariables,PreventingInfiniteLoops
<(lessthan),GreaterThan
=(assignment),Variables
==(doubleequals),EqualTo
===(exactlyequals),EqualTo,Chainingif...elseStatements
>(greaterthan),Combininglogicaloperators
[](squarebrackets),FindingtheLengthofaString,WhyShouldYouCareAboutArrays?,Creating
anArray,AccessinganArray’sElements,MixingDataTypesinanArray,KeysWithoutQuotes
accessingacharacterfromastringwith,FindingtheLengthofaString
accessingelementsfromanarraywith,CreatinganArray,MixingDataTypesinanArray
accessingvaluesinobjectswith,KeysWithoutQuotes
addingelementstoanarraywith,AccessinganArray’sElements
creatinganarraywith,WhyShouldYouCareAboutArrays?
{}(curlybrackets),Objects,AccessingValuesinObjects
||(or),&&(and),Combininglogicaloperators
A
addandassign(+=)operator,IncrementingandDecrementing,KeepingTrackofOwedMoney
addition,NumbersandOperators,JoiningStrings,ProgrammingChallenges,CreatingaPrompt
withstrings,JoiningStrings,ProgrammingChallenges,CreatingaPrompt
alertmethod,UsingconfirmtoAskaYesorNoQuestion
and(&&)operator,ChangingStringstoAllCapitalorAllLowercaseLetters,Combininglogical
operators
animation,CallingCodeMultipleTimeswithsetInterval,MovingAcrossthePage,Animatingthe
SizeofaSquare,AnimatingtheSizeofaSquare,BouncingaBall!
withcanvas,MovingAcrossthePage,AnimatingtheSizeofaSquare,AnimatingtheSizeofa
Square,BouncingaBall!
bouncingball,BouncingaBall!
changingsize,AnimatingtheSizeofaSquare
movinghorizontally,MovingAcrossthePage
randombee,AnimatingtheSizeofaSquare
withsetInterval,CallingCodeMultipleTimeswithsetInterval
appendjQuerymethod,CreatingNewElementswithjQuery,DrawingtheCars
arccontextmethod,FillingPaths
arguments,forfunctions,PassingArgumentsintoFunctions,Glossary
arrays,Arrays,WhyShouldYouCareAboutArrays?,CreatinganArray,AccessinganArray’s
Elements,MixingDataTypesinanArray,WorkingwithArrays,FindingtheLengthofanArray,
AddingElementstoanArray,RemovingElementsfromanArray,RemovingElementsfroman
Array,JoiningMultipleArrays,FindingtheIndexofanElementinanArray,TurninganArrayinto
aString,AccessingValuesinObjects,CombiningArraysandObjects,forLoops,Glossary
accessing,CreatinganArray
addingelementsto,FindingtheLengthofanArray,RemovingElementsfromanArray
anddatatypes,MixingDataTypesinanArray
combiningmultiple,RemovingElementsfromanArray
combiningwithobjects,CombiningArraysandObjects
convertingtoastring,FindingtheIndexofanElementinanArray
creating,WhyShouldYouCareAboutArrays?
findingindexofelementin,JoiningMultipleArrays
findinglengthof,WorkingwithArrays
loopingthroughelementsof,forLoops
modifying,AccessinganArray’sElements
removingelementsfrom,AddingElementstoanArray
vs.objects,AccessingValuesinObjects
assigningvalues,Variables
attributes,HTML,AddingLinkstoYourHTML,Glossary
B
beginPathcontextmethod,DrawingLinesorPaths
block-levelHTMLelements,ThepElement
body,ifStatements,whileLoops,PreventingInfiniteLoops,Functions
ofacontrolstructure,ifStatements,whileLoops,PreventingInfiniteLoops
ofafunction,Functions
bodyelement,AFullHTMLDocument
Booleans,DataTypesandVariables,ChangingStringstoAllCapitalorAllLowercaseLetters,
ChangingStringstoAllCapitalorAllLowercaseLetters,Combininglogicaloperators,Embedding
JavaScriptinHTML,CreatingaPrompt,Glossary
comparingnumberswith,Combininglogicaloperators
foryes-or-noanswers,CreatingaPrompt
inconditionalstatements,EmbeddingJavaScriptinHTML
logicaloperators,ChangingStringstoAllCapitalorAllLowercaseLetters
brackets,FindingtheLengthofaString,Objects,AccessingValuesinObjects
curly,Objects,AccessingValuesinObjects
square,FindingtheLengthofaString(seesquarebrackets)
breakkeyword,HandlingthePlayer’sInput
C
calling,FindingtheLengthofanArray,CallingaFunction,PassingArgumentsintoFunctions,
Glossary
functions,CallingaFunction,PassingArgumentsintoFunctions,Glossary
methods,FindingtheLengthofanArray
camelcase,NamingVariables,Glossary
canvaselement,TheCanvasElement,TheCanvasElement,SelectingandSavingthecanvas
Element,DrawingMultipleSquares,DrawingRectangleOutlines,DrawingLinesorPaths,Drawing
LinesorPaths,FillingPaths,MakingThingsMoveontheCanvas,MovingAcrossthePage,
ClearingtheCanvas,AnimatingtheSizeofaSquare,AnimatingtheSizeofaSquare,Bouncinga
Ball!,CSS
animating,MakingThingsMoveontheCanvas,MovingAcrossthePage,AnimatingtheSizeofa
Square,AnimatingtheSizeofaSquare,BouncingaBall!
bouncingball,BouncingaBall!
changingsize,AnimatingtheSizeofaSquare
movinghorizontally,MovingAcrossthePage
randombee,AnimatingtheSizeofaSquare
circlesandarcs,FillingPaths
clearing,ClearingtheCanvas
colors,DrawingMultipleSquares
creating,TheCanvasElement
linesandpaths,DrawingLinesorPaths,DrawingLinesorPaths
drawing,DrawingLinesorPaths
filling,DrawingLinesorPaths
rectanglesandsquares,SelectingandSavingthecanvasElement,DrawingRectangleOutlines
drawing,SelectingandSavingthecanvasElement
outlining,DrawingRectangleOutlines
resources,CSS
CascadingStyleSheets(CSS),CSS
chainingif...elsestatements,Chainingif...elseStatements
chainingjQueryanimations,ChainingjQueryAnimations
Chrome,webbrowserandconsole,WritingSomeJavaScript
clearIntervalfunction,CallingCodeMultipleTimeswithsetInterval
clearRectcontextmethod,MovingAcrossthePage
clearTimeoutfunction,DelayingCodewithsetTimeout
clickevents,RespondingtoUserActions
coercion,CreatingaPrompt
collisiondetection,MovingtheBall,CheckingforCollisionsandAddingtheHead
colon(:),CreatingObjects
comma(,),PassingMultipleArgumentstoaFunction
comments,Syntax,UpdatingtheGameState,Glossary
concatmethod,RemovingElementsfromanArray
condition(ofacontrolstructure),ifStatements,Chainingif...elseStatements,whileLoops,
PreventingInfiniteLoops
inforloops,PreventingInfiniteLoops
inifstatements,ifStatements
inif...elsestatements,Chainingif...elseStatements
inwhileloops,whileLoops
conditionals,ConditionalsandLoops,EmbeddingJavaScriptinHTML,EmbeddingJavaScriptin
HTML,ifStatements,LeavingaFunctionEarlywithreturn,Glossary
ifstatements,EmbeddingJavaScriptinHTML
if...elsestatements,EmbeddingJavaScriptinHTML,ifStatements,LeavingaFunctionEarlywith
return
confirmfunction,CreatingaPrompt
console,WritingSomeJavaScript,CreatinganArray,ExploringObjectsintheConsole,Embedding
JavaScriptinHTML,TheGameCode,TheCarConstructorfunction,AddingthekeydownEvent
Handler
callingconstructorsin,TheCarConstructorfunction
exploringobjectsin,ExploringObjectsintheConsole
findingerrorswith,TheGameCode
loggingvaluesto,EmbeddingJavaScriptinHTML
typingin,CreatinganArray
viewingoutputfromkeyboardeventswith,AddingthekeydownEventHandler
console.logmethod,EmbeddingJavaScriptinHTML,UsingconfirmtoAskaYesorNoQuestion,
CallingaFunction
vs.alert,UsingconfirmtoAskaYesorNoQuestion
constructors,SharingaMethodBetweenMultipleObjects,Glossary
controlstructures,ConditionalsandLoops,Glossary
(seealsoconditionals;loops)
coordinates,browser,RespondingtoClicks
CSS(CascadingStyleSheets),CSS
cssjQuerymethod,DrawingtheCars
curlybrackets,Objects,AccessingValuesinObjects
D
data,DataTypesandVariables,Glossary
decrementing,AgeinSeconds,Glossary
dialogs,CreatingaHangmanGame,Glossary
divideandassign(/)operator,+=(plus-equals)and–=(minus-equals)
division,NumbersandOperators
documentobjectmodel(DOM),TheDOMandjQuery,Glossary
document.getElementByIdDOMmethod,UsingidtoIdentifyElements,TheCanvasElement
DOM(documentobjectmodel),TheDOMandjQuery,Glossary
DOMtree,TheDOMandjQuery
dotnotation,KeysWithoutQuotes,AddingValuestoObjects,CombiningArraysandObjects,ObjectOrientedProgramming,Object-OrientedProgramming
accessingobjectkeyswith,CombiningArraysandObjects
addingkeystoobjectswith,AddingValuestoObjects
addingmethodstoobjectswith,Object-OrientedProgramming
addingpropertiestoobjectswith,Object-OrientedProgramming
doubleequals(==)operator,EqualTo
doublequotationmark("),+=(plus-equals)and–=(minus-equals),CreatingObjects
drawingcontext(forcanvas),SelectingandSavingthecanvasElement
E
elements,HTML,TagsandElements,Glossary
elsekeyword,ifStatements,Chainingif...elseStatements
emelement,WhitespaceinHTMLandBlock-LevelElements
endtags,HTML,TagsandElements,Glossary
equalto(===)operator,EqualTo,Chainingif...elseStatements
errors,TheGameCode
eventhandlers,RespondingtoUserActions,DesigningtheGame,PickingRandomNumbers,
Glossary
eventobject,RespondingtoUserActions,TheClickHandler
exactlyequals(===)operator,EqualTo,Chainingif...elseStatements
execute,WritingSomeJavaScript,Glossary
F
fadeInjQuerymethod,ChainingjQueryAnimations
fadeOutjQuerymethod,CreatingNewElementswithjQuery
fadeTojQuerymethod,ProgrammingChallenges
false(Booleanvalue),DataTypesandVariables,ChangingStringstoAllCapitalorAllLowercase
Letters
(seealsoBooleans)
fillcontextmethod,DrawingLinesorPaths,ANewcircleFunction
fillRectcontextmethod,TheCanvasElement,DrawingLinesorPaths,ClearingtheCanvas,
DefiningthescoreVariable,BuildingtheBlockConstructor
fillStylecontextproperty,DrawingMultipleSquares,DrawingtheBee,DefiningthescoreVariable,
WritingthedrawScoreFunction,BuildingtheBlockConstructor
fillTextcontextmethod,DisplayingtheScore,SettingtheTextBaseline
FindtheBuriedTreasure!game,FindtheBuriedTreasure!,FindtheBuriedTreasure!,Designing
theGame,CreatingtheWebPagewithHTML,PickingRandomNumbers,TheClickHandler,
TellingthePlayerHowCloseTheyAre,TellingthePlayerHowCloseTheyAre,TellingthePlayer
HowCloseTheyAre
calculatingdistances,TheClickHandler
clickhandler,PickingRandomNumbers
codefor,TellingthePlayerHowCloseTheyAre
creatingwebpage,DesigningtheGame
design,FindtheBuriedTreasure!
displayinghints,TellingthePlayerHowCloseTheyAre
randomizingtreasurelocation,CreatingtheWebPagewithHTML
wincondition,TellingthePlayerHowCloseTheyAre
floormethod,UsingMath.random(),ProgrammingChallenges
fontcontextproperty,SettingtheTextBaseline
forloops,PreventingInfiniteLoops
functionkeyword,PassingMultipleArgumentstoaFunction
(seealsofunctions)
functions,Functions,CallingaFunction,CallingaFunction,PassingArgumentsintoFunctions,
PassingArgumentsintoFunctions,PassingMultipleArgumentstoaFunction,PassingMultiple
ArgumentstoaFunction,UsingFunctionstoSimplifyCode,LeavingaFunctionEarlywithreturn,
LeavingaFunctionEarlywithreturn,UsingreturnMultipleTimesInsteadofif...elseStatements,
Glossary,Glossary,Glossary
arguments,PassingArgumentsintoFunctions,PassingMultipleArgumentstoaFunction
calling,CallingaFunction,PassingArgumentsintoFunctions,Glossary
leavingearly,LeavingaFunctionEarlywithreturn
returningvaluesfrom,CallingaFunction,PassingMultipleArgumentstoaFunction,Glossary
shorthand,UsingreturnMultipleTimesInsteadofif...elseStatements
simplifyingcodewith,UsingFunctionstoSimplifyCode
vs.if...elsestatements,LeavingaFunctionEarlywithreturn
G
games,programming,MeetJavaScript,AudioProgramming
(seealsoFindtheBuriedTreasure!game;Hangmangame;Snakegame)
getContextcanvasmethod,TheCanvasElement
getElementById,UsingidtoIdentifyElements,TheCanvasElement
GoogleChrome,webbrowserandconsole,WritingSomeJavaScript
graphicalprogramming,MeetJavaScript
greaterthan(>)operator,Combininglogicaloperators
H
h1element,TagsandElements
Hangmangame,CreatingaHangmanGame,WhyUsealertInsteadofconsole.log?,Designingthe
GameLoop,CodingtheGameLoop,CodingtheGameLoop,HandlingthePlayer’sInput,Updating
theGameState,UpdatingtheGameState,ProgrammingChallenges,ProgrammingChallenges,
ProgrammingChallenges
choosingarandomword,DesigningtheGameLoop
codefor,UpdatingtheGameState
creatingwithfunctions,ProgrammingChallenges
design,WhyUsealertInsteadofconsole.log?
displayingplayer’sprogress,CodingtheGameLoop
drawing,ProgrammingChallenges,ProgrammingChallenges
guesses,ProgrammingChallenges
hangman,ProgrammingChallenges
respondingtoplayerinput,CodingtheGameLoop
updatinggamestate,HandlingthePlayer’sInput
wincondition,UpdatingtheGameState
headelement,AFullHTMLDocument
heightattribute,CreatingtheWebPagewithHTML,TheCanvasElement
hidejQuerymethod,ChainingjQueryAnimations
hrefattribute,LinkAttributes
HTML,TheBasicsofHTML,TagsandElements,AFullHTMLDocument,AFullHTML
Document,AddingLinkstoYourHTML,TheDOMandjQuery,MoreJavaScript,Glossary,
Glossary
attributes,AddingLinkstoYourHTML,Glossary
elements,TagsandElements,Glossary
hierarchy,AFullHTMLDocument
nesting,AFullHTMLDocument
htmlelement,AFullHTMLDocument,ThemousemoveEvent
hyperlinks,TheBasicsofHTML,HTMLHierarchy
I
idattribute,UsingidtoIdentifyElements,ReplacingtheHeadingTextUsingjQuery
ifstatements,EmbeddingJavaScriptinHTML
if...elsestatements,EmbeddingJavaScriptinHTML,ifStatements,LeavingaFunctionEarlywith
return
imgelement,DesigningtheGame,PickingRandomNumbers,DrawingtheCars
incrementing,AgeinSeconds,Glossary
indexes,inarrays,CreatinganArray,AccessinganArray’sElements,MixingDataTypesinan
Array,JoiningMultipleArrays,UsingMath.random(),Glossary
anddatatypes,MixingDataTypesinanArray
changingelementswith,AccessinganArray’sElements
finding,JoiningMultipleArrays
withstrings,UsingMath.random()
indexOfmethod,JoiningMultipleArrays
infiniteloops,CountingSheepwithawhileloop,Glossary
inlineHTMLelements,WhitespaceinHTMLandBlock-LevelElements
innerHTMLproperty,UsingidtoIdentifyElements
interactiveprogramming,InteractiveProgramming
intervalID,CallingCodeMultipleTimeswithsetInterval,UsingsetIntervaltoAnimatetheGame,
EndingtheGame,PuttingItAllTogether
J
joinmethod,FindingtheIndexofanElementinanArray,ProgrammingChallenges
jQuery,TheDOMandjQuery,UsingjQuerytoWorkwiththeDOMTree,UsingjQuerytoWorkwith
theDOMTree,ReplacingtheHeadingTextUsingjQuery,CreatingNewElementswithjQuery,
CreatingNewElementswithjQuery,ControllingAnimationswiththeKeyboard,Reactingtothe
Keyboard,Glossary
$function,ReplacingtheHeadingTextUsingjQuery
animatingelementswith,CreatingNewElementswithjQuery
creatingnewelementswith,CreatingNewElementswithjQuery
keyboardevents,respondingwith,ControllingAnimationswiththeKeyboard,Reactingtothe
Keyboard
loadingonpage,UsingjQuerytoWorkwiththeDOMTree
replacingpagetextwith,UsingjQuerytoWorkwiththeDOMTree
K
key-valuepairs(inobjects),Objects,CreatingObjects,Object-OrientedProgramming,Glossary
keyCodeeventproperty,AddingthekeydownEventHandler,SettingtheSnake’sDirectionwiththe
Keyboard
keydownevent,ControllingAnimationswiththeKeyboard,ReactingtotheKeyboard,Settingthe
Snake’sDirectionwiththeKeyboard
keys(inobjects),Objects,CreatingObjects,CreatingObjects,AddingValuestoObjects,ObjectOrientedProgramming
adding,AddingValuestoObjects
andquotationmarks,CreatingObjects
keywords,NumbersandOperators,Glossary
L
lengthproperty,JoiningStrings,WorkingwithArrays,CreatingaRandomInsultGenerator,
ExploringObjectsintheConsole
onarrays,WorkingwithArrays,CreatingaRandomInsultGenerator,ExploringObjectsinthe
Console
onstrings,JoiningStrings
lessthan(<)operator,GreaterThan
libraries,UsingjQuerytoWorkwiththeDOMTree,Glossary
lineTocontextmethod,DrawingLinesorPaths
lineWidthcontextproperty,DrawingRectangleOutlines,DrawingtheBee
links,TheBasicsofHTML,HTMLHierarchy
literals,Objects
logs,EmbeddingJavaScriptinHTML
loops,ConditionalsandLoops,whileLoops,PreventingInfiniteLoops,Glossary
forloops,PreventingInfiniteLoops
whileloops,whileLoops
M
Math.floor,UsingMath.random(),ProgrammingChallenges
Math.PI,DrawingArcsandCircles
Math.random,UsingMath.random()
Math.sqrt,UsingthePythagoreanTheorem
mathematicaloperators,NumbersandOperators
methods,CreatinganArray,FindingtheLengthofanArray,Object-OrientedProgramming,Adding
MethodstoObjects,AddingMethodstoObjects,Glossary
addingtoobjects,Object-OrientedProgramming
andthis,AddingMethodstoObjects
calling,FindingtheLengthofanArray
sharingbetweenobjects,AddingMethodstoObjects
mousemoveevent,ThemousemoveEvent,ProgrammingChallenges
moveTocontextmethod,DrawingLinesorPaths
multiplication,NumbersandOperators
multiplyandassign(*=)operator,+=(plus-equals)and–=(minus-equals),ProgrammingChallenges
musicprogramming,MeetJavaScript,AudioProgramming
N
newkeyword,SharingaMethodBetweenMultipleObjects,DrawingtheCars
Node.js,CSS
not(!)operator,||(or)
nullvalue,DoubleEquals,CreatingaPrompt,Glossary
numbers,DataTypesandVariables,CreatinganArray,KeysWithoutQuotes
O
object-orientedprogramming,Object-OrientedProgramming,Glossary
Object.keysmethod,AccessingValuesinObjects,StoringInformationAboutYourMovies
objects,Objects,Objects,KeysWithoutQuotes,AccessingValuesinObjects,AddingValuesto
Objects,CombiningArraysandObjects,ExploringObjectsintheConsole,ExploringObjectsinthe
Console,Object-OrientedProgramming,Object-OrientedProgramming,SharingaMethodBetween
MultipleObjects,CustomizingObjectswithPrototypes,Glossary
accessingvaluesin,KeysWithoutQuotes
addingkeysto,AddingValuestoObjects
addingmethodsto,Object-OrientedProgramming
addingvaluesto,AccessingValuesinObjects
combiningwitharrays,CombiningArraysandObjects
creating,Objects,Object-OrientedProgramming
customizingwithprototypes,CustomizingObjectswithPrototypes
exploringwiththeconsole,ExploringObjectsintheConsole
withconstructors,SharingaMethodBetweenMultipleObjects
offsetjQuerymethod,AnimatingElementswithsetInterval,ThemousemoveEvent,Drawingthe
Cars
offsetXandoffsetYeventproperties,TheClickHandler
operators,NumbersandOperators
or(||)operator,&&(and),Combininglogicaloperators
P
pelement,TagsandElements
pageXandpageYeventproperties,RespondingtoUserActions,ThemousemoveEvent
parentheses,(),NumbersandOperators,GettingaSingleCharacterfromaString,Callinga
Function
period(.),KeysWithoutQuotes(seedotnotation)
pi(π),DrawingArcsandCircles
plaintext,TheBasicsofHTML
popmethod,AddingElementstoanArray,FindingYourWayHome
promptmethod,CreatingaHangmanGame,ReplacingtheHeadingTextUsingtheDOM
properties,WorkingwithArrays,ExploringObjectsintheConsole,Object-OrientedProgramming,
Glossary
prototypeproperty,CustomizingObjectswithPrototypes,TheBallConstructor
prototypes,ExploringObjectsintheConsole,CustomizingObjectswithPrototypes,TheBall
Constructor
pseudocode,WhyUsealertInsteadofconsole.log?,TheStructureoftheGame
pushmethod,FindingtheLengthofanArray,FindingYourWayHome
Pythagoreantheorem,CalculatingtheDistanceBetweentheClickandtheTreasure
Q
queue(datastructure),GoinginReversewithpop
quotationmarks,+=(plus-equals)and–=(minus-equals),CreatingObjects
R
radians,FillingPaths
randomnumbergeneration,withMath.random,UsingMath.random()
returnkeyword,ReturningValuesfromFunctions,UsingFunctionstoSimplifyCode,Glossary
returningvaluesfromfunctions,CallingaFunction,PassingMultipleArgumentstoaFunction,
Glossary
S
scriptelement,ConditionalsandLoops,UsingjQuerytoWorkwiththeDOMTree
selectorstrings,ReplacingtheHeadingTextUsingjQuery,Glossary
semicolons,DataTypesandVariables,PreventingInfiniteLoops
setIntervalfunction,CallingCodeMultipleTimeswithsetInterval,CallingCodeMultipleTimeswith
setInterval,MovingAcrossthePage,ChangingtheCoordinatewithanOffsetValue,Bouncingthe
Ball,ReactingtotheKeyboard,UsingsetIntervaltoAnimatetheGame,MovingtheApple
andSnakegame,UsingsetIntervaltoAnimatetheGame,MovingtheApple
bouncingball,BouncingtheBall
movingtext,CallingCodeMultipleTimeswithsetInterval
randombee,ChangingtheCoordinatewithanOffsetValue
withcanvas,MovingAcrossthePage
withkeyboardinput,ReactingtotheKeyboard
setTimeoutfunction,InteractiveProgramming
shiftmethod,RemovingElementsfromanArray
showjQuerymethod,ChainingjQueryAnimations
singlequotationmark,Strings
slicemethod,GettingaSingleCharacterfromaString
slideDownjQuerymethod,ChainingjQueryAnimations
slideUpjQuerymethod,ChainingjQueryAnimations
Snakegame,MakingaSnakeGame:Part1,TheStructureoftheGame,SettingUpKeyboard
Control,CreatingtheHTML,DefiningthescoreVariable,DisplayingtheScore,EndingtheGame,
MakingaSnakeGame:Part2,BuildingtheBlockConstructor,AddingthedrawSquareMethod,
AddingtheequalMethod,AddingtheequalMethod,CreatingtheSnake,DrawingtheSnake,Eating
theApple,SettingtheSnake’sDirectionwiththeKeyboard,AddingthesetDirectionMethod,
DrawingtheApple,MovingtheApple
apple,AddingthesetDirectionMethod,DrawingtheApple
creating,AddingthesetDirectionMethod
moving,DrawingtheApple
codefor,MovingtheApple
collisiondetection,AddingtheequalMethod,EatingtheApple
design,TheStructureoftheGame
displayingtext,DisplayingtheScore
drawing,BuildingtheBlockConstructor,AddingthedrawSquareMethod
circle,AddingthedrawSquareMethod
square,BuildingtheBlockConstructor
endingthegame,EndingtheGame,AddingtheequalMethod
gamegrid,CreatingtheHTML,DefiningthescoreVariable,MakingaSnakeGame:Part2
addingborder,DefiningthescoreVariable
creatingBlock,MakingaSnakeGame:Part2
settingup,CreatingtheHTML
gameplay,MakingaSnakeGame:Part1
HTMLcode,SettingUpKeyboardControl
snake,CreatingtheSnake,DrawingtheSnake,SettingtheSnake’sDirectionwiththeKeyboard
creating,CreatingtheSnake
moving,DrawingtheSnake
settingdirectionof,SettingtheSnake’sDirectionwiththeKeyboard
squarebrackets,[],FindingtheLengthofaString,WhyShouldYouCareAboutArrays?,Creating
anArray,AccessinganArray’sElements,MixingDataTypesinanArray,KeysWithoutQuotes
accessingacharacterfromastringwith,FindingtheLengthofaString
accessingelementsfromanarraywith,CreatinganArray,MixingDataTypesinanArray
accessingvaluesinobjectswith,KeysWithoutQuotes
addingelementstoanarraywith,AccessinganArray’sElements
creatinganarraywith,WhyShouldYouCareAboutArrays?
squareroot,UsingthePythagoreanTheorem
srcattribute,UsingjQuerytoWorkwiththeDOMTree,CreatingtheWebPagewithHTML
stack(datastructure),GoinginReversewithpop
starttag,TagsandElements,Glossary
statements,DataTypesandVariables
strings,DataTypesandVariables,+=(plus-equals)and–=(minus-equals),JoiningStrings,Joining
Strings,FindingtheLengthofaString,GettingaSingleCharacterfromaString,CuttingUp
Strings,FindingtheIndexofanElementinanArray,Objects,CreatingObjects,KeysWithout
Quotes,UsingforLoopswithArraysandStrings,HandlingthePlayer’sInput,Glossary
accessingsinglecharacterfrom,FindingtheLengthofaString
asobjectkeys,Objects,CreatingObjects,KeysWithoutQuotes
changingcaseof,CuttingUpStrings
findinglengthof,JoiningStrings
joining,JoiningStrings
loopingthrougheachcharacterof,UsingforLoopswithArraysandStrings,Handlingthe
Player’sInput
slicing,GettingaSingleCharacterfromaString
turningarraysinto,FindingtheIndexofanElementinanArray
strokecontextmethod,DrawingLinesorPaths,ANewcircleFunction
strokeRectcontextmethod,DrawingRectangleOutlines,ChangingtheCoordinatewithanOffset
Value,BouncingtheBall
strokeStylecontextproperty,DrawingRectangleOutlines,DrawingtheBee
strongelement,WhitespaceinHTMLandBlock-LevelElements
SublimeText,TheBasicsofHTML
subtractandassign(-=)operator,IncrementingandDecrementing
subtraction,NumbersandOperators
SVG,SVGUsingRaphaël
syntax,Syntax,Glossary
syntaxhighlighting,TextEditors
T
tags,HTML,TagsandElements,Glossary
texteditors,TheBasicsofHTML,Glossary
textjQuerymethod,TellingthePlayerHowCloseTheyAre
textAligncontextproperty,SettingtheTextBaseline
textBaselinecontextproperty,SettingtheTextBaseline,WritingthedrawScoreFunction
thiskeyword,AddingMethodstoObjects,TheCarConstructorfunction,AddingadrawMethodto
theCarPrototype
timeoutID,DelayingCodewithsetTimeout
titleattribute,LinkAttributes
toLowerCasemethod,CuttingUpStrings
toUpperCasemethod,CuttingUpStrings
true(Booleanvalue),DataTypesandVariables,ChangingStringstoAllCapitalorAllLowercase
Letters
(seealsoBooleans)
U
undefinedvalue,NumbersandOperators,DoubleEquals,SettingorChangingElementsinan
Array,CallingaFunction,Glossary
unshiftmethod,AddingElementstoanArray
V
values(inobjects),Objects,CreatingObjects,CreatingObjects,KeysWithoutQuotes,Accessing
ValuesinObjects,Object-OrientedProgramming
accessing,KeysWithoutQuotes
adding,AccessingValuesinObjects
datatypeof,CreatingObjects
varkeyword,NumbersandOperators,Variables,NamingVariables
variables,NumbersandOperators,NamingVariables,NamingVariables,AgeinSeconds,Double
Equals,Arrays,Glossary
creatingwithmath,NamingVariables
increasinganddecreasingvaluesof,AgeinSeconds
naming,NamingVariables
undefinedandnullfor,DoubleEquals
vs.arrays,Arrays
W
webbrowsers,MeetJavaScript
whileloops,whileLoops
whitespace,ThepElement,WhitespaceinHTMLandBlock-LevelElements,Glossary
widthattribute,CreatingtheWebPagewithHTML,TheCanvasElement
JavaScriptforKids:APlayfulIntroductiontoProgramming
NickMorgan
Copyright©2014
JavaScriptforKids.
Allrightsreserved.Nopartofthisworkmaybereproducedortransmittedinanyformorbyanymeans,electronicormechanical,
includingphotocopying,recording,orbyanyinformationstorageorretrievalsystem,withoutthepriorwrittenpermissionofthecopyright
ownerandthepublisher.
1817161514123456789
ISBN-10:1-59327-408-4
ISBN-13:978-1-59327-408-5
Publisher:WilliamPollock
ProductionEditor:RileyHoffman
CoverIllustration:TinaSalameh
Illustrator:MiranLipovača
DevelopmentalEditors:WilliamPollockandSephKramer
TechnicalReviewer:AngusCroll
Copyeditor:RachelMonaghan
Compositor:RileyHoffman
Proofreader:PaulaL.Fleming
Forinformationondistribution,translations,orbulksales,pleasecontactNoStarchPress,Inc.directly:
NoStarchPress,Inc.
2458thStreet,SanFrancisco,CA94103
phone:415.863.9900;[email protected]
www.nostarch.com
LibraryofCongressControlNumber:2014953113
NoStarchPressandtheNoStarchPresslogoareregisteredtrademarksofNoStarchPress,Inc.Otherproductandcompanynames
mentionedhereinmaybethetrademarksoftheirrespectiveowners.Ratherthanuseatrademarksymbolwitheveryoccurrenceofa
trademarkedname,weareusingthenamesonlyinaneditorialfashionandtothebenefitofthetrademarkowner,withnointentionof
infringementofthetrademark.
Theinformationinthisbookisdistributedonan“AsIs”basis,withoutwarranty.Whileeveryprecautionhasbeentakeninthepreparation
ofthiswork,neithertheauthornorNoStarchPress,Inc.shallhaveanyliabilitytoanypersonorentitywithrespecttoanylossordamage
causedorallegedtobecauseddirectlyorindirectlybytheinformationcontainedinit.
NoStarchPress
2014-12-02T10:57:26-08:00