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|sales@nostarch.com|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;info@nostarch.com 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