object-oriented javascript - third edition · 2017. 4. 20. · es6 object literals object...
TRANSCRIPT
![Page 1: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/1.jpg)
![Page 2: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/2.jpg)
Object-Oriented JavaScript - Third Edition
![Page 3: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/3.jpg)
Table of Contents
Object-OrientedJavaScript-ThirdEditionCreditsAbouttheAuthorsAbouttheReviewerwww.PacktPub.comWhysubscribe?
CustomerFeedbackPrefaceWhatthisbookcoversWhatyouneedforthisbookWhothisbookisforConventionsReaderfeedbackCustomersupportErrataPiracyQuestions
1.Object-OrientedJavaScriptAbitofhistoryBrowserwarsand renaissanceThe presentThefuture
ECMAScript5StrictmodeinES6
ECMAScript6BrowsersupportforES6Babel
Object-orientedprogrammingObjectsClassesEncapsulationAggregationInheritancePolymorphism
OOPsummarySettingupyourtrainingenvironmentWebKit'swebinspectorJavaScriptCoreonaMacMoreconsoles
![Page 4: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/4.jpg)
Summary2.PrimitiveDataTypes, Arrays,Loops,andConditionsVariablesVariablesarecasesensitive
OperatorsPrimitivedatatypesFindingoutthevaluetype-thetypeofoperatorNumbersOctalandhexadecimalnumbersBinaryLiteralsExponentliteralsInfinityNaNNumber.isNaNNumber.isInteger
StringsStringconversionsSpecialstringsStringtemplateliterals
BooleansLogicaloperatorsOperatorprecedenceLazyevaluationComparison
UndefinedandnullSymbols
PrimitivedatatypesrecapArraysAdding/updatingarrayelementsDeletingelementsArraysofarrays
ConditionsandloopsCode blocksTheifconditionTheelseclauseCheckingifavariableexistsAlternativeifsyntaxSwitchDon'tforgettobreak
LoopsWhileloopsDo-whileloops
![Page 5: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/5.jpg)
ForloopsFor...inloops
CommentsExercisesSummary
3.FunctionsWhatisafunction?Calling a functionParameters
DefaultparametersRestparametersSpreadoperatorsPredefinedfunctionsparseInt()parseFloat()isNaN()isFinite()Encode/decodeURIseval()Abonus-thealert()function
ScopeofvariablesVariablehoisting
BlockscopeFunctionsaredataAnonymousfunctionsCallbackfunctionsCallbackexamples
ImmediatefunctionsInner(private)functionsFunctionsthatreturnfunctionsFunction,rewritethyself!
ClosuresScope chainBreakingthechain withaclosureClosure#1Closure#2Adefinitionandclosure#3
ClosuresinaloopGetterandsetterIterator
IIFEversusblocksArrowfunctions
![Page 6: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/6.jpg)
ExercisesSummary
4.ObjectsFromarraystoobjectsElements,properties,methods,andmembersHashesandassociativearraysAccessinganobject'spropertiesCalling an object's methodsAlteringproperties/methodsUsingthethisvalueConstructorfunctionsTheglobalobjectTheconstructorpropertyTheinstanceofoperatorFunctionsthatreturnobjectsPassingobjectsComparingobjectsObjectsintheWebKitconsoleLoggingusingtheconsole.logmethod
ES6objectliteralsObjectpropertiesandattributesES6objectmethodsCopypropertiesusingObject.assignComparevalueswithObject.is
DestructuringBuilt-inobjectsObjectArrayAfewarraymethods
ES6arraymethodsArray.fromCreatingarraysusingArray.ofArray.prototype methodsFunctionPropertiesoffunctionobjectsUsingtheprototypepropertyMethodsoffunctionobjectsCallandapplyTheargumentsobjectrevisited
LexicalthisinarrowfunctionsInferringobjecttypesBoolean
![Page 7: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/7.jpg)
NumberStringAfewmethodsofstringobjects
MathDateMethodstoworkwithdateobjectsCalculatingbirthdays
RegExpPropertiesofRegExpobjectsMethodsofRegExpobjectsStringmethodsthatacceptregularexpressionsasargumentssearch()andmatch()replace()Replacecallbackssplit()Passingastring whenaRegExpisexpectedErrorobjects
ExercisesSummary
5.ES6IteratorsandGeneratorsFor...ofloopIteratorsanditerablesIteratorsIterables
GeneratorsIteratingovergenerators
CollectionsMapIteratingovermapsConvertingmapstoarrays
SetWeakMapandWeakSet
Summary6.PrototypeTheprototypepropertyAddingmethodsandpropertiesusingtheprototype
Usingtheprototype'smethodsandpropertiesOwnpropertiesversusprototypepropertiesOverwritingaprototype'spropertywithanownpropertyEnumeratingproperties
UsingisPrototypeOf()methodThesecret__proto__link
![Page 8: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/8.jpg)
Augmentingbuilt-inobjectsAugmentingbuilt-inobjects-discussionPrototypegotchas
ExercisesSummary
7.InheritancePrototypechainingPrototype chaining exampleMovingsharedpropertiestotheprototype
InheritingtheprototypeonlyAtemporaryconstructor-newF()
Uber-accesstotheparentfromachildobjectIsolatingtheinheritancepartintoafunctionCopyingpropertiesHeads-upwhencopyingbyreferenceObjectsinheritfromobjectsDeepcopyUsingobject()methodUsingamixofprototypalinheritanceandcopyingpropertiesMultipleinheritanceMixins
ParasiticinheritanceBorrowingaconstructorBorrowingaconstructorandcopyingitsprototype
Casestudy-drawingshapesAnalysisImplementationTesting
ExercisesSummary
8.ClassesandModulesDefiningclassesConstructorPrototypemethodsStaticmethodsStaticpropertiesGeneratormethods
SubclassingMixins
ModulesExportlists
Summary
![Page 9: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/9.jpg)
9.PromisesandProxiesAsynchronousprogrammingmodelJavaScriptcallstackMessagequeueEventloopTimersRuntocompletionEventsCallbacks
PromisesCreatingpromisesPromise.all()
MetaprogrammingandproxiesProxyFunctiontraps
Summary10.TheBrowserEnvironmentIncludingJavaScriptinanHTMLpageBOMandDOM-anoverviewBOMThewindowobjectrevisitedUsingwindow.navigatorpropertyYourconsoleisacheatsheetUsingwindow.locationpropertyUsingwindow.historypropertyusingwindow.framespropertyUsingwindow.screenpropertywindow.open()/close()methodwindow.moveTo()andwindow.resizeTo()methodswindow.alert(),window.prompt(),andwindow.confirm()methodsUsingwindow.setTimeout()andwindow.setInterval()methodswindow.documentproperty
DOMCoreDOMandHTMLDOMAccessingDOMnodesThedocumentnodedocumentElementChildnodesAttributesAccessingthecontentinsideatagDOMaccessshortcutsSiblings,body,first,andlastchild
![Page 10: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/10.jpg)
WalktheDOMModifyingDOMnodesModifyingstylesFunwithforms
CreatingnewnodesDOM-onlymethodUsingcloneNode()methodUsing insertBefore() method
RemovingnodesHTML-onlyDOMobjectsPrimitivewaystoaccessthedocumentUsingdocument.write()methodCookies,title,referrer,anddomain
EventsInlineHTMLattributesElementPropertiesDOMeventlistenersCapturingandbubblingStoppropagationPreventdefaultbehaviorCross-browsereventlistenersTypesofevents
XMLHttpRequestSendingtherequestProcessingtheresponseCreatingXMLHttpRequestobjectsinIEpriortoVersion7AisforAsynchronousXisforXMLAnexample
ExercisesSummary
11.CodingandDesignPatternsCoding patternsSeparatingbehaviorContentPresentationBehaviorExampleofseparatingbehavior
AsynchronousJavaScriptloadingNamespacesAnObjectasanamespaceNamespacedconstructors
![Page 11: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/11.jpg)
Anamespace()methodInit-timebranchingLazydefinitionConfigurationobjectPrivatepropertiesandmethodsPrivilegedmethodsPrivatefunctionsaspublicmethodsImmediate functionsModulesChainingJSONHigherorderfunctions
DesignpatternsSingletonpatternSingleton2patternGlobalvariablePropertyoftheconstructorInaprivateproperty
FactorypatternDecoratorpatternDecoratingachristmastree
ObserverpatternSummary
12.TestingandDebuggingUnittestingTestDrivenDevelopmentBehaviorDrivenDevelopmentMocha,ChaiandSinon
JavaScriptdebuggingSyntaxerrorsUsingstrict
RuntimeexceptionsConsole.log and assertsChromeDeveloperTools
Summary13.ReactiveProgrammingandReactReactiveprogrammingWhyshouldyouconsiderreactiveprogramming?
ReactVirtualDOMInstallingandrunningreactComponentsandprops
![Page 12: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/12.jpg)
StateLifecycleevents
SummaryA.ReservedWordsKeywordsES6reservedwordsFuturereservedwords
Previously reserved wordsB.Built-inFunctionsC.Built-inObjectsObjectMembersoftheObjectconstructorTheObject.prototypemembersECMAScript5additionstoobjects
ES6additiontoobjectsPropertyshorthandComputedpropertynamesObject.assign
ArrayTheArray.prototypemembersECMAScript5additionstoArrayES6additiontoarrays
FunctionTheFunction.prototypemembersECMAScript5additionstoaFunctionECMAScript6additionstoaFunction
BooleanNumberMembersoftheNumberconstructorTheNumber.prototypemembers
StringMembersoftheStringconstructorThe String.prototype membersECMAScript5additionstoStringECMAScript6additionstoString
DateMembersoftheDateconstructorTheDate.prototypemembersECMAScript5additionstoDate
MathMembersoftheMathobject
RegExp
![Page 13: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/13.jpg)
TheRegExp.prototypemembersErrorobjectsTheError.prototypemembers
JSONMembersoftheJSONobject
D.RegularExpressionsE.AnswerstoExerciseQuestionsChapter 2, Primitive Data Types, Arrays, Loops, and ConditionsExercises
Chapter3,FunctionsExercises
Chapter4,ObjectsExercises
Chapter5,PrototypeExercises
Chapter6,InheritanceExercises
Chapter7,TheBrowserEnvironmentExercises
![Page 14: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/14.jpg)
Object-Oriented JavaScript - Third Edition
![Page 15: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/15.jpg)
Object-Oriented JavaScript - Third EditionCopyright © 2017 Packt Publishing
Allrightsreserved.Nopartofthisbookmaybereproduced,storedinaretrievalsystem,ortransmittedinanyformorbyanymeans,withoutthepriorwrittenpermissionofthepublisher,exceptinthecaseofbriefquotationsembeddedincriticalarticlesorreviews.
Everyefforthasbeenmadeinthepreparationofthisbooktoensuretheaccuracyoftheinformationpresented.However,theinformationcontainedinthisbookissoldwithoutwarranty,eitherexpressorimplied.Neithertheauthors,norPacktPublishing,anditsdealersanddistributorswillbeheldliableforanydamagescausedorallegedtobecauseddirectlyorindirectlybythisbook.
PacktPublishinghasendeavoredtoprovidetrademarkinformationaboutallofthecompaniesandproducts mentioned in this book by the appropriate use of capitals. However, Packt Publishingcannotguaranteetheaccuracyofthisinformation.
Firstpublished:July2008
Secondedition:July2013
Thirdedition:January2017
Production reference: 1050117
PublishedbyPacktPublishingLtd.
LiveryPlace
35LiveryStreet
Birmingham
B32PB,UK.
ISBN978-1-78588-056-8
www.packtpub.com
![Page 16: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/16.jpg)
CreditsAuthors
VedAntani
StoyanStefanov
CopyEditor
ZainabBootwala
Reviewer
MohamedSanaulla
ProjectCoordinator
RitikaManoj
CommissioningEditor
WilsonDsouza
Proofreader
SafisEditing
AcquisitionEditor
DenimPinto
Indexer
RekhaNair
ContentDevelopmentEditor
ArunNadar
Graphics
JasonMonteiro
TechnicalEditor
AbhishekSharma
ProductionCoordinator
ArvindkumarGupta
![Page 17: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/17.jpg)
About the AuthorsVedAntani has been building scalable server and mobile platforms using JavaScript, Go, andJavasince2005.HeisanassociatevicepresidentatMyntraandhaspreviouslyworkedatElectronicArtsandOracle.Heisanavidreaderandauthoronseveralsubjects.HehasstudiedcomputerscienceandcurrentlylivesinBangalore,India.Vedispassionateaboutclassicalmusicandlovestospendtimewithhisson.
Writingthisbookrequiredasignificantinvestmentofmytime,andIwouldliketothankmyparentsandfamilyfortheirsupportandencouragementduringthoselongdaysandweekendswhenIwaspracticallyinvisible.
StoyanStefanovisaFacebookengineer,author,andspeaker.Hetalksregularlyaboutwebdevelopmenttopicsatconferences,andhisblog,www.phpied.com.Healsorunsanumberofothersites,includingJSPatterns.com-asitededicatedtoexploringJavaScriptpatterns.PreviouslyatYahoo!,StoyanwasthearchitectofYSlow2.0andcreatoroftheimageoptimizationtool,Smush.it.
A"citizenoftheworld", StoyanwasbornandraisedinBulgaria,butisalsoaCanadiancitizen,currentlyresidinginLos Angeles,California.Inhisofflinemoments,heenjoysplayingtheguitar,takingflyinglessons,andspendingtimeattheSantaMonicabeacheswithhisfamily.
I'dliketodedicatethisbooktomywife,Eva,andmydaughters,ZlatinaandNathalie.Thankyouforyourpatience,support,andencouragement.
![Page 18: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/18.jpg)
About the ReviewerMohamed Sanaulla is a software developer with more than 7 years of experience in developingenterpriseapplicationsandJava-basedback-endsolutionsfore-commerceapplications.
HisinterestsincludeEnterprisesoftwaredevelopment,refactoringandredesigningapplications,designingandimplementingRESTfulwebservices,troubleshootingJavaapplicationsforperformanceissues,andTDD.
HehasstrongexpertiseinJava-basedapplicationdevelopment,ADF(JSF-basedJavaEEwebframework),SQL,PL/SQL,JUnit,designingRESTfulservices,Spring,Struts,Elasticsearch,andMongoDB.HeisalsoaSunCertifiedJavaProgrammerfortheJava6platform.HeisamoderatorforJavaRanch.com.Helikestosharefindingsonhisblog(http://sanaulla.info).
![Page 19: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/19.jpg)
www.PacktPub.comFor support files and downloads related to your book, please visit www.PacktPub.com.
DidyouknowthatPacktofferseBookversionsofeverybookpublished,withPDFandePubfilesavailable?YoucanupgradetotheeBookversionatwww.PacktPub.comandasaprintbookcustomer,youareentitledtoadiscountontheeBookcopy.Getintouchwithusatservice@packtpub.comformoredetails.
Atwww.PacktPub.com,youcanalsoreadacollectionoffreetechnicalarticles,signupforarangeoffreenewslettersandreceiveexclusivediscountsandoffersonPacktbooksandeBooks.
https://www.packtpub.com/mapt
Getthemostin-demandsoftwareskillswithMapt.MaptgivesyoufullaccesstoallPacktbooksandvideocourses,aswellasindustry-leadingtoolstohelpyouplanyourpersonaldevelopmentandadvanceyourcareer.
![Page 20: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/20.jpg)
Why subscribe?FullysearchableacrosseverybookpublishedbyPacktCopyandpaste,print,andbookmarkcontentOndemandandaccessibleviaawebbrowser
![Page 21: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/21.jpg)
Customer FeedbackThank you for purchasing this Packt book. We take our commitment to improving our content andproductstomeetyourneedsseriously-that'swhyyourfeedbackissovaluable.Whateveryourfeelingsaboutyourpurchase,pleaseconsiderleavingareviewonthisbook'sAmazonpage.Notonlywillthishelpus,moreimportantlyitwillalsohelpothersinthecommunitytomakeaninformeddecisionabouttheresourcesthattheyinvestintolearn.Youcanalsoreviewforusonaregularbasisbyjoiningourreviewers'club.Ifyou'reinterestedinjoining,orwouldliketolearnmoreaboutthebenefitsweoffer,pleasecontactus:[email protected].
![Page 22: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/22.jpg)
PrefaceJavaScript has emerged as one of the most robust and versatile programming language around.ModernJavaScriptembracesavastarrayoftime-testedandcuttingedgefeatures.Severalofthesefeaturesareslowlygivingshapetothenextgenerationofwebandserverplatforms.ES6introducesveryimportantlanguageconstructs,suchaspromises,classes,arrowfunctions,andseveral,muchanticipatedfeatures.Thisbooktakesadetailedlookatthelanguageconstructsandtheirpracticaluses.Thisbookdoesn'tassumeanypriorknowledgeofJavaScriptandworksfromthegrounduptogiveyouathoroughunderstandingofthelanguage.Peoplewhoknowthelanguagewillstillfinditusefulandinformative.ForpeoplewhoalreadyknowJavaScriptandarefamiliarwithES5syntax,thisbookwillbeaveryusefulprimerforES6features.
![Page 23: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/23.jpg)
What this book coversChapter 1, Object-Oriented JavaScript, talks briefly about the history, present, and future ofJavaScript,andthenmovesontoexplorethebasicsofobject-orientedprogramming(OOP)ingeneral.Youwillthenlearnhowtosetupyourtrainingenvironment(Firebug)inordertodiveintothelanguageonyourown,usingthebookexamplesasabase.
Chapter2,PrimitiveDataTypes,Arrays,Loops,andConditions,discussesthelanguagebasics-variables,datatypes,primitivedatatypes,arrays,loops,andconditionals.
Chapter3,Functions,coversfunctionsthatJavaScriptuses,andhereyouwilllearntomasterthemall.YouwillalsolearnaboutthescopeofvariablesandJavaScript'sbuilt-infunctions.Aninteresting,butoftenmisunderstood,featureofthelanguage-closures-isdemystifiedattheendofthechapter.
Chapter 4, Objects, talks about objects, how to work with properties and methods, and thevariouswaystocreateyourobjects.Thischapteralsotalksaboutbuilt-in objectssuchasArray,Function,Boolean,Number,andString.
Chapter5,ES6IteratorsandGenerators,introducesthemostanticipatedfeaturesofES6,IteratorsandGenerators.Withthisknowledge,youwillproceedtotakeadetailedlookattheenhancedcollectionsconstructs.
Chapter6,Prototype,isdedicatedtotheall-importantconceptofprototypesinJavaScript.Italsoexplainshowtheprototypechainworks,hasOwnProperty(),andsomegotchasofprototypes.
Chapter7,Inheritance,discusseshowinheritanceworks.Thischapteralsotalksaboutamethodtocreatesubclasseslikeotherclassiclanguages.
Chapter8,ClassesandModules,showsthatES6introducesimportantsyntacticalfeaturesthatmakesiteasiertowriteclassicalobject-oriented programmingconstructs.ES6classsyntaxwrapstheslightlycomplexsyntaxofES5.ES6alsohasfulllanguagesupportformodules.ThischaptergoesintothedetailsoftheclassesandmoduleconstructsintroducedinES6.
Chapter9,PromisesandProxies,explainsthatJavaScripthasalwaysbeenalanguagewithstrongsupportforasynchronousprogramming.UpuntilES5,writingasynchronousprogramsmeantyouneededtorelyoncallbacks-sometimesresultingincallbackhell.ES6promisesareamuch-awaitedfeatureintroducedinthelanguage. PromisesprovideamuchcleanerwaytowriteasynchronousprogramsinES6.Proxiesareusedtodefinecustombehaviortosomeofthefundamentaloperations.ThischapterlooksatpracticalusesofbothpromisesandproxiesinES6.
Chapter 10, The Browser Environment, is dedicated to browsers. This chapter also covers BOM(BrowserObjectModel),DOM(W3C'sDocumentObjectModel),browserevents,andAJAX.
![Page 24: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/24.jpg)
Chapter11,CodingandDesignPatterns,divesintovariousuniqueJavaScriptcodingpatterns,aswellasseverallanguage-independentdesignpatterns,translatedtoJavaScriptfromtheBookofFour,themostinfluentialworkofsoftwaredesignpatterns.ThischapteralsodiscussesJSON.
Chapter12,TestingandDebugging,talksabouthowModernJavaScriptisequippedwithtoolsthatsupportTestDrivenDevelopmentandBehaviorDrivenDevelopment.Jasmineisoneofthemostpopulartoolsavailableatthemoment.ThischapterdiscussesTDDandBDDusingJasmineastheframework.
Chapter13,ReactiveProgrammingandReact,explainsthatwiththeadventofES6,severalradicalideasaretakingshape.Reactiveprogrammingtakesaverydifferentapproachtohowwemanagechangeofstatesusingdataflows.React,however,isaframeworkfocusingontheViewpartofMVC.Thischapterdiscussesthesetwoideas.
AppendixA,ReservedWords,liststhereservedwordsinJavaScript.
Appendix B, Built-in Functions, is a reference of built-in JavaScript functions together withsampleuses.
AppendixC,Built-inObjects,isareferencethatprovidesdetailsandexamplesoftheuseofeverymethodandpropertyofeverybuilt-inobjectinJavaScript.
AppendixD,RegularExpressions,isaregularexpressionspatternreference.
AppendixE,AnswerstoExerciseQuestions,hassolutionsforalltheexercisesmentionedattheendofthechapters.
![Page 25: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/25.jpg)
What you need for this bookYou need a modern browser-Google Chrome or Firefox are recommended, and an optionalNode.jssetup.Mostofthecodeinthisbookcanbeexecutedinhttp://babeljs.io/repl/orhttp://jsbin.com/.ToeditJavaScript,youcanuse anytexteditorofyourchoice.
![Page 26: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/26.jpg)
Who this book is forThis book is for anyone who is starting to learn JavaScript, or who knows JavaScript but isn'tverygoodattheobject-orientedpartofit.ThisbookcanbeausefulprimerforES6ifyouarealreadyfamiliarwiththeES5featuresofthelanguage.
![Page 27: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/27.jpg)
ConventionsIn this book, you will find a number of text styles that distinguish between different kinds ofinformation.Herearesomeexamplesofthesestylesandanexplanationoftheirmeaning.
Codewordsintext,databasetablenames,foldernames,filenames,fileextensions,pathnames,dummyURLs,userinput,andTwitterhandlesareshownasfollows:"TheTriangleconstructortakesthreepointobjectsandassignsthemtothis.points(itsowncollectionofpoints)."
Ablockofcodeissetasfollows:
functionsum(a,b){varc=a+b;returnc;}
Anycommand-lineinput oroutputiswrittenasfollows:
mkdirbabel_testcdbabel_test&&npminitnpminstall--save-devbabel-cli
Newtermsandimportantwordsareshowninbold.Wordsthatyouseeonthescreen,forexample,inmenusordialogboxes,appearinthetextlikethis:"InordertobringuptheconsoleinChromeorSafari,right-clickanywhereonapageandselectInspectElement.TheadditionalwindowthatshowsupistheWebInspectorfeature.SelecttheConsoletab,andyou'rereadytogo".
Note
Warningsorimportantnotesappearinaboxlikethis.
Tip
Tipsandtricksappearlikethis.
![Page 28: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/28.jpg)
Reader feedbackFeedback from our readers is always welcome. Let us know what you think about this book-whatyoulikedordisliked.Readerfeedbackisimportantforusasithelpsusdeveloptitlesthatyouwillreallygetthemostoutof.
Tosendusgeneralfeedback,[email protected],andmentionthebook'stitleinthesubjectofyourmessage.
Ifthereisatopicthatyouhaveexpertiseinandyouareinterestedineitherwritingorcontributingtoabook,seeourauthorguideatwww.packtpub.com/authors.
![Page 29: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/29.jpg)
Customer supportNow that you are the proud owner of a Packt book, we have a number of things to help you to getthemostfromyourpurchase.
![Page 30: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/30.jpg)
Errata
Althoughwehavetakeneverycaretoensuretheaccuracyofourcontent,mistakesdohappen.Ifyoufindamistakeinoneofourbooks-maybeamistakeinthetextorthecode-wewouldbegratefulifyoucouldreportthistous.Bydoingso,youcansaveotherreadersfromfrustrationandhelpusimprovesubsequentversionsofthisbook.Ifyoufindanyerrata,pleasereportthembyvisitinghttp://www.packtpub.com/submit-errata,selectingyourbook,clickingontheErrataSubmissionFormlink,andenteringthedetailsofyourerrata.Onceyourerrataareverified,yoursubmissionwillbeacceptedandtheerratawillbeuploadedtoourwebsiteoraddedtoanylistofexistingerrataundertheErratasectionofthattitle.
Toviewthepreviouslysubmittederrata,gotohttps://www.packtpub.com/books/content/supportandenterthenameofthebookinthesearchfield.TherequiredinformationwillappearundertheErratasection.
![Page 31: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/31.jpg)
Piracy
PiracyofcopyrightedmaterialontheInternetisanongoingproblemacrossallmedia.AtPackt,wetaketheprotectionofourcopyrightandlicensesveryseriously.IfyoucomeacrossanyillegalcopiesofourworksinanyformontheInternet,pleaseprovideuswiththelocationaddressorwebsitenameimmediatelysothatwecanpursuearemedy.
[email protected] piratedmaterial.
Weappreciateyourhelpinprotectingourauthorsandourabilitytobringyouvaluablecontent.
![Page 32: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/32.jpg)
Questions
Ifyouhaveaproblemwithanyaspectofthisbook,[email protected],andwewilldoourbesttoaddresstheproblem.
![Page 33: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/33.jpg)
Chapter 1. Object-Oriented JavaScriptEver since the early days of the web, there has been a need for more dynamic and responsiveinterfaces.Whileit'sOKtoreadstaticHTMLpagesoftext,andevenbetterwhentheyarebeautifullypresentedwiththehelpofCSS,it'smuchmorefuntoengagewithapplicationsinourbrowsers,suchase-mail,calendars,banking,shopping,drawing,playinggames,andtextediting.AllthatispossiblethankstoJavaScript,theprogramminglanguageoftheweb.JavaScriptstartedwithsimpleone-linersembeddedinHTML,butisnowusedinmuchmoresophisticatedways.Developersleveragethe object-orientednatureofthelanguagetobuildscalablecodearchitecturesmadeupof reusablepieces.
Ifyoulookatthepastandpresentbuzzwordsinwebdevelopment,DHTML,Ajax,Web2.0,HTML5,theyallessentiallymeanHTML,CSS,andJavaScript-HTMLforcontent,CSSforpresentation,andJavaScriptforbehavior.Inotherwords,JavaScriptisthegluethatmakeseverythingworktogethersothatwecanbuildrichwebapplications.
However,that'snotall;JavaScriptcanbeusedformorethanjusttheweb.
JavaScriptprogramsrun insideahostenvironment.Thewebbrowseristhemostcommonenvironment,butit'snottheonlyone.UsingJavaScript,youcancreateallkindsofwidgets,applicationextensions,andotherpiecesofsoftware,asyou'llseeinabit.TakingthetimetolearnJavaScriptisasmartinvestment;youlearnonelanguageandcanthenwriteallkindsofdifferentapplicationsrunningonmultipleplatforms,includingmobileandserver-sideapplications.Thesedays,it'ssafetosaythatJavaScriptiseverywhere.
Thisbookstartsfromzero,anddoesnotassumeanypriorprogrammingknowledgeotherthansomebasicunderstandingofHTML.Althoughthereisonechapterdedicatedtothewebbrowserenvironment,therestofthebookisaboutJavaScriptingeneral,soit'sapplicabletoallenvironments.
Let'sstartwiththefollowing:
AbriefintroductiontothestorybehindJavaScriptThebasicconceptsyou'llencounterindiscussionsonobject-orientedprogramming
![Page 34: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/34.jpg)
A bit of historyInitially, the web was not much more than just a number of scientific publications in the form ofstaticHTMLdocumentsconnectedtogetherwithhyperlinks.Believeitornot,therewasatimewhentherewasnowaytoputanimageinapage.However,thatsoonchanged.Asthewebgrewinpopularityandsize,thewebmasterswhowere creatingHTMLpagesfelttheyneededsomethingmore.Theywantedtocreatericheruserinteractions,mainlydrivenbythedesiretosaveserverroundtripsforsimpletaskssuchasformvalidation.Twooptionscameup-JavaappletsandLiveScript,alanguageconceivedbyBrendanEichatNetscapein1995andlaterincludedintheNetscape2.0browserunderthenameofJavaScript.
Theappletsdidn'tquitecatchon,butJavaScriptdid.TheabilitytouseshortcodesnippetsembeddedinHTMLdocumentsandalterotherwisestaticelementsofawebpagewasembracedbythewebmastercommunity.Soon,thecompetingbrowservendor,Microsoft,shippedInternetExplorer(IE)3.0withJScript,whichwasareverseengineeredversionofJavaScriptplussomeIE-specificfeatures.Eventually,therewasanefforttostandardizethevariousimplementationsofthelanguage,andthisishowECMAScriptwasborn.EuropeanComputerManufacturersAssociation(ECMA)createdthestandardcalledECMA-262,whichdescribesthecorepartsoftheJavaScriptprogramminglanguagewithoutbrowserandwebpage-specificfeatures.
YoucanthinkofJavaScriptasatermthatencompassesthefollowingthreepieces:
ECMAScript:Thecorelanguage-variables,functions,loops,andsoon.Thispartisindependentofthebrowserandthislanguagecanbeusedinmanyotherenvironments.DocumentObjectModel(DOM):ThisprovideswaystoworkwithHTMLandXMLdocuments.Initially,JavaScriptprovidedlimitedaccesstowhat'sscriptableonthepage,mainlyforms,links,andimages.Later,itwasexpandedtomakeallelementsscriptable.ThisledtothecreationoftheDOMstandardbytheWorldWideWebConsortium(W3C)asalanguage-independent(nolongertiedtoJavaScript)waytomanipulatestructureddocuments.Browser Object Model (BOM): This is a set of objects related to the browser environmentandwasneverpartofanystandarduntilHTML5startedstandardizingsomeofthecommonobjectsthatexistacrossbrowsers.
Whilethereisonechapterinthisbookdedicated tothebrowser,theDOM,andtheBOM,mostofthisbookdescribesthecorelanguageandteachesyouskillsyoucanuseinanyenvironmentwhereJavaScriptprogramsrun.
![Page 35: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/35.jpg)
Browserwarsandrenaissance
Forbetterorforworse,JavaScript'sinstantpopularityhappenedduringtheperiodofthebrowserwarsI(approximately1996to2001).ThosewerethetimesduringtheinitialInternetboomwhenthetwomajorbrowservendors,NetscapeandMicrosoft,werecompetingformarketshare.BothwereconstantlyaddingmorebellsandwhistlestotheirbrowsersandtheirversionsofJavaScript,DOM,andBOM,whichnaturallyledtomanyinconsistencies.Whileaddingmorefeatures,thebrowservendorswerefallingbehindonprovidingproperdevelopmentanddebuggingtoolsandadequatedocumentation.Often,developmentwasapain;youwouldwriteascriptwhiletestinginonebrowser,andonceyou'redonewithdevelopment,youtestintheotherbrowser,onlytofindthatyourscriptsimplyfails fornoapparentreason,andthebestyoucangetisacrypticerrormessage,suchasoperationaborted.
Inconsistentimplementations,missingdocumentation,andnoappropriatetoolspaintedJavaScriptin such a light that many programmers simply refused to bother with it.
Ontheotherhand,developerswhodidtrytoexperimentwithJavaScriptgotalittlecarriedaway,addingtoomanyspecialeffectstotheirpageswithoutmuchregardofhowusabletheendresultswere.Developerswereeagertomakeuseofeverynewpossibilitythebrowsersprovided,andendedupenhancingtheirwebpageswiththingssuchasanimationsinthestatusbar,flashingcolors,blinkingtexts,objectsstalkingyourmousecursor,andmanyotherinnovationsthatactuallyhurttheuserexperience.ThesevariouswaystoabuseJavaScriptarenowmostlygone,buttheywereoneofthereasonswhythelanguagehadsomethingofabadreputation.ManyseriousprogrammersdismissedJavaScriptasnothingbutatoyfordesignerstoplayaroundwith,anddismisseditasalanguageunsuitableforseriousapplications.TheJavaScriptbacklashcausedsomewebprojectstocompletelybananyclient-sideprogrammingandtrustonlytheirpredictableandtightlycontrolledserver.Andreally,whywouldyoudoublethetimetodeliverafinishedproductandthenspendadditionaltimedebuggingproblemswiththedifferentbrowsers?
EverythingchangedintheyearsfollowingtheendofthebrowserwarsI.Anumberofeventsreshapedthewebdevelopmentlandscapeinapositiveway.Someofthemaregivenasfollows:
MicrosoftwonthewarwiththeintroductionofIE6,thebestbrowseratthetime,andformanyyearstheystoppeddevelopingInternetExplorer.ThisallowedtimeforotherbrowserstocatchupandevensurpassIE'scapabilities.Themovementforwebstandardswasembracedbydevelopersandbrowservendorsalike.Naturally,developersdidn'tlikehavingtocodeeverythingtwo(ormore)timestoaccountforbrowsers'differences;therefore,theylikedtheideaofhavingagreed-uponstandardsthateveryonewouldfollow.Developersandtechnologiesmaturedandmorepeoplestartedcaringaboutthingssuchasusability,progressiveenhancementtechniques,andaccessibility.ToolssuchasFirebugmadedevelopersmuchmoreproductiveandthedevelopmentlessofapain.
![Page 36: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/36.jpg)
Inthishealthierenvironment,developersstartedfindingoutnewandbetterwaystousetheinstrumentsthatwerealreadyavailable.AfterthepublicreleaseofapplicationssuchasGmailandGoogleMaps,whichwererichonclient-sideprogramming,itbecameclearthatJavaScriptisamature,uniqueincertainways,andpowerfulprototypalobject-orientedlanguage.ThebestexampleofitsrediscoverywasthewideadoptionofthefunctionalityprovidedbytheXMLHttpRequestobject,whichwasonceanIE-onlyinnovation,butwasthenimplementedbymostotherbrowsers.XMLHttpRequestobjectallowsJavaScripttomake HTTPrequestsandgetfreshcontentfromtheserverinordertoupdatesomepartsofapagewithoutafullpagereload.DuetothewideuseoftheXMLHttpRequestobject,anewbreedofdesktop-likewebapplications,dubbedAjaxapplications,wasborn.
![Page 37: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/37.jpg)
Thepresent
AninterestingthingaboutJavaScriptisthatitalwaysrunsinsideahostenvironment.Thewebbrowserisjustoneoftheavailablehosts.JavaScriptcanalsorunontheserver,onthedesktop,andonmobiledevices.Today,youcanuseJavaScripttodoallofthefollowing:
Createrichandpowerfulwebapplications(thekindofapplicationsthatruninsidethewebbrowser).AdditionstoHTML5,suchasapplicationcache,client-sidestorage,anddatabases,makebrowserprogrammingmoreandmorepowerfulforbothonlineandofflineapplications.PowerfuladditionstoChromeWebKitalsoincludesupportforserviceworkersandbrowserpushnotifications.Writeserver-sidecodeusingNode.js,aswellascodethatcanrunusingRhino(aJavaScriptenginewritteninJava).Makemobileapplications;youcancreateappsforiPhone,Android, andotherphonesandtabletsentirelyinJavaScriptusingPhoneGaporTitanium.Additionally,appsforFirefoxOSformobilephonesareentirelyinJavaScript,HTML,andCSS.ReactNativefromFacebookisanexcitingnewwaytodevelopnativeiOS,Android,andWindows(experimental)applicationsusingJavaScript.Createrichmediaapplications,suchasFlashorFlex,usingActionScript,whichisbasedonECMAScript.Writecommand-linetoolsandscriptsthatautomateadministrativetasksonyourdesktopusingWindowsScriptingHost(WSH)orWebKit'sJavaScriptCore,whichisavailableonallMacs.Writeextensionsandpluginsforaplethoraofdesktopapplications,suchasDreamweaver,Photoshop,andmostotherbrowsers.Createcross-operatingsystemdesktopapplicationsusingMozilla'sXULRunnerandElectron.Electronisusedtobuildsomeofthemostpopularappsonthedesktop,suchasSlack,Atom,andVisualStudioCode.Emscripten,ontheotherhand,allowscode writteninC/C++tobecompiledintoanasm.jsformat,whichcanthenberuninsideabrowser.TestingframeworkslikePhantomJSareprogrammedusingJavaScript.This is by no means an exhaustive list. JavaScript started inside web pages, but today it'ssafetosayitispracticallyeverywhere.Inaddition,browservendorsnowusespeedasacompetitiveadvantageandareracingtocreatethefastestJavaScript engines,whichisgreatforbothusersanddevelopers,andopensdoorsforevenmorepowerfulusesofJavaScriptinnewareassuchasimage,audioandvideoprocessing,andgamesdevelopment.
![Page 38: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/38.jpg)
Thefuture
Wecanonlyspeculatewhatthefuturewillbe,butit'squitecertainthatitwillincludeJavaScript.Forquitesometime,JavaScriptmayhavebeenunderestimatedandunderused(ormaybeoverusedinthewrongways),buteveryday,wewitnessnewapplicationsofthelanguageinmuchmoreinterestingandcreativeways.Itallstartedwithsimpleone-liners,oftenembeddedinHTMLtagattributes,suchasonclick.Nowadays,developersshipsophisticated,well-designedandarchitected,andextensibleapplicationsandlibraries,oftensupportingmultipleplatformswithasinglecodebase.JavaScriptisindeedtakenseriously,anddevelopersarestartingtorediscoverandenjoyitsuniquefeaturesmoreandmore.
Oncelistedinthenice-to-havesectionsofjobpostings,today,knowledgeofJavaScriptisoftenadecidingfactorwhenitcomestohiringwebdevelopers.Commonjobinterviewquestionsyoucanheartodayinclude-IsJavaScriptanobject-orientedlanguage?Good.Now,howdoyouimplementinheritanceinJavaScript?Afterreadingthisbook,you'llbepreparedtoaceyourJavaScript job interview and even impress your interviewers with some bits that, maybe, theydidn'tknow.
![Page 39: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/39.jpg)
ECMAScript 5The last most important milestone in ECMAScript revisions was ECMAScript 5 (ES5),officiallyacceptedinDecember2009.ECMAScript5standardisimplementedandsupportedonallmajorbrowsersandserver-sidetechnologies.
ES5wasamajorrevisionbecauseapartfromseveralimportantsyntacticchangesandadditionstothestandardlibraries, ES5alsointroducedseveralnewconstructsinthelanguage.
Forinstance,ES5introducedsomenewobjectsandproperties,andalsotheso-calledstrictmode.Strictmodeisasubsetofthelanguagethatexcludesdeprecatedfeatures.Thestrictmodeisopt-inandnotrequired,meaningthatifyouwantyourcodetoruninthestrictmode,youwilldeclareyourintentionusing(onceperfunction,oronceforthewholeprogram)thefollowingstring:
"usestrict";
ThisisjustaJavaScriptstring,andit'soktohavestringsfloatingaroundunassignedtoanyvariable.Asaresult,olderbrowsersthatdon'tspeakES5willsimplyignoreit,sothisstrictmodeisbackwardscompatibleandwon'tbreakolderbrowsers.
Forbackwardscompatibility,alltheexamplesin thisbookworkinES3,butatthesametime,allthecodeinthebookiswrittensothatitwillrunwithoutwarningsinES5'sstrictmode.Additionally, any ES5-specific parts will be clearly marked. Appendix C, Built-in Objects, liststhenewadditionstoES5indetail.
![Page 40: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/40.jpg)
StrictmodeinES6
WhilestrictmodeisoptionalinES5,allES6modulesandclassesarestrictbydefault.Asyouwillseesoon,mostofthecodewewriteinES6residesinamodule;hence,strictmodeisenforcedbydefault.However,itisimportanttounderstandthatallotherconstructsdonothaveimplicitstrictmodeenforced.Therewereefforts tomakenewerconstructs,suchasarrowandgeneratorfunctions,toalsoenforcestrictmode,butitwaslaterdecidedthatdoingsowouldresultinveryfragmentedlanguagerulesandcode.
![Page 41: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/41.jpg)
ECMAScript 6ECMAScript 6 revision took a long time to finish and was finally accepted on June 17, 2015. ES6featuresareslowlybecomingpartofmajorbrowsersandservertechnologies.ItispossibletousetranspilerstocompileES6toES5andusethecodeonenvironmentsthatdonotyetsupportES6completely(wewilldiscusstranspilersindetaillater).
ES6substantiallyupgradesJavaScriptasalanguageandbringsinveryexcitingsyntacticalchangesandlanguageconstructs.Broadly,therearetwokindsoffundamentalchangesinthisrevisionofECMAScript,whichareasfollows:
Improvedsyntaxforexistingfeaturesandeditionstothestandardlibrary;forexample,classesandpromisesNewlanguagefeatures;forexample,generators
ES6allowsyoutothinkdifferentlyaboutyourcode.Newsyntaxchangescanletyouwritecodethatiscleaner,easiertomaintain,anddoesnotrequirespecialtricks.Thelanguageitselfnowsupportsseveralconstructsthatrequiredthird-partymodulesearlier.LanguagechangesintroducedinES6needaseriousrethinkinthewaywehavebeencodinginJavaScript.
Anoteonthenomenclature-ECMAScript6,ES6,andECMAScript2015arethesame,butusedinterchangeably.
![Page 42: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/42.jpg)
BrowsersupportforES6
ThemajorityofthebrowsersandserverframeworksareontheirwaytowardsimplementingES6features.Youcancheckoutthewhatissupportedandwhatisnotbyclickinghttp://kangax.github.io/compat-table/es6/.
ThoughES6isnotfullysupportedonallbrowsersandserverframeworks,wecanstartusingalmostallfeaturesofES6withthehelpoftranspilers.Transpilersaresource-to-sourcecompilers.ES6transpilersallowyoutowritecodeinES6syntaxandcompile/transformthemintoequivalentES5syntax,whichcanthenberunonbrowsersthatdonotsupporttheentirerangeofES6features.
ThedefactoES6transpileratthemomentisBabel.Inthisbook,wewilluseBabelandwriteandtestourexamples.
![Page 43: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/43.jpg)
Babel
BabelsupportsalmostallES6featuresoutoftheboxorwithcustomplugins.Babelcanbeusedfromawiderangeofbuildsystems,frameworks, andlanguagestotemplateengines,andhasagoodcommandlineandread-eval-printloop(REPL)builtin.
TogetagoodideaabouthowBabeltranspilesES6codetoitsES5equivalentform,headovertoBabelREPL(http://babeljs.io/repl/).
BabelREPLallowsyoutoquicklytestsmallsnippetsofES6.WhenyouopenBabelREPLinthebrowser, you will see some ES6 code defaulted there. On the left pane, remove the code and typeinthefollowingtext:
varname="John",mood="happy";console.log(`Hey${name},areyoufeeling${mood}today?`)
Whenyoutypethisandtaboutoftheleftpane,youwillseeREPLtranspilingthisES6codeintosomethinglikethefollowingcode:
"usestrict";varname="John",mood="happy";console.log("Hey"+name+",areyoufeeling"+mood+"today?");
ThisistheES5equivalentofthecodewewroteearlierintheleftpane.Youcanseethattheresulting code in the right pane is a familiar ES5. As we said, Babel REPL is a good place to tryandexperimentwithvariousES6constructs.However,weneedbabeltoautomaticallytranspileyourES6codeintoES5,andforthat,youcanincludeBabelintoyourexistingbuildsystemsorframeworks.
Let'sbeginbyinstallingBabelasacommand-linetool.Forthis,wewillassumethatyouarefamiliarwithnodeandNodePackageManager (npm).InstallingBabelusingnpmiseasy.Let'sfirstcreateadirectorywherewewillhaveBabelinstalledasamoduleandrestofthesourcecode.OnmyMac,thefollowingcommandswillcreateadirectorycalledbabel_test,initializetheprojectusingnpminit,andinstallBabelcommandlineusingnpm:
mkdirbabel_testcdbabel_test&&npminitnpminstall--save-devbabel-cli
Ifyouarefamiliarwithnpm,youmaygettemptedtoinstallBabelglobally.However,installingBabelasaglobalmoduleisnotgenerallyagoodidea.OnceyouhaveinstalledBabelinyourproject,yourpackage.jsonfilewilllooksomethinglikethefollowingblockofcode:
{
![Page 44: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/44.jpg)
"name":"babel_test","version":"1.0.0","description":"","main":"index.js","scripts":{"test":"echo"Error:notestspecified"&&exit1"},"author":"","license":"ISC","devDependencies":{"babel-cli":"^6.10.1"}}
YoucanseeadevelopmentdependencycreatedforBabelforversion>6.10.1.YoucanuseBabeltotranspileyourcodebyeitherinvokingitfromthecommandlineoraspartofthebuildstep.Foranynon-trivialwork,youwillneedthelaterapproach.ToinvokeBabelaspartoftheprojectbuildstep,youcanaddabuildstepinvokingBabelinsideyourscripttagtoyourpackage.jsonfile,forexample:
"scripts":{"build": "babel src -d lib"
},
Whenyoudonpmbuild,Babelwillbeinvokedonyoursrcdirectoryandthetranspiledcodewillbeplacedinsidelibdirectory.Alternatively,youcanrunBabelmanuallyalsobywritingthefollowingcommand:
$./node_modules/.bin/babelsrc-dlib
WewilltalkaboutvariousBabeloptionsandpluginslaterinthebook.ThissectionwillequipyoutostartexploringES6.
![Page 45: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/45.jpg)
Object-oriented programmingBefore diving into JavaScript, let's take a moment to review what people mean when they sayobject-oriented,andwhatthemainfeaturesofthisprogrammingstyleare.Here'salistofconceptsthataremostoftenusedwhentalkingaboutobject-orientedprogramming(OOP):
Object,method,andpropertyClassEncapsulationAggregationReusability/inheritancePolymorphism
Let'stakeacloserlookintoeachoneoftheseconcepts.Ifyou'renewtotheobject-orientedprogramminglingo,theseconceptsmightsoundtootheoretical,andyoumighthavetroublegraspingorrememberingthemfromonereading.Don'tworry,itdoestakeafewtries,andthesubjectcanbealittledryataconceptuallevel.However,we'lllookatplentyofcodeexamplesfurtheroninthebook,andyou'llseethatthingsaremuchsimplerinpractice.
![Page 46: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/46.jpg)
Objects
Asthenameobject-orientedsuggests,objectsareimportant.Anobjectisarepresentationofathing(someoneorsomething),andthisrepresentationisexpressedwiththehelpofaprogramminglanguage.Thethingcanbeanything,areal-lifeobject,oramoreconvolutedconcept.Takingacommonobject,acat,forexample,youcanseethatithascertaincharacteristics-color,name,weight,andsoonandcanperformsomeactions-meow,sleep,hide,escape,andsoon.ThecharacteristicsoftheobjectarecalledpropertiesinOOP-speak,andtheactionsarecalledmethods.
Theanalogywiththespokenlanguageareasfollows:
Objectsaremostoftennamedusingnouns,suchasbook,person,andsoonMethodsareverbs,forexample,read,run,andsoonValuesofthepropertiesareadjectives
Takethesentence"Theblackcatsleepsonthemat"asanexample."Thecat"(anoun)istheobject,"black"(adjective)isthevalueofthecolorproperty,and"sleep"(averb)isanactionoramethodinOOP.Forthesakeoftheanalogy,wecangoastepfurtherandsaythat"onthemat"specifiessomethingabouttheaction"sleep",soit'sactingasaparameterpassedtothesleepmethod.
![Page 47: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/47.jpg)
Classes
Inreallife,similarobjectscanbegroupedbasedonsomecriteria.Ahummingbirdandaneaglearebothbirds,sotheycanbeclassifiedasbelongingtosomemade-upBirdsclass.InOOP,aclassisablueprintorarecipeforanobject.Anothernameforobjectisinstance,sowecansaythattheeagleisoneconcreteinstanceofthegeneralBirdsclass.Youcancreatedifferentobjectsusingthesameclassbecauseaclassisjustatemplate,whiletheobjectsareconcreteinstancesbasedonthetemplate.
There'sadifferencebetweenJavaScriptandtheclassicOOlanguagessuchasC++andJava.YoushouldbeawarerightfromthestartthatinJavaScript,therearenoclasses;everythingisbasedonobjects.JavaScripthasthenotionofprototypes,whicharealsoobjects(we'lldiscussthemlaterindetail).InaclassicOOlanguage,you'dsaysomethinglike-createanewobjectformecalledBob,whichisofclassPerson.InaprototypalOOlanguage,you'dsay-I'mgoingtotakethisobjectcalledBob'sdadthatIhavelyingaround(onthecouchinfrontoftheTV?)andreuseitasaprototypeforanewobjectthatI'llcallBob.
![Page 48: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/48.jpg)
Encapsulation
Encapsulationisanother OOPrelatedconcept,whichillustratesthefactthatanobjectcontains(encapsulates)thefollowing:
Data(storedinproperties)Themeanstodosomethingwiththedata(usingmethods)
Oneothertermthatgoestogetherwithencapsulationisinformationhiding.Thisisaratherbroadtermandcanmeandifferentthings,butlet'sseewhatpeopleusuallymeanwhentheyuseitinthecontextofOOP.
Imagineanobject,say,anMP3player.You,astheuseroftheobject,aregivensomeinterfacetoworkwith,suchasbuttons,display,andsoon.Youusetheinterfaceinordertogettheobjecttodosomethingusefulforyou,likeplayasong.Howexactlythedeviceisworkingontheinside,youdon'tknow,and,mostoften,don'tcare.Inotherwords,theimplementationoftheinterfaceishiddenfromyou.ThesamethinghappensinOOPwhenyourcodeusesanobjectbycallingitsmethods.Itdoesn'tmatterifyoucodedtheobjectyourselforitcamefromsomethird-partylibrary;yourcodedoesn'tneedtoknowhowthemethodsworkinternally. Incompiledlanguages,youcan'tactuallyreadthecodethatmakesanobjectwork.InJavaScript,becauseit'saninterpretedlanguage,youcanseethesourcecode,buttheconceptisstillthesame-youworkwiththe object's interface without worrying about its implementation.
Anotheraspectofinformationhidingisthevisibilityofmethodsandproperties.Insomelanguages,objectscanhavepublic,private,andprotectedmethodsandproperties.Thiscategorizationdefinesthelevelofaccesstheusersoftheobjecthave.Forexample,onlythemethodsofthesameobjecthaveaccesstotheprivatemethods,whileanyonehasaccesstothepublicones.InJavaScript,allmethodsandpropertiesarepublic,butwe'llseethattherearewaystoprotectthedatainsideanobjectandachieveprivacy.
![Page 49: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/49.jpg)
Aggregation
Combiningseveralobjectsintoanewoneisknownasaggregationorcomposition.It'sapowerfulwaytoseparateaproblemintosmallerandmoremanageableparts(divideandconquer).Whenaproblemscopeissocomplexthatit'simpossibletothinkaboutitatadetailedlevelinitsentirety,youcanseparatetheproblemintoseveralsmallerareas,andpossiblythenseparateeachoftheseintoevensmallerchunks.Thisallowsyoutothinkabouttheproblemonseverallevelsofabstraction.
Take,forexample,apersonalcomputer.It'sacomplexobject.Youcannotthinkaboutallthethingsthatneedtohappenwhenyoustartyourcomputer.But,youcanabstracttheproblemsayingthatyouneedtoinitializealltheseparateobjectsthatyourComputerobjectconsistsoftheMonitorobject,theMouseobject,theKeyboardobject,andsoon.Then,youcandivedeeperintoeachofthesubobjects.Thisway,you'recomposingcomplexobjectsbyassemblingreusableparts.
Touseanotheranalogy,aBookobjectcancontain(aggregate)oneormoreAuthorobjects,aPublisherobject,severalChapterobjects,aTOC(tableofcontents),andsoon.
![Page 50: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/50.jpg)
Inheritance
Inheritanceisanelegantwaytoreuseexistingcode.Forexample,youcanhaveagenericobject,Person,whichhaspropertiessuchasnameanddate_of_birth,andwhichalsoimplementsthewalk,talk,sleep,andeatfunctionality.Then,youfigureoutthatyouneedanotherobjectcalledProgrammer.YoucanreimplementallthemethodsandpropertiesthataPersonobjecthas,butitwillbesmartertojustsaythattheProgrammerobjectinheritsaPersonobject,andsaveyourselfsomework.TheProgrammerobjectonlyneedstoimplementmorespecificfunctionality,suchasthewriteCodemethod,whilereusingallofthePersonobject'sfunctionality.
InclassicalOOP,classesinheritfromotherclasses,butinJavaScript,astherearenoclasses,objectsinheritfromotherobjects.
Whenanobjectinheritsfromanotherobject,itusuallyaddsnewmethodstotheinheritedones,thusextendingtheoldobject.Often,thefollowingphrasescanbeusedinterchangeably-BinheritsfromAandBextendsA.Also,theobjectthatinheritscanpickoneormoremethodsandredefinethem, customizing them for its own needs. This way, the interface stays the same and the methodnameisthesame,butwhencalledonthenewobject,themethodbehavesdifferently.Thiswayofredefininghowaninheritedmethodworksisknownasoverriding.
![Page 51: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/51.jpg)
Polymorphism
Intheprecedingexample,aProgrammerobjectinheritedallofthemethodsoftheparentPersonobject.Thismeansthatbothobjectsprovideatalkmethod,amongothers.Nowimaginethatsomewhereinyourcode,there'savariablecalledBob,anditjustsohappensthatyoudon'tknowifBobisaPersonobjectoraProgrammerobject.YoucanstillcallthetalkmethodontheBobobjectandthecodewillwork.Thisabilitytocallthesamemethodondifferentobjects,andhaveeachofthemrespondintheirownway,iscalledpolymorphism.
![Page 52: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/52.jpg)
OOP summaryHere's a quick table summarizing the concepts discussed so far:
FeatureIllustratesconcept
Bobisaman(anobject). Objects
Bob'sdateofbirthisJune1,1980,gender-male,andhair-black. Properties
Bobcaneat,sleep,drink,dream,talk,andcalculatehisownage. Methods
BobisaninstanceoftheProgrammerclass.Class(inclassicalOOP)
BobisbasedonanotherobjectcalledProgrammer.
Prototype
(inprototypalOOP)
Bobholdsdata,suchasbirth_date,andmethodsthatworkwiththedata,suchascalculateAge(). Encapsulation
Youdon'tneedtoknowhowthecalculationmethodworksinternally.Theobjectmighthavesomeprivatedata,suchasthenumberofdaysinFebruaryinaleapyear.Youdon'tknow,nordoyouwanttoknow.
Informationhiding
BobispartofaWebDevTeamobjecttogetherwithJill,aDesignerobject,andJack,aProjectManagerobject.Aggregationandcomposition
Designer,ProjectManager,andProgrammerareallbasedonandextendaPersonobject. Inheritance
YoucancallthemethodsBob.talk(),Jill.talk(),andJack.talk(),andthey'llallworkfine,albeitproducingdifferentresults.Bobwillprobablytalkmoreaboutperformance,Jillaboutbeauty,andJackaboutdeadlines.EachobjectinheritedthemethodtalkfromPersonandcustomizedit.
Polymorphismandmethodoverriding
![Page 53: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/53.jpg)
Setting up your training environmentThis book takes a do-it-yourself approach when it comes to writing code, because I firmlybelievethatthebestwaytoreallylearnaprogramminglanguageisbywritingcode.Therearenocut-and-paste-readycodedownloadsthatyousimplyputinyourpages.Onthecontrary,you'reexpectedtotypeincode,seehowitworks,andthentweakitandplayaroundwithit.Whentryingoutthecodeexamples,you'reencouragedtoenterthecodeintoaJavaScriptconsole.Let'sseehowyougoaboutdoingthis.
Asadeveloper,youmostlikelyalreadyhaveanumberofwebbrowsersinstalledonyoursystem,suchasFirefox,Safari,Chrome,orInternetExplorer.AllmodernbrowsershaveaJavaScriptconsolefeaturethatyou'llusethroughoutthebooktohelpyoulearnandexperimentwiththelanguage.Morespecifically,thisbookusesWebKit'sconsole,whichisavailableinSafariandChrome,buttheexamplesshouldworkinanyotherconsole.
![Page 54: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/54.jpg)
WebKit'swebinspector
Thisexampleshowshowyoucanusetheconsoletotypeinsomecodethatswapsthelogoonthegoogle.comhomepagewithanimageofyourchoice.Asyoucansee,you cantestyourJavaScriptcodeliveonanypage:
InordertobringuptheconsoleinChromeorSafari,rightclickanywhereonapageandselectInspectElement.TheadditionalwindowthatshowsupistheWebInspectorfeature.SelecttheConsoletab,andyou'rereadytogo.
Youtypecodedirectlyintotheconsole,andwhenyoupressEnter,yourcodeisexecuted.The
![Page 55: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/55.jpg)
returnvalueofthecodeisprintedintheconsole.Thecodeisexecutedinthecontextofthecurrentlyloadedpage,so,forexample,ifyoutypelocation.href,itwillreturntheURLofthecurrentpage.
The console also has an autocomplete feature. It works in a similar way to the normal command-linepromptinyouroperatingsystemorautocompletefeatureofthefull-fledgedIDEs.If,forexample,youtypedocuandhittheTaborrightarrowkey,docuwillbeautocompletedtodocument.Then,ifyoutype.(thedotoperator),youcaniteratethroughalltheavailablepropertiesandmethodsyoucancallonthedocumentobject.
Byusingtheupanddownarrowkeys,youcangothroughthelistofalreadyexecutedcommandsandbringthembackintheconsole.
Theconsolegivesyouonlyonelinetotypein,butyoucanexecuteseveralJavaScriptstatementsbyseparatingthemwithsemicolons.Ifyouneedmorelines,youcanpressShift+Entertogotoanewlinewithoutexecutingtheresultjustyet.
![Page 56: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/56.jpg)
JavaScriptCoreonaMac
OnaMac,youdon'tactuallyneedabrowser;youcanexploreJavaScriptdirectlyfromyourcommandlineTerminalapplication.
Ifyou'veneverusedTerminal,youcansimplysearchforitinSpotlightsearch.Onceyou'velaunchedit,typethefollowingcommand:
aliasjsc='/System/Library/Frameworks/JavaScriptCore.framework/Versions/Current/Resources/jsc'
ThiscommandmakesanaliastothelittlejscapplicationthatstandsforJavaScriptCoreandispartoftheWebKitengine.JavaScriptCoreisshippedtogetherwithMacoperatingsystems.
You can add the alias line shown previously to your ~/.profile file so that jsc is always therewhen you need it.
Now,inordertostarttheinteractiveshell,youwillsimplytypejscfrom anydirectory.Then,youcantypeJavaScriptexpressions,andwhenyouhitEnter,you'llseetheresultoftheexpression.Takealookatthefollowingscreenshot:
![Page 57: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/57.jpg)
Moreconsoles
Allmodernbrowsershaveconsolesbuiltin.YouhaveseentheChrome/Safariconsolepreviously.InanyFirefoxversion,youcaninstalltheFirebugextension,whichcomeswithaconsole.Additionally,innewerFirefoxreleases,there'saconsolebuiltinandaccessibleviatheTools|WebDeveloper|WebConsolemenu.
InternetExplorer,sinceversion8,hasanF12DeveloperToolsfeature,whichhasaconsoleinitsScripttab.
It'salsoagoodideatofamiliarizeyourselfwithNode.js,andyoucanstartbytryingoutitsconsole.InstallNode.jsfromhttp://nodejs.organdtrytheconsoleinyourcommandprompt(terminal):
![Page 58: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/58.jpg)
Asyoucansee,youcanusetheNode.jsconsoletotryoutquickexamples.But,youcanalsowritelongershellscripts(test.jsinthescreenshot)andrunthemwiththescriptname.jsnode.
NodeREPLisapowerfuldevelopmenttool.Whenyoutype'node'onthecommandline,theREPLinvokes.YoucantryoutJavaScriptonthis REPL:
node>console.log("HellowWorld");HellowWorldundefined>a=10,b=10;10>console.log(a*b);100undefined
![Page 59: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/59.jpg)
SummaryIn this chapter, you learned about how JavaScript was born, and where it is today. You were alsointroducedtoobject-orientedprogrammingconceptsandhaveseenhowJavaScriptisnotaclass-basedOOlanguage,butaprototype-basedone.Finally,youlearnedhowtouseyourtrainingenvironment-theJavaScriptconsole.Now,you'rereadytodiveintoJavaScriptandlearnhowtouseitspowerfulOOfeatures.However,let'sstartfromthebeginning.
ThenextchapterwillguideyouthroughthedatatypesinJavaScript(therearejustafew),conditions,loops,andarrays.Ifyouthinkyouknowthesetopics,feelfreetoskipthenextchapter,butnotbeforeyoumakesureyoucancompletethefewshortexercisesattheendofthechapter.
![Page 60: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/60.jpg)
Chapter 2. Primitive Data Types, Arrays,Loops,andConditionsBeforedivingintotheobject-orientedfeaturesof JavaScript,let'sfirsttakealookatsomeofthebasics.Thischapterwalksyouthroughthefollowingtopics:
TheprimitivedatatypesinJavaScript,such asstringsandnumbersArraysCommonoperators,suchas+,-,delete,andtypeofFlowcontrolstatements,suchasloopsandif...elseconditions
![Page 61: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/61.jpg)
VariablesVariables are used to store data; they are placeholders for concrete values. When writingprograms,it'sconvenienttousevariablesinsteadoftheactualdataasit'smucheasiertowritepiinsteadof3.141592653589793;especiallywhenithappensseveraltimesinsideyourprogram.Thedatastoredinavariablecanbechangedafteritinitiallyassigned,hencethenamevariable.Youcanalsousevariablestostoredatathatisunknowntoyouwhileyouwritethecode,suchastheresultofalateroperation.
Usingavariablerequiresthefollowingtwosteps.Youwillneedto:
Declare the variableInitializeit,thatis,giveitavalue
Todeclareavariable,youwillusethevarstatementlikethefollowingpieceofcode:
vara;varthisIsAVariable;var_and_this_too;varmix12three;
Forthenamesofthevariables,youcanuseanycombinationofletters,numbers,theunderscorecharacter,andthedollarsign.However,youcan'tstartwithanumber,whichmeansthatthefollowingdeclarationofcodeisinvalid:
var2three4five;
Toinitializeavariablemeanstogiveitavalueforthefirst(initial)time.Thefollowingarethetwowaystodoso:
Declarethevariablefirst,theninitializeitDeclareandinitializeitwithasinglestatement
Anexampleofthelatterisasfollows:
vara=1;
Nowthevariablenamedacontainsthevalue1.
Youcandeclare,andoptionallyinitialize,severalvariableswithasinglevarstatement;justseparatethedeclarationswithacomma,asshowninthefollowinglineofcode:
varv1,v2,v3='hello',v4=4,v5;
Forreadability,thisisoftenwrittenusingonevariableperline,asfollows:
varv1,
![Page 62: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/62.jpg)
v2,v3='hello',v4=4,v5;
Note
The$characterinvariablenames
Youmayseethedollarsigncharacter($)usedinvariablenames,asin$myvarorlesscommonlymy$var.Thischaracterisallowedtoappearanywhereinavariablename,althoughpreviousversionsoftheECMAstandarddiscourageditsuseinhandwrittenprogramsandsuggesteditshouldonlybeusedingeneratedcode(programs writtenbyotherprograms).ThissuggestionisnotwellrespectedbytheJavaScriptcommunity,and$isinfactcommonlyusedinpracticeasafunctionname.
![Page 63: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/63.jpg)
Variablesarecasesensitive
Variablenamesarecasesensitive.YoucaneasilyverifythisstatementusingyourJavaScriptconsole.TrytypingthefollowingcodebypressingEnteraftereachline:
varcase_matters='lower';varCASE_MATTERS='upper';case_matters;CASE_MATTER;
Tosavekeystrokeswhenyouenterthethirdline,youcantypecaseandpresstheTaborrightarrowkey.Consoleautocompletesthevariablenametocase_matters.Similarly,forthelastline,typeCASEandpresstheTabkey.Theendresultisshowninthefollowingfigure:
Throughouttherestofthisbook,onlythecodefortheexamplesisgiveninsteadofascreenshot,asfollows:
>varcase_matters='lower';>varCASE_MATTERS='upper';
> case_matters;"lower">CASE_MATTERS;"upper"
Thegreater-thansigns(>)showthecodethatyoutype;therestistheresultasprintedinConsole.
![Page 64: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/64.jpg)
Again,rememberthatwhenyouseesuchcodeexamples,you'restronglyencouragedtotypeinthecodeyourself.Then,youcanexperimentbytweakingitalittlehereandtheretogetabetterfeelingofhowexactlyitworks.
Note
YoucanseeintheprecedingscreenshotthatsometimeswhatyoutypeinConsoleresultsinthewordundefined.Youcansimplyignorethis,butifyou'recurious,here'swhathappenswhenevaluating(executing)whatyoutype-theConsoleprintsthereturnedvalue.Someexpressions,suchasvara=1;,don'treturnanythingexplicitly,inwhichcase,theyimplicitlyreturnthespecialvalueundefined(moreoninabit).Whenanexpressionreturnssomevalue(forexample,case_mattersinthepreviousexampleorsomethingsuchas1+1),theresultingvalueisprintedout.Notallconsolesprinttheundefinedvalue;forexample,theFirebugconsole.
![Page 65: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/65.jpg)
OperatorsOperators take one or two values (or variables), perform an operation, and return a value. Let'scheckoutasimpleexampleofusinganoperator,justtoclarifytheterminology:
>1+2;3
Intheprecedingcode:
The+symbolistheoperatorTheoperationisadditionTheinputvaluesare1and2(theyarealsocalledoperands)Theresultvalueis3Thewholethingiscalledanexpression
Insteadofusingthevalues1and2directlyintheexpression,youcanusevariables.Youcanalsouseavariabletostoretheresultoftheoperationasthefollowingexampledemonstrates:
>vara=1;>varb=2;>a+1;2>b+2;4>a+b;3>varc=a+b;>c;3
Thefollowingtableliststhebasicarithmeticoperators:
Operatorsymbol
Operation Example
+ Addition>1+2;3
- Subtraction>99.99-11;88.99
* Multiplication>2*3;6
/ Division>6/4;1.5
![Page 66: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/66.jpg)
%Modulo,theremainderofadivision
>6%3;0>5%3;2
It'ssometimesusefultotestifanumberisevenorodd.Usingthemodulooperator,it'seasytodojustthat.Alloddnumbersreturn1whendividedby2,whileallevennumbersreturn0,forexample:
>4%2;0>5%2;1
++Incrementavalue by 1
Postincrementiswhentheinputvalueisincrementedafterit'sreturned,forexample:
>vara=123;>varb=a++;>b;123>a;124
Theoppositeispre-increment.Theinputvalueisincrementedby1firstandthenreturned,forexample:
>vara=123;>varb=++a;>b;124>a;124
--Decrementavalueby1
Post-decrement:
>vara=123;>varb=a--;>b;123>a;122
Pre-decrement:
>vara=123;>varb=--a;>b;122>a;122
Thevara=1;isalsoanoperation;it'sthesimpleassignmentoperation,and=isthesimpleassignmentoperator.
Thereisalsoafamilyof operatorsthatareacombinationofanassignmentandanarithmeticoperator. These are called compound operators. They can make your code more compact. Let'sseesomeofthemwiththefollowingexamples:
>vara=5;>a+=3;8
![Page 67: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/67.jpg)
Inthisexample,a+=3;isjustashorterwayofdoinga=a+3;.Forexample:
>a-=3;5
Here,a-=3;isthesameasa=a-3;:
>a*=2;10>a/=5;2>a%=2;0
Inadditiontothearithmeticandassignmentoperatorsdiscussedpreviously,thereareothertypesofoperators,asyou'llseelaterinthis,andthefollowingchapters.
Note
Bestpractice
Alwaysendyourexpressionswithasemicolon.JavaScripthasasemicoloninsertionmechanism,whereitcanaddthesemicolonifyouforgetitattheendofaline.However,thiscanalsobeasourceoferrors,soit'sbesttomakesureyoualwaysexplicitlystatewhereyouwanttoterminateyourexpressions.Inotherwords,bothexpressions>1+1and>1+1;willwork;butthroughoutthebook,you'llalwaysseethesecondtype,terminatedwithasemicolon,justtoemphasizethishabit.
![Page 68: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/68.jpg)
Primitive data typesAny value that you use is of a certain type. In JavaScript, the following are just a few primitivedatatypes:
1. Number:Thisincludesfloatingpointnumbersaswellasintegers.Forexample,thesevaluesareallnumbers-1,100,3.14.
2. String:Theseconsistofanynumberofcharacters,forexample,a,one,andone2three.3. Boolean:Thiscanbeeithertrueorfalse.4. Undefined:Whenyoutrytoaccessavariablethatdoesn'texist,yougetthespecialvalueundefined.Thesamehappenswhenyoudeclareavariablewithoutassigningavaluetoityet.JavaScriptinitializesthevariablebehindthesceneswiththevalueundefined.Theundefineddatatype canonlyhaveonevalue-thespecialvalueundefined.
5. Null:Thisisanotherspecialdatatypethatcanhaveonlyonevalue-thenullvalue.Itmeansnovalue,anemptyvalue,ornothing.Thedifferencewithundefinedisthatifavariablehasanullvalue,it'sstilldefined;itjustsohappensthatitsvalueisnothing.You'llseesomeexamplesshortly.
Anyvaluethatdoesn'tbelongtooneofthefiveprimitivetypeslistedhereisanobject.Evennullisconsideredanobject,whichisalittleawkwardhavinganobject(something)thatisactuallynothing.We'lllearnmoreaboutobjectsinChapter4,Objects,butforthetimebeing,justrememberthatinJavaScript,thedatatypesareasfollows:
Primitive(thefivetypeslistedpreviously)Non-primitive(objects)
![Page 69: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/69.jpg)
Findingoutthevaluetype-thetypeofoperator
Ifyouwanttoknowthetypeofavariableoravalue,youcanusethespecialtypeofoperator.Thisoperatorreturnsastringthatrepresentsthedatatype.Thereturnvaluesofusingtypeofareoneofthefollowing:
numberstringbooleanundefinedobjectfunction
Inthenextfewsections,you'llseetypeofinactionusingexamplesofeachofthefiveprimitivedatatypes.
![Page 70: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/70.jpg)
Numbers
Thesimplestnumberisaninteger.Ifyouassign1toavariable,andthenusethetypeofoperator,itreturnsthestringnumber,asfollows:
>varn=1;>typeofn;"number">n=1234;>typeofn;"number"
Intheprecedingexample,youcanseethatthesecondtimeyousetavariable'svalue,youdon'tneedthevarstatement.
Numberscanalsobefloatingpoint(decimals),forexample:
>varn2=1.23;>typeofn;"number"
Youcancalltypeofdirectlyonthevaluewithoutassigningittoavariablefirst,forexample:
>typeof123;"number"
Octalandhexadecimalnumbers
Whenanumberstartswitha0,it'sconsideredan octalnumber.Forexample,theoctal0377isthedecimal255:
>varn3=0377;>typeofn3;"number">n3;255
Thelastlineintheprecedingexampleprintsthedecimalrepresentationoftheoctalvalue.
ES6providesaprefix0o(or0O,butthislooksveryconfusinginmostmonospacefonts)torepresentoctals.Considerthefollowinglineofcodeforexample:
console.log(0o776);//510
Whileyoumaynotbeintimatelyfamiliarwithoctalnumbers,you'veprobablyusedhexadecimalvaluestodefinecolorsinCSSstylesheets.
InCSS,youhaveseveraloptionstodefineacolor,twoofthemareasfollows:
![Page 71: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/71.jpg)
UsingdecimalvaluestospecifytheamountofR(red),G(green),andB(blue),rangingfrom0to255.Forexample,rgb(0,0,0)isblackandrgb(255,0,0)isred (maximumamountofredandnogreenor blue).UsinghexadecimalsandspecifyingtwocharactersforeachR,G,andBvalue.Forexample,#000000isblackand#ff0000isred.Thisisbecauseffisthehexadecimalvaluefor255.
InJavaScript,youcanput0xbeforeahexadecimalvalue,alsocalledhex forshort,forexample:
>varn4=0x00;>typeofn4;"number">n4;0>varn5=0xff;>typeofn5;"number">n5;255
BinaryLiterals
UntillES6,ifyouneededbinaryrepresentationofaninteger,youhadtopassthemtotheparseInt()functionasastringwitharadixof2,asfollows:
console.log(parseInt('111',2));//7
InES6youcanuse0b(or0B)prefixtorepresentbinaryintegers.Forexample:
console.log(0b111);//7
Exponentliterals
1e1(alsowrittenas1e+1or1E1or1E+1)representsthenumber1witha0afterit,orinotherwords,10.Similarly,2e+3representsthenumber2withthree0safterit,or2000,forexample:
>1e1;10>1e+1;
10>2e+3;2000>typeof2e+3;"number"
2e+3meansmovingthedecimalpointthreedigitstotherightofthenumber2.There'salso2e-3,meaningyoumovethedecimalpointthreedigitstotheleftofthenumber2.Lookatthefollowingfigure:
![Page 72: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/72.jpg)
Thefollowingisthecode:
>2e-3;0.002>123.456E-3;0.123456>typeof2e-3;"number"
Infinity
ThereisaspecialvalueinJavaScriptcalledInfinity.ItrepresentsanumbertoobigforJavaScripttohandle.Infinityisindeedanumber,astypingtypeofInfinityintheconsolewillconfirm.Youcanalsoquicklycheckthatanumberwith308zerosisok,but309zerosistoomuch.Tobeprecise,thebiggestnumberJavaScriptcanhandleis1.7976931348623157e+308,whilethesmallestis5e-324,Lookatthefollowingexample:
> Infinity;Infinity>typeofInfinity;"number">1e309;Infinity>1e308;1e+308
Dividingbyzerogivesyouinfinity,forexample:
>vara=6/0;>a;
Infinity
Infinityisthebiggestnumber(orratheralittlebiggerthanthebiggest),buthowaboutthe
![Page 73: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/73.jpg)
smallest?It'sinfinitywithaminussigninfrontofit;-Infinity,forexample:
>vari=-Infinity;>i;-Infinity>typeofi;"number"
Doesthismeanyoucanhavesomethingthat'sexactlytwiceasbigasInfinity,from0uptoinfinityandthenfrom0downtominusinfinity?Well,notreally.WhenyousumInfinityand-Infinity,youdon'tget0,butsomethingthatiscalledNotaNumber(NaN),Forexample:
>Infinity-Infinity;NaN>-Infinity+Infinity;NaN
AnyotherarithmeticoperationwithInfinityasoneoftheoperandsgivesyouInfinity,forexample:
>Infinity-20;Infinity>-Infinity*3;-Infinity>Infinity/2;Infinity>Infinity-99999999999999999;Infinity
Thereisalesserknownglobalmethod,isFinite(),thattellsyouifthevalueisinfinityornot.ES6addsaNumber.isFinite()methodtodojustthat.Whyanothermethod,youmayask.TheglobalvariantofisFinite()triestocastthevaluethroughNumber(value),whileNumber.isFinite()doesn't,henceit'smoreaccurate.
NaN
WhatwasthisNaNinthepreviousexample?Itturnsoutthatdespiteitsname,NotaNumber,NaNisaspecialvaluethatisalsoanumber:
>typeofNaN;"number">vara=NaN;>a;NaN
YougetNaNwhenyoutrytoperformanoperationthatassumesnumbers,buttheoperationfails.Forexample,ifyoutrytomultiply10bythecharacter"f",theresultisNaN,because"f"isobviouslynotavalidoperandforamultiplication:
![Page 74: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/74.jpg)
>vara=10*"f";>a;NaN
NaNiscontagious,soifyouhaveevenoneNaNinyourarithmeticoperation,thewholeresultgoesdownthedrain,forexample:
>1+2+NaN;NaN
Number.isNaN
ES5hasaglobalmethod-isNaN().ItdeterminesifavalueisNaNornot.ES6providesaverysimilarmethod-Number.isNaN()(Noticethatthismethodisnotglobal).
ThedifferencebetweentheglobalisNaN()andNumber.isNaN()isthatglobalisNaN()castsnon-numericvaluesbeforeevaluatingthemtobeNaN.Let'slookatthefollowingexample.WeareusingtheES6Number.isNaN()methodtotestifsomethingisaNaNornot:
console.log(Number.isNaN('test'));//false:StringsarenotNaNconsole.log(Number.isNaN(123));//false:integersarenotNaNconsole.log(Number.isNaN(NaN));//true:NaNsareNaNsconsole.log(Number.isNaN(123/'abc'));//true:123/'abc'resultsinan
NaN
WesawthatES5'sglobalisNaN()methodfirstcastsnon-numericvaluesandthendoesthecomparison;thefollowingresultwillbedifferentfromitsES6counterpart:
console.log(isNaN('test'));//true
Ingeneral,comparedtoitsglobalvariant,Number.isNaN()ismorecorrect.However,neitherofthemcanbeusedtofigureoutifsomethingisnotanumber-theyjustanswerifthevalueisaNaNornot.Practically,youareinterestedinknowingifavalueidentifiesasanumberornot.Mozillasuggeststhefollowingpolyfillmethodtodojustthat:
functionisNumber(value){returntypeofvalue==='number'&&!Number.isNaN(value);}
Number.isInteger
ThisisanewmethodinES6.Itreturnstrueifthenumberisfiniteanddoesnotcontainanydecimalpoints(isaninteger):
console.log(Number.isInteger('test'));//falseconsole.log(Number.isInteger(Infinity));//falseconsole.log(Number.isInteger(NaN));//falseconsole.log(Number.isInteger(123));//trueconsole.log(Number.isInteger(1.23));//false
![Page 75: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/75.jpg)
Strings
Astringisasequenceof charactersusedtorepresenttext.InJavaScript,anyvalueplacedbetweensingleordoublequotesisconsideredastring.Thismeansthat1isanumber,but"1"isastring.Whenusedwithstrings,typeofreturnsthestring"string",forexample:
> var s = "some characters";>typeofs;"string">vars='somecharactersandnumbers1235.87';>typeofs;"string"
Here'sanexampleofanumberusedinthestringcontext:
>vars='1';>typeofs;"string"
Ifyouputnothinginquotes,it'sstillastring(anemptystring),forexample:
>vars="";typeofs;"string"
Asyoualreadyknow,whenyouusetheplussignwithtwonumbers,thisisthearithmeticadditionoperation.However,ifyouusetheplussignwithstrings,thisisastringconcatenationoperation,anditreturnsthetwostringsgluedtogether:
>vars1="web";>vars2="site";
> var s = s1 + s2;>s;"website">typeofs;"string"
Thedualpurposeofthe+operatorisasourceoferrors.Therefore,ifyouintendtoconcatenatestrings,it'salwaysbesttomakesurethatalloftheoperandsarestrings.Thesameappliesforaddition;ifyouintendto addnumbersthenmakesuretheoperandsarenumbers.You'lllearnvariouswaystodosofurtherinthechapterandthebook.
Stringconversions
When you use a number-like string, for example, "1", as an operand in an arithmetic operation,the string is converted to a number behind the scenes. This works for all arithmetic operationsexceptaddition,becauseofitsambiguity.Considerthefollowingexample:
>vars='1';>s=3*s;
![Page 76: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/76.jpg)
>typeofs;"number">s;3>vars='1';>s++;>typeofs;"number">s;2
Alazywaytoconvertanynumber-likestringtoanumberistomultiplyitby1(anotherwayistouseafunctioncalledparseInt(),asyou'llseeinthenextchapter):
>vars="100";typeofs;"string">s=s*1;100>typeofs;"number"
Iftheconversionfails,you'llgetNaN:
>varmovie='101dalmatians';>movie*1;NaN
Youcanconvertastringtoanumberbymultiplyingitby1.Theopposite-convertinganythingtoastring-canbedonebyconcatenatingitwithanemptystring,asfollows:
>varn=1;>typeofn;"number">n=""+n;"1">typeofn;"string"
Specialstrings
Therearealsostringswithspecialmeanings,aslistedinthefollowingtable:
String Meaning Example
\\
'
"
The\istheescapecharacter.Whenyouwanttohavequotesinsideyourstring,youcanescapethemsothatJavaScriptdoesn'tthinktheymeantheendofthestring.
Ifyouwanttohaveanactualbackslashinthestring,escapeit
>vars='Idon'tknow';:ThisisanerrorbecauseJavaScriptthinksthestringisIdonandtherestisinvalidcode.Thefollowingcodesarevalid:
> var s = 'I don't know';>vars="Idon'tknow";>vars="Idon'tknow";>vars='"Hello",hesaid.';>vars=""Hello",hesaid.";
![Page 77: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/77.jpg)
withanotherbackslash. Escapingtheescape:>vars="1\\2";s;"1\2"
\n Endofline.
>vars='\n1\n2\n3\n';>s;"123"
\r Carriagereturn.
Consider the following statements:
>vars='1\r2';>vars='1\n\r2';>vars='1\r\n2';
Theresultofalloftheseisasfollows:
>s;"12"
\t Tab.>vars="1\t2";>s;"12"
\uThe\ufollowedbyacharactercodeallowsyoutouseUnicode.
Here'smynameinBulgarianwrittenwithCyrilliccharacters:
>"\u0421\u0442\u043E\u044F\u043D";"Стoян"
Therearealsoadditionalcharactersthatarerarelyused:\b(backspace),\v(verticaltab),and\f(formfeed).
Stringtemplateliterals
ES6introducedtemplateliterals.Ifyouarefamiliarwithotherprogramminglanguages,PerlandPythonhavesupportedtemplateliteralsforawhilenow.Templateliteralsallowexpressionstobeembeddedwithinregularstrings.ES6hastwokindsofliterals:templateliteralsandtaggedliterals.
Templateliteralsaresingleormultiplelinestringswithembeddedexpressions.Forexample,youmusthavedonesomethingsimilartothis:
varlog_level="debug";varlog_message="meltdown";console.log("Loglevel:"+log_level+"-message:"+log_message);//Loglevel:debug-message:meltdown
![Page 78: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/78.jpg)
Youcanaccomplishthesameusingtemplateliterals,asfollows:
console.log(`Loglevel:${log_level}-message:${log_message}`)
Templateliteralsareenclosedbytheback-tick(``)(graveaccent)characterinsteadoftheusualdoubleorsinglequotes.Templateliteralplaceholdersareindicatedbythedollarsignandcurlybraces(${expression}).Bydefault,theyareconcatenatedtoformasinglestring.Thefollowingexampleshowsatemplateliteralwithaslightlycomplexexpression:
vara=10;varb=10;console.log(`Sumis${a+b}andMultiplicationwouldbe${a*b}.`);//Sumis20andMultiplicationwouldbe100.
Howaboutembeddingafunctioncall?
vara=10;varb=10;functionsum(x,y){returnx+y}
function multi(x,y){returnx*y}console.log(`Sumis${sum(a,b)}andMultiplicationwouldbe${multi(a,b)}.`);
Templateliteralsalsosimplifymultilinestringsyntax.Insteadofwritingthefollowinglineofcode:
console.log("Thisislineone\n"+"andthisislinetwo");
Youcanhaveamuchcleanersyntaxusingtemplateliterals,whichisasfollows:
console.log(`Thisislineoneandthisislinetwo`);
ES6hasanotherinterestingliteraltypecalledTaggedTemplateLiterals.Taggedtemplatesallowyoutomodifytheoutputoftemplateliteralsusingafunction.Ifyouprefixanexpressiontoatemplateliteral,thatprefixisconsideredtobeafunctiontobeinvoked.Thefunctionneedstobe defined before we can use the tagged template literal. For example, the following expression:
transform`Nameis${lastname},${firstname}${lastname}`
Theprecedingexpressionisconvertedintoafunctioncall:
transform([["Nameis",",",""],firstname,lastname)
Thetagfunction,'transform',getstwoparameters-templatestringslikeNameisandsubstitutionsdefinedby${}.Thesubstitutionsareonlyknownatruntime.Let'sexpandthetransform
![Page 79: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/79.jpg)
function:
functiontransform(strings,...substitutes){console.log(strings[0]);//"Nameis"console.log(substitutes[0]);//Bond}varfirstname="James";varlastname="Bond"transform`Nameis${lastname},${firstname}${lastname}`
When template strings (Name is) are passed to the tag function, there are two forms of eachtemplate string, as follows:
TherawformwherethebackslashesarenotinterpretedThecookedformwherethebackslasheshas specialmeaning
Youcanaccesstherawstringformusingrawproperty,asthefollowingexampleshows:
functionrawTag(strings,...substitutes){console.log(strings.raw[0])}rawTag`Thisisarawtextand\narenottreateddifferently`//Thisisarawtextand\narenottreateddifferently
![Page 80: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/80.jpg)
Booleans
ThereareonlytwovaluesthatbelongtotheBooleandatatype-thetrueandfalsevaluesusedwithoutquotes:
> var b = true;>typeofb;"boolean">varb=false;>typeofb;"boolean"
Ifyouquotetrueorfalse,theybecomestrings,asshowninthefollowingexample:
> var b = "true";>typeofb;"string"
Logical operators
Therearethreeoperators,calledlogicaloperators,thatworkwithBooleanvalues.Theseareasfollows:
!-logicalNOT(negation)&&-logicalAND||-logicalOR
Youknowthatwhensomethingisnottrue,itmustbefalse.Here'showthisisexpressedusingJavaScriptandthelogical!operator:
>varb=!true;>b;false
IfyouusethelogicalNOTtwice,youwillgettheoriginalvalue,whichisasfollows:
>varb=!!true;>b;true
Ifyouusealogicaloperatoronanon-Booleanvalue,thevalueisconvertedtoBooleanbehindthescenes,asfollows:
>varb="one";>!b;false
Intheprecedingcase,thestringvalue"one"isconvertedtoaBoolean,true,andthennegated.Theresultofnegatingtrueisfalse.Inthefollowingexample,there'sadoublenegation,sothe
![Page 81: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/81.jpg)
resultistrue:
>varb="one";>!!b;true
You can convert any value to its Boolean equivalent using a double negation. Understanding howanyvalueconvertstoaBooleanisimportant.Mostvaluesconverttotruewiththeexceptionofthefollowing,whichconverttofalse:
Theemptystring""nullundefinedThenumber0ThenumberNaNTheBooleanfalse
Thesesixvaluesarereferredtoasfalsy,whileallothersaretruthy,(including,forexample,thestrings"0","",and"false").
Let'sseesomeexamples oftheothertwooperators-thelogicalAND(&&)andthelogicalOR(||).Whenyouuse&&,theresultistrueonlyifalloftheoperandsaretrue.Whenyouuse||,theresultistrueifatleastoneoftheoperandsistrue:
>varb1=true,b2=false;> b1 || b2;
true>b1&&b2;false
Here'salistofthepossibleoperationsandtheirresults:
Operation Result
true&&true true
true&&false false
false&&true false
false&&false false
true||true true
true||false true
![Page 82: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/82.jpg)
false||true true
false||false false
Youcanuseseverallogicaloperationsoneaftertheother,asfollows:
>true&&true&&false&&true;false>false||true||false;true
Youcanalsomix&&and ||inthesameexpression.Insuchcases,youshoulduseparenthesestoclarifyhowyouintendtheoperationtowork.Considerthefollowingexample:
>false&&false||true&&true;true>false&&(false||true)&&true;false
Operatorprecedence
Youmightwonderwhythepreviousexpression(false&&false||true&&true)returnedtrue.Theanswerliesintheoperatorprecedence,asyouknowfrommathematics:
>1+2*3;7
Thisisbecausemultiplicationhasahigherprecedenceoveraddition,so2*3isevaluatedfirst,asifyoutyped:
>1+(2*3);7
Similarlyforlogicaloperations,!hasthehighestprecedenceandisexecutedfirst,assumingtherearenoparenthesesthatdemandotherwise.Then,intheorderofprecedence,comes&&andfinally,||.Inotherwords,thefollowingtwocodesnippetsarethesame.Thefirstoneisasfollows:
>false&&false||true&&true;true
Andthesecondoneisasfollows:
>(false&&false)||(true&&true);true
Note
Bestpractice
![Page 83: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/83.jpg)
Useparenthesesinsteadofrelyingonoperatorprecedence.Thismakesyourcodeeasiertoreadandunderstand.
The ECMAScript standard defines the precedence of operators. While it may be a goodmemorizationexercise,thisbookdoesn'tofferit.Firstofall,you'llforgetit,andsecond,evenifyoumanagetorememberit,youshouldn'trelyonit.Thepersonreadingandmaintainingyourcodewilllikelybeconfused.
Lazyevaluation
Ifyouhaveseverallogicaloperationsoneaftertheother,buttheresultbecomesclearatsomepointbeforetheend,thefinaloperationswillnot beperformedbecausetheydon'taffecttheendresult.Considerthefollowinglineofcodeasanexample:
>true||false||true||false||true;true
AstheseareallORoperationsandhavethesameprecedence,theresultwillbetrueifatleast,oneoftheoperandsistrue.Afterthefirstoperandisevaluated,itbecomesclearthattheresultwillbetrue,nomatterwhatvaluesfollow.So,theJavaScriptenginedecidestobelazy(OK,efficient)andavoidsunnecessaryworkbyevaluatingcodethatdoesn'taffecttheendresult.Youcanverifythisshort-circuitingbehaviorbyexperimentingintheconsole,asshowninthefollowingcodeblock:
>varb=5;> true || (b = 6);
true>b;5>true&&(b=6);6>b;6
Thisexamplealsoshowsanotherinterestingbehavior-ifJavaScriptencountersanon-Booleanexpressionasanoperandinalogicaloperation,thenon-Booleanisreturnedasaresult:
>true||"something";true>true&&"something";"something">true&&"something"&&true;true
Thisbehaviorisnotsomethingyoushouldrelyonbecauseitmakesthecodehardertounderstand.It's common to use this behavior to define variables when you're not sure whether they werepreviouslydefined.Inthenextexample,ifthemynumbervariableisdefined,itsvalueiskept;otherwise,it'sinitializedwiththevalue10:
![Page 84: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/84.jpg)
>varmynumber=mynumber||10;>mynumber;10
Thisissimpleandlooks elegant,butbeawarethatit'snotcompletelyfoolproof.Ifmynumberisdefinedandinitializedto0,ortoanyofthesixfalsyvalues,thiscodemightnotbehaveasyouexpect,asshowninthefollowingpieceofcode:
>varmynumber=0;>varmynumber=mynumber||10;>mynumber;
10
Comparison
There'sanothersetofoperatorsthatallreturnaBooleanvalueasaresultoftheoperation.Thesearethecomparisonoperators.Thefollowingtableliststhemtogetherwithexampleuses:
Operatorsymbol
Description Example
==Equalitycomparison:Thisreturnstruewhenbothoperandsareequal.Theoperandsareconvertedtothesametypebeforebeingcompared.They'realsocalledloosecomparison.
>1==1;true>1==2;false>1=='1';true
===Equalityandtype comparison:Thisreturnstrueifbothoperandsareequalandofthesametype.It'sbetterandsafertocomparethiswaybecausethere'snobehind-the-scenestypeconversions.Itisalsocalledstrictcomparison.
>1==='1';false>1===1;true
!=Non-equalitycomparison:Thisreturnstrueiftheoperandsarenotequaltoeachother(afteratypeconversion).
> 1 !=1;false>1!='1';false>1!='2';true
!==Non-equalitycomparisonwithouttype conversion:Returnstrueiftheoperandsarenotequaloriftheyareofdifferenttypes.
>1!==1;false>1!=='1';true
>1>1;
![Page 85: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/85.jpg)
> Thisreturnstrueiftheleftoperandisgreaterthantherightone.
false>33>22;true
>= Thisreturnstrueiftheleftoperandisgreaterthanorequaltotherightone.>1>=1;true
< Thisreturnstrueiftheleftoperandislessthantherightone.
>1<1;false>1<2;true
<= Thisreturnstrueiftheleftoperandislessthanorequaltotherightone.
>1<=1;true>1<=2;true
NotethatNaNisnotequaltoanything,notevenitself.Takealookatthefollowinglineofcode:
>NaN==NaN;false
![Page 86: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/86.jpg)
Undefinedandnull
Ifyoutrytouseanon-existingvariable,you'llgetthefollowingerror:
> foo;ReferenceError:fooisnotdefined
Usingthetypeofoperatoronanon-existingvariableisnotanerror.Youwillgetthe"undefined"stringback,asfollows:
>typeoffoo;"undefined"
Ifyoudeclareavariablewithoutgivingitavalue,thisis,ofcourse,notanerror.But,thetypeofstillreturns"undefined":
>varsomevar;>somevar;>typeofsomevar;"undefined"
This is because, when you declare a variable without initializing it, JavaScript automaticallyinitializesitwiththeundefinedvalue,asshowninthefollowinglinesofcode:
>varsomevar;>somevar===undefined;true
Thenullvalue,ontheotherhand,isnotassignedbyJavaScriptbehindthescenes;it'sassignedbyyourcode,whichisasfollows:
>varsomevar=null;null>somevar;null>typeofsomevar;"object"
Althoughthedifferencebetweennullandundefinedissmall,itcanbecriticalattimes.Forexample,ifyouattemptanarithmeticoperation,youwillgetdifferentresults:
> var i = 1 + undefined;>i;NaN>vari=1+null;>i;1
Thisisbecauseofthedifferentwaysnullandundefinedareconvertedtotheotherprimitive
![Page 87: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/87.jpg)
types.Thefollowingexamplesshowthepossibleconversions:
Conversiontoanumber:
> 1 * undefined;
ConversiontoNaN:
>1*null;0
ConversiontoaBoolean:
>!!undefined;false>!!null;false
Conversiontoastring:
>"value:"+null;"value:null">"value:"+undefined;"value:undefined"
![Page 88: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/88.jpg)
Symbols
ES6introducedanewprimitivetype-symbols.Severallanguageshaveasimilarnotion.Symbolslookverysimilartoregularstrings,buttheyareverydifferent.Let'sseehowthesesymbolsarecreated:
varatom=Symbol()
Noticethatwedon'tusenewoperatorwhilecreatingsymbols.Youwillgetanerrorwhenyoudouseit:
varatom=newSymbol()//Symbolisnotaconstructor
YoucandescribeSymbolaswell:
varatom=Symbol('atomicsymbol')
Describingsymbolscomesinveryhandywhiledebugginglargeprogramswheretherearelotsofsymbolsscatteredacross.
ThemostimportantpropertyofSymbol(andhencethereasonoftheirexistence)isthattheyareuniqueandimmutable:
console.log(Symbol()===Symbol())//falseconsole.log(Symbol('atom')===Symbol('atom'))//false
Fornow,wewillhavetopausethisdiscussiononsymbols.Symbolsareusedaspropertykeysandplaceswhereyouneeduniqueidentifiers.Wewilldiscusssymbolsinalaterpartofthisbook.
![Page 89: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/89.jpg)
Primitive data types recapLet's quickly summarize some of the main points discussed so far:
TherearefiveprimitivedatatypesinJavaScript:NumberStringBooleanUndefinedNull
Everythingthatisnotaprimitivedatatypeisanobject.
Theprimitivenumberdatatypecanstorepositiveandnegativeintegersorfloats,hexadecimalnumbers,octalnumbers,exponents,andthespecialnumbers-NaN,Infinity,and-Infinity.Thestringdatatypecontainscharactersinquotes.Templateliteralsallowembeddingofexpressionsinsideastring.TheonlyvaluesoftheBooleandatatypearetrueandfalse.Theonlyvalueofthenulldatatypeisthenullvalue.Theonlyvalueoftheundefineddatatypeistheundefinedvalue.AllvaluesbecometruewhenconvertedtoaBoolean,withtheexceptionofthefollowingsixfalsyvalues:
""
null
undefined
0
NaN
false
![Page 90: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/90.jpg)
ArraysNow that you know about the basic primitive data types in JavaScript, it's time to move to a morepowerfuldatastructure-thearray.
So,whatisanarray?It'ssimplyalist(asequence)ofvalues.Insteadofusingonevariabletostoreonevalue,youcanuseonearrayvariabletostoreanynumberofvaluesaselementsofthearray.
Todeclareavariablethatcontainsanemptyarray,youcanusesquarebracketswithnothingbetweenthem,asshowninthefollowinglineofcode:
>vara=[];
Todefineanarraythathasthreeelements,youcanwritethefollowinglineofcode:
>vara=[1,2,3];
Whenyousimplytypethenameofthearrayintheconsole,youcangetthecontentsofyourarray:
>a;[1,2,3]
Nowthequestionishowtoaccessthevaluesstoredinthesearrayelements.Theelementscontainedinanarrayareindexedwithconsecutivenumbers,startingfromzero.Thefirstelementhasindex(orposition)0,thesecondhasindex1, andsoon.Here'sthethree-elementarrayfromthepreviousexample:
Index Value
0 1
1 2
2 3
Toaccessanarrayelement,youcanspecifytheindexofthatelementinsidesquarebrackets.So,a[0]givesyouthefirstelementofthearraya,a[1]givesyouthesecond,andsoon,asshowninthefollowingexample:
>a[0];1>a[1];2
![Page 91: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/91.jpg)
Adding/updatingarrayelements
Usingtheindex,youcanalsoupdatethevaluesoftheelementsofthearray.Thenextexampleupdatesthethirdelement(index2)andprintsthecontentsofthenewarray,asfollows:
>a[2]='three';"three">a;[1,2,"three"]
Youcanaddmoreelementsbyaddressinganindexthatdidn'texistbefore,asshowninthefollowing lines of code:
>a[3]='four';"four">a;[1,2,"three","four"]
Ifyouaddanewelementbutleaveagapinthearray,thoseelementsinbetweendon'texistandreturntheundefinedvalueifaccessed.Checkoutthefollowingexample:
>vara=[1,2,3];>a[6]='n`xew';"new">a;[1,2,3,undefinedx3,"new"]
![Page 92: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/92.jpg)
Deletingelements
Todeleteanelement,youcanusethedeleteoperator.However,afterthedeletion,thelengthofthearraydoesnotchange.Inasense,youmaygetaholeinthearray:
> var a = [1, 2, 3];>deletea[1];true>a;[1,undefined,3]>typeofa[1];"undefined"
![Page 93: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/93.jpg)
Arraysofarrays
Arrayscancontainalltypesofvalues,includingotherarrays:
> var a = [1, "two", false, null, undefined];>a;[1,"two",false,null,undefined]>a[5]=[1,2,3];[1,2,3]>a;[1,"two",false,null,undefined,Array[3]]
TheArray[3]intheresultisclickableintheconsoleanditexpandsthearrayvalues.Let'slookatanexamplewhereyouhaveanarrayoftwoelements,bothofthembeingotherarrays:
>vara=[[1,2,3],[4,5,6]];>a;[Array[3],Array[3]]
Thefirstelementofthearrayis[0],andit'salso anarray:
>a[0];[1,2,3]
To access an element in the nested array, you can refer to the element index in another set ofsquarebrackets,asfollows:
>a[0][0];1>a[1][2];6
Notethatyoucanusethearraynotationtoaccess individualcharactersinsideastring,asshowninthefollowingcodeblock:
>vars='one';>s[0];"o"
> s[1];"n">s[2];"e"
Note
Arrayaccesstostringswassupportedbymanybrowsersforawhile(notolderIEs),butitwasofficiallyrecognizedonlyaslateasECMAScript5.
Therearemorewaystohavefunwitharrays(andwegettothoseinChapter4,Objects),butlet'sstopherefornow,rememberingthefollowingpoints:
![Page 94: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/94.jpg)
AnarrayisadatastoreAnarraycontainsindexedelementsIndexesstartfromzeroandincrementbyoneforeachelementinthearrayToaccessanelementofanarray,youcanuseitsindexinsquarebracketsAnarraycancontainanytypeofdata,includingotherarrays
![Page 95: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/95.jpg)
Conditions and loopsConditions provide a simple but powerful way to control the flow of code execution. Loopsallowyoutoperformrepetitiveoperationswithlesscode.Let'stakealookat:
ifconditionsswitchstatementswhile,do...while,for,andfor...inloops
Note
TheexamplesinthefollowingsectionsrequireyoutoswitchtothemultilineFirebugconsole.Or,ifyouusetheWebKitconsole,pressShift+EnterinsteadofEntertoaddanewline.
![Page 96: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/96.jpg)
Codeblocks
Intheprecedingexamples,yousawtheuseofcodeblocks.Let'stakeamomenttoclarifywhatablockofcodeis,becauseyouwilluseblocksextensivelywhenconstructingconditionsandloops.
Ablockofcodeconsistsofzeroormoreexpressionsenclosedincurlybrackets,whichisshowninthefollowinglinesofcode:
{vara=1;varb=3;}
Youcannestblockswithineachotherindefinitely,asshowninthefollowingexample:
{vara=1;varb=3;varc,d;{c=a+b;{d=a-b;}}}
Note
Bestpracticetips
Useend-of-linesemicolons,asdiscussedpreviouslyinthechapter.Althoughthesemicolonisoptionalwhenyouhaveonlyoneexpressionperline,it'sgoodtodevelopthehabitofusingthem.Forbestreadability,theindividualexpressionsinsideablockshouldbeplacedoneperlineandseparatedbysemicolons.
Indentanycodeplacedwithincurlybrackets.Someprogrammerslikeonetabindentation,someusefourspaces,andsomeusetwospaces.Itreallydoesn'tmatter,aslongasyou'reconsistent.Intheprecedingexample,theouterblockisindentedwithtwospaces,thecodeinthefirstnestedblockisindentedwithfourspaces,andtheinnermostblockisindentedwithsixspaces.
Use curly brackets. When a block consists of only one expression, the curly brackets are optional,butforreadabilityandmaintainability,youshouldgetintothehabitofalwaysusingthem,evenwhenthey'reoptional.
Theifcondition
![Page 97: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/97.jpg)
Here'sasimpleexampleofanifcondition:
varresult='',a=3;if(a>2){result='aisgreaterthan2';}
Thepartsoftheifconditionareasfollows:
TheifstatementAconditioninparentheses-isagreaterthan2?Ablockofcodewrappedin{}thatexecutesiftheconditionissatisfied
Thecondition(thepartinparentheses)alwaysreturnsaBooleanvalue,andmayalsocontainthefollowing:
Alogicaloperation-!,&&,or||Acomparison,suchas===,!=,>,andsoonAnyvalueorvariablethatcanbeconvertedtoaBooleanAcombinationoftheabove
Theelseclause
Therecanalsobeanoptionalelsepartoftheifcondition.Theelsestatementisfollowedbyablockofcodethatrunsiftheconditionevaluatestofalse:
if(a>2){result='aisgreaterthan2';}else{result='aisNOTgreaterthan2';}
Inbetweentheifandtheelsestatements,therecanalsobeanunlimitednumberofelse...ifconditions.Here'sanexample:
if(a>2||a<-2){result='aisnotbetween-2and2';}elseif(a===0&&b===0){result='bothaandbarezeros';}elseif(a===b){result='aandbareequal';}else{result='Igiveup';}
Youcanalsonestconditionsbyputtingnewconditionswithinanyoftheblocks,asshowninthefollowingpieceofcode:
if(a===1){if(b===2){
![Page 98: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/98.jpg)
result='ais1andbis2';}else{result='ais1butbisdefinitelynot2';}}else{result='aisnot1,noideaaboutb';}
Checkingifavariableexists
Let'sapplythenewknowledgeaboutconditionsforsomethingpractical.It'softennecessarytocheckwhetheravariableexists.Thelaziestwaytodothisistosimplyputthevariableintheconditionpartoftheifstatement,forexample,if(somevar){...}.But,thisisnotnecessarilythebestmethod.Let'stakealookatanexamplethattestswhetheravariablecalledsomevarexists,andifso,setstheresultvariabletoyes:
>varresult='';>if(somevar){result='yes';}ReferenceError:somevarisnotdefined>result;""
Thiscodeobviouslyworksbecausetheendresultwasnotyes.Butfirstly,thecodegeneratedanerror-somevarisnotdefined,andyoudon'twant yourcodetobehavelikethat.Secondly,justbecauseif(somevar)returnsfalse,itdoesn'tmeanthatsomevarisnotdefined.Itcouldbethatsomevarisdefinedandinitializedbutcontainsafalsyvaluelikefalseor0.
Abetterwaytocheckifavariableisdefinedistousetypeof:
>varresult="";>if(typeofsomevar!=="undefined"){result="yes";
}>result;""
Thetypeofoperatoralwaysreturnsastring,andyoucancomparethisstringwiththestring"undefined".Notethatthesomevarvariablemayhavebeendeclaredbutnotassignedavalueyetandyou'llstillgetthesameresult.So,whentestingwithtypeoflikethis,you'rereallytestingwhetherthevariablehas anyvalueotherthantheundefinedvalue:
>varsomevar;>if(typeofsomevar!=="undefined"){result="yes";
}>result;""
![Page 99: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/99.jpg)
>somevar=undefined;>if(typeofsomevar!=="undefined"){result="yes";}>result;""
Ifavariableisdefinedandinitializedwithanyvalueotherthanundefined,itstypereturnedbytypeofisnolonger"undefined",asshowninthefollowingpieceofcode:
>somevar=123;>if(typeofsomevar!=="undefined"){result='yes';}>result;"yes"
Alternativeifsyntax
Whenyouhaveasimplecondition,youcanconsiderusinganalternativeifsyntax.Takealookatthis:
vara=1;varresult='';
if (a === 1) {result="aisone";}else{result="aisnotone";}
Youcanalsowritethisas:
>vara=1;>varresult=(a===1)?"aisone":"aisnotone";
Youshouldonlyusethissyntaxforsimpleconditions.Becarefulnottoabuseit,asitcaneasilymakeyourcodeunreadable.Here'sanexample.
Let'ssayyouwanttomakesureanumberiswithinacertainrange,saybetween50and100:
>vara=123;>a=a>100?100:a<50?50:a;>a;100
Itmaynotbeclearhowthiscodeworksexactlybecauseofthemultiple?.Addingparenthesesmakesitalittleclearer,asshowninthefollowingcodeblock:
>vara=123;>a=(a>100?100:a<50)?50:a;>a;
![Page 100: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/100.jpg)
50>vara=123;>a=a>100?100:(a<50?50:a);>a;100
?:iscalledaternaryoperatorbecauseittakesthreeoperands.
Switch
Ifyoufindyourselfusinganifconditionandhavingtoomanyelse...ifparts,youcanconsiderchangingtheiftoaswitch,asfollows:
vara='1',result='';switch(a){case1:result='Number1';break;case'1':result='String1';break;default:result='Idon'tknow';break;}
Theresultafterexecutingthisis"String1".Let'sseewhatthepartsofaswitchare:
Theswitchstatement.Anexpressioninparentheses.Theexpressionmostoftencontainsavariable,butcanbeanythingthatreturnsavalue.Anumberofcaseblocksenclosedincurlybrackets.Eachcasestatementisfollowedbyanexpression.Theresultoftheexpressioniscomparedtotheexpressionfoundaftertheswitchstatement.Iftheresultofthecomparisonistrue,thecodethatfollowsthecolonafterthecaseisexecuted.Thereisanoptionalbreakstatementtosignaltheendofthecaseblock.Ifthisbreakstatementisreached,theswitchstatementisalldone.Otherwise,ifthebreakismissing,theprogramexecutionentersthenextcaseblock.There'sanoptionaldefaultcasemarkedwiththedefaultstatementandfollowedbyablockofcode.Thedefaultcaseisexecutedifnoneofthepreviouscasesevaluatedtotrue.
Inotherwords,thestep-by-stepproceduretoexecuteaswitchstatementisasfollows:
1. Evaluate the switch expression found in parentheses; remember it.2. Move to the first case and compare its value with the one fromStep 1.3. IfthecomparisoninStep2returnstrue,executethecodeinthecaseblock.4. Afterthecaseblockisexecuted,ifthere'sabreakstatementattheendofit,exitswitch.
![Page 101: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/101.jpg)
5. Ifthere'snobreakorStep2returnedfalse,moveontothenextcaseblock.6. Repeatsteps2to5.7. Ifyouarestillhere(noexitinStep4),executethecodefollowingthedefaultstatement.
Tip
Indentthecodethatfollowsthecaselines.Youcanalsoindentcasefromtheswitch,butthatdoesn'tgiveyoumuchin termsofreadability.
Don'tforgettobreak
Sometimes,youmaywanttoomitthebreakintentionally,butthat'srare.It'scalledafall-throughandshouldalwaysbedocumentedbecauseitmaylooklikeanaccidentalomission.Ontheotherhand,sometimesyoumaywanttoomitthewholecodeblockfollowingacaseandhavetwocasessharingthesamecode.Thisisfine,butitdoesn'tchangetherulethatifthere'scodethatfollowsacasestatement,thiscodeshouldendwithabreak.Intermsofindentation,aligningthebreakwiththecaseorwiththecodeinsidethecaseisapersonalpreference;again,beingconsistentiswhatmatters.
Usethedefaultcase.Thishelpsyoumakesurethatyoualwayshaveameaningfulresultaftertheswitchstatement,evenifnoneofthecasesmatchesthevaluebeingswitched.
![Page 102: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/102.jpg)
Loops
Theif...elseandswitchstatementsallowyourcodetotakedifferentpaths,asifyou'reatacrossroad,anddecidewhichwaytogodependingonacondition.Loops,ontheotherhand,allowyourcodetotakeafewroundaboutsbeforemergingbackintothemainroad.Howmanyrepetitions?Thatdependsontheresultofevaluatingaconditionbefore(orafter)eachiteration.
Let'ssayyouare(yourprogramexecutionis)travelingfromAtoB.Atsomepoint,youwillreachaplacewhereyouhavetoevaluateacondition,C.TheresultofevaluatingCtellsyouwhetheryoushouldgointoaloop,L.YoumakeoneiterationandarriveatCagain.Then,youevaluatetheconditiononceagaintoseeifanotheriterationisneeded.Eventually,youmoveonyourwaytoB:
Aninfiniteloopiswhentheconditionisalwaystrue,andyourcodegetsstuckintheloopforever.Thisis,ofcourse,alogicalerror,andyoushouldlookoutforsuchscenarios.
InJavaScript,thefollowingarethefourtypesofloops:
whileloopsdo-whileloopsforloopsfor-inloops
While loops
Thewhileloopsarethesimplesttypeofiteration.Theylooklikethefollowing:
vari=0;while(i<10){i++;
![Page 103: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/103.jpg)
}
Thewhilestatementisfollowedbyaconditioninparenthesesandacodeblockincurlybrackets.Aslongastheconditionevaluatestotrue,thecodeblockisexecutedoverandoveragain.
Do-whileloops
Thedo...whileloopsareaslightvariationofwhileloops.Anexampleisshownasfollows:
vari=0;do{
i++;}while(i<10);
Here,thedostatementisfollowedbyacodeblockandaconditionaftertheblock.Thismeansthatthecodeblockisalwaysexecuted,atleastonce,beforetheconditionisevaluated.
Ifyouinitializeito11insteadof0inthelasttwoexamples,thecodeblockinthefirstexample(thewhileloop)willnotbeexecuted,andiwillstillbe11attheend,whileinthesecond(thedo...whileloop),thecodeblockwillbeexecutedonceandiwillbecome12.
Forloops
Theforloopisthemostwidelyusedtypeofloop,andyoushouldmakesureyou'recomfortablewiththisone.Itrequiresjustalittlebitmoreintermsofsyntax:
InadditiontotheCconditionandtheLcodeblock,youhavethefollowing:
Initialization:Thisisthecodethatisexecutedbeforeyouevenentertheloop(markedwith0inthediagram)Increment:Thisisthecodethatisexecutedaftereveryiteration(markedwith++inthe
![Page 104: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/104.jpg)
diagram)
Thefollowingisthemostwidelyusedforlooppattern:
Intheinitializationpart,youcandefineavariable(orsettheinitialvalueofanexistingvariable),mostoftencallediIntheconditionpart,youcancompareitoaboundaryvalue,suchasi<100Intheincrementpart,youcanincreaseiby1,suchasi++
Here'sanexample:
varpunishment='';for(vari=0;i<100;i++){punishment+='Iwillneverdothisagain,';}
Allthreeparts(initialization,condition,andincrement)cancontainmultipleexpressionsseparatedbycommas.Sayyouwanttorewritetheexampleanddefinethevariablepunishmentinsidetheinitializationpartoftheloop:
for(vari=0,punishment='';i<100;i++){punishment+='Iwillneverdothisagain,';}
Canyoumovethebodyoftheloopinsidetheincrementpart?Yes,youcan,especiallyasit'saone-liner.Thisgivesyoualoopthatlooksalittleawkward,asithasnobody.Notethatthisisjustanintellectualexercise;it'snotrecommendedthatyouwriteawkward-lookingcode:
for(vari=0,punishment='';i<100;i++,punishment+='Iwillneverdothisagain,'){
//nothinghere
}
Thesethreepartsarealloptional.Here'sanotherwayofrewritingthesameexample:
vari=0,punishment='';for(;;){punishment+='Iwillneverdothisagain,';if(++i==100){break;}}
Althoughthelastrewriteworksexactlythesamewayastheoriginal,it'slongerandhardertoread.It'salsopossibletoachievethesameresult usingawhileloop.But,theforloopsmakethe
![Page 105: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/105.jpg)
codetighterandmorerobustbecausethemeresyntaxoftheforloopmakesyouthinkaboutthethreeparts(initialization,condition,andincrement),andthushelpsyoureconfirmyourlogicandavoidsituationssuchasbeingstuckinaninfiniteloop.
The for loops can be nested within each other. Here's an example of a loop that is nested insideanother loop and assembles a string containing ten rows and ten columns of asterisks. Think of ibeing the row and j being the column of an image:
varres='\n';for(vari=0;i<10;i++){for(varj=0;j<10;j++){res+='*';}res+='\n';}
Theresultisastring,asshownhere:
"****************************************************************************************************"
Here'sanotherexamplethatusesnestedloopsandamodulooperationtodrawasnowflake-likeresult:
varres='\n',i,j;for(i=1;i<=7;i++){for(j=1;j<=15;j++){res+=(i*j)%8?'':'*';}res+='\n';}
Theresultisasfollows:
"****************
![Page 106: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/106.jpg)
*"
For...inloops
Thefor...inloopisusedtoiterateovertheelementsofanarray,oranobject,asyou'llseelater.Thisisitsonlyuse;itcannotbeusedasageneral-purposerepetitionmechanismtoreplacefororwhile.Let'sseeanexampleofusingafor-intoloopthroughtheelementsofanarray.But,bearinmindthatthisisforinformationalpurposesonly,asfor...inismostlysuitableforobjectsandtheregularforloopshouldbeusedforarrays.
Inthisexample,youcaniterateoveralloftheelementsofanarrayandprintouttheindex(thekey)andthevalueofeachelement,forexample:
//exampleforinformationonly//for-inloopsareusedforobjects//regularforisbettersuitedforarrays
vara=['a','b','c','x','y','z'];
varresult='\n';
for(variina){result += 'index: ' + i + ', value: ' + a[i] + '\n';
}Theresultis:"index:0,value:aindex:1,value:bindex:2,value:cindex:3,value:xindex:4,value:yindex:5,value:z"
![Page 107: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/107.jpg)
CommentsOne last thing for this chapter-comments. Inside your JavaScript program, you can put comments.TheseareignoredbytheJavaScriptengineanddon'thaveanyeffectonhowtheprogramworks.Buttheycanbeinvaluablewhenyourevisityourcodeafterafewmonths,ortransferthecodetosomeoneelseformaintenance.
Thefollowingtwotypes ofcommentsareallowed:
Single line comments start with // and end at the end of the line.Multiline comments start with /* and end with */ on the same line or any subsequent line.Note that any code in between the comment start and the comment end is ignored.
Someexamplesareasfollows:
//beginningofline
vara=1;//anywhereontheline
/*multi-linecommentonasingleline*/
/*commentthatspansseverallines*/
There are even utilities, such as JSDoc and YUIDoc, that can parse your code and extractmeaningfuldocumentationbasedonyourcomments.
![Page 108: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/108.jpg)
Exercises1. Whatistheresultofexecutingeachoftheselinesintheconsole?Why?
>vara;typeofa;>vars='1s';s++;>!!"false";>!!undefined;
> typeof -Infinity;>10%"0";>undefined==null;>false==="";>typeof"2E+2";>a=3e+3;a++;
2. Whatisthevalueofvafterthefollowing?
>varv=v||10;
Experimentbyfirstsettingvto100,0,ornull.3. Writeasmallprogramthatprintsoutthemultiplicationtable.Hint:usealoopnestedinsideanotherloop.
![Page 109: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/109.jpg)
SummaryIn this chapter, you learned a lot about the basic building blocks of a JavaScript program. Nowyouknowthefollowingprimitivedatatypes:
NumberStringBooleanUndefinedNull
Youalsoknowquiteafewoperators,whichareasfollows:
Arithmeticoperators:+,-,*,/,and%Incrementoperators:++and-Assignmentoperators:=,+=,-=,*=,/=,and%=Specialoperators:typeofanddeleteLogicaloperators:&&,||,and!Comparisonoperators:==,===,!=,!==,<,>,>=,and<=Theternaryoperator:?
Thenyoulearnedhowtousearraystostoreandaccessdata,andfinallyyousawdifferentwaystocontroltheflowofyourprogramusingconditions(if...elseorswitch)andloops(while,do...while,for,andfor...in).
Thisisquiteabitofinformation;giveyourselfawell-deservedpatonthebackbeforedivingintothenextchapter.Morefuniscomingup!
![Page 110: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/110.jpg)
Chapter 3. FunctionsMastering functions is an important skill when you learn any programming language, and evenmoresowhenitcomestoJavaScript.ThisisbecauseJavaScripthasmanyusesforfunctions,andmuchofthelanguage'sflexibilityandexpressivenesscomesfromthem.Wheremostprogramminglanguageshaveaspecialsyntaxforsomeobject-orientedfeatures,JavaScriptjustusesfunctions.Thischapterwillcoverthefollowingtopics:
HowtodefineanduseafunctionPassingargumentstoafunctionPredefinedfunctionsthatareavailabletoyouforfreeThescopeofvariablesinJavaScriptTheconceptthatfunctionsarejustdata,albeitaspecialtypeofdata
Understandingthesetopicswillprovideasolidbasethatwillallowyoutodiveintothesecondpartofthechapter,whichshowssomeinterestingapplicationsoffunctions,asfollows:
UsinganonymousfunctionsCallbacksImmediate(self-invoking)functionsInner functions (functions defined inside other functions)FunctionsthatreturnfunctionsFunctionsthatredefinethemselvesClosures
![Page 111: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/111.jpg)
What is a function?Functions allow you to group together a code, give it a name, and reuse it later, addressing it bythenameyougaveit.Let'sconsiderthefollowingcodeasanexample:
functionsum(a,b){varc=a+b;returnc;}
Thepartsthatmakeupafunctionareshownasfollows:
Thefunctionkeyword.Thenameofthefunction;inthiscase,sum.Thefunctionparameters;inthiscase,aandb.Afunctioncantakeanynumberofparameters,ornoparameters,separatedbycommas.Acodeblock,alsocalledthebodyofthefunction.Thereturnstatement.Afunctionalwaysreturnsavalue.Ifitdoesn'treturnavalueexplicitly,itimplicitlyreturnsthevalueundefined.
Notethatafunctioncanonlyreturnasinglevalue.Ifyouneedtoreturnmorevalues,youcansimplyreturnanarraythatcontainsallofthevaluesyouneedaselementsofthisarray.
Theprecedingsyntaxiscalledafunctiondeclaration.It'sjustoneofthewaystocreateafunctioninJavaScript,andmorewaysarecomingup.
![Page 112: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/112.jpg)
Callingafunction
Inordertomakeuseofafunction,youwillneedtocallit.Youcancallafunctionsimplyusingitsname,optionally,followedbyanynumberofvaluesinparentheses.Toinvokeafunctionisanotherwayofsayingtocall.
Let'scallthesum()function,passingtwoargumentsandassigningthevaluethatthefunctionreturnstothevariableresult:
>varresult=sum(1,2);>result;3
![Page 113: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/113.jpg)
Parameters
Whendefiningafunction,youcanspecifywhatparametersthefunctionexpectstoreceivewhenit'scalled.Afunctionmaynotrequireanyparameters,butifitdoes,andyouforgettopassthem,JavaScriptwillassigntheundefinedvaluetotheonesyouskipped.Inthenextexample,thefunctioncallreturnsNaNbecauseittriestosum1andundefined:
>sum(1);NaN
Technicallyspeaking,thereisadifferencebetweenparametersandarguments,althoughthetwoareoftenusedinterchangeably.Parametersaredefinedtogetherwiththefunction,whileargumentsarepassedtothefunctionwhenit'scalled.Considerthefollowingexample:
>functionsum(a,b){returna+b;}>sum(1,2);
Here,aandbareparameters,while1and2arearguments.
JavaScriptisnotpickyatallwhenitcomestoacceptingarguments.Ifyoupassmorethanthefunctionexpects,theextraoneswillbesilentlyignored,asshowninthefollowingexample:
> sum(1, 2, 3, 4, 5);3
What'smore,youcancreatefunctionsthatareflexibleaboutthenumberofparameterstheyaccept.Thisispossiblethankstothespecialvalueargumentsthatarecreatedautomaticallyinsideeachfunction.Here'safunctionthatsimplyreturnswhateverargumentsarepassedtoit:
>functionargs(){returnarguments;}>args();[]>args(1,2,3,4,true,'ninja');[1,2,3,4,true,"ninja"]
Usingarguments,youcanimprovethesum()functiontoacceptanynumberofargumentsandaddthemallup,asshowninthefollowingexample:
functionsumOnSteroids(){vari,res=0,number_of_params=arguments.length;for(i=0;i<number_of_params;i++){res+=arguments[i];}
![Page 114: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/114.jpg)
returnres;}
Ifyoutestthisfunctionbycallingitwithadifferentnumberofarguments,orevennoneatall,youcanverifythatitworksasexpected,asyoucanseeinthefollowingexample:
>sumOnSteroids(1,1,1);3>sumOnSteroids(1,2,3,4);10>sumOnSteroids(1,2,3,4,4,3,2,1);20>sumOnSteroids(5);5
> sumOnSteroids();0
Thearguments.lengthexpressionreturnsthenumberofargumentspassedwhenthefunctionwascalled.Don'tworryifthesyntaxisunfamiliar,we'llexamineitindetailinthenextchapter.You'llalsoseethatargumentsisnotanarray(althoughitsurelookslikeone),butanarray-likeobject.
ES6introducesseveralimportantimprovementsaroundfunctionparameters.ES6functionparameterscannowhavedefaultvalues,restparameters,andallowsdestructuring.Thenextsectiondiscusseseachoftheseconceptsindetail.
![Page 115: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/115.jpg)
Default parametersFunction parameters can be assigned default values. While calling the function, if a parameter isomitted,thedefaultvalueassignedtotheparameterisused:
functionrender(fog_level=0,spark_level=100){console.log(`FogLevel:${fog_level}andspark_level:${spark_level}`)}render(10);//FogLevel:10andspark_level:100
Inthisexample,weareomittingthespark_levelparameter,andhencethedefaultvalueassignedtotheparameterisused.Itisimportanttonotethatundefinedisconsideredasanabsenceofparametervalue;considerthefollowinglineofcode,forexample:
render(undefined,10);//FogLevel:0andspark_level:10
Whileprovidingdefaultvaluesofparameters,itispossibletorefertootherparametersaswell:
functiont(fog_level=1,spark_level=fog_level){console.log(`FogLevel:${fog_level}andspark_level:${spark_level}`)//FogLevel:10andspark_level:10}functions(fog_level=10,spark_level=fog_level*10){console.log(`FogLevel:${fog_level}andspark_level:
${spark_level}`)//FogLevel:10andspark_level:100}t(10);s(10);
Defaultparametershavetheirownscope;thisscopeissandwichedbetweentheouterfunctionscopeandtheinnerscopeofthefunction.Iftheparameterisshadowedbyavariableininnerscope,surprisingly,theinnervariableisnotavailable.Thefollowingexamplewillhelpexplainthis:
varscope="outer_scope";functionscoper(val=scope){varscope="inner_scope";console.log(val);//outer_scope}scoper();
Youmayexpectvaltogetshadowedbytheinnerdefinitionofthescopevariable,butasthedefaultparametershavetheirownscope,thevalueassignedtovalisunaffectedbytheinnerscope.
![Page 116: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/116.jpg)
Rest parametersES6 introduces rest parameters. Rest parameters allow us to send an arbitrary number ofparameterstoafunctionintheformofanarray.Restparametercanonlybethelastoneinthelistofparameters,andtherecanonlybeonerestparameter.Puttingarestoperator(...)beforethelastformalparameterindicatesthatparameterisarestparameter.Thefollowingexampleshowsaddingarestoperatorbeforethelastformalparameter:
functionsayThings(tone,...quotes){console.log(Array.isArray(quotes)); //true
console.log(`In${tone}voice,Isay${quotes}`)}sayThings("MorganFreeman","Somethingserious","ImplodingUniverse","Amen");//InMorganFreemanvoice,IsaySomethingserious,ImplodingUniverse,Amen
Thefirstparameterpassedtothefunctionisreceivedintone,whiletherestoftheparametersarereceivedasanarray.Variablearguments(var-args)havebeenpartofseveralotherlanguagesandawelcomeeditiontoES6.Restparameterscanreplacetheslightlycontroversialargumentsvariable.Themajordifferencebetweenrestparametersandtheargumentsvariableisthattherestparametersarerealarrays.Allarraymethodsareavailabletorestparameters.
![Page 117: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/117.jpg)
Spread operatorsA spread operator looks exactly like a rest operator but performs the exact opposite function.Spreadoperatorsareusedwhileprovidingargumentswhilecallingafunctionordefininganarray.Thespreadoperatortakesanarrayandsplitsitselementintoindividualvariables.Thefollowingexampleillustrateshowthespreadoperatorprovidesamuchclearersyntaxwhilecallingfunctionsthattakeanarrayasanargument:
functionsumAll(a,b,c){returna+b+c}varnumbers=[6,7,8]//ES5wayofpassingarrayasanargumentofafunction
console.log(sumAll.apply(null,numbers)); //21//ES6Spreadoperatorconsole.log(sumAll(...numbers))//21
InES5,itiscommontousetheapply()function whenpassinganarrayasanargumenttoafunction.Intheprecedingexample,wehaveanarrayweneedtopasstoafunctionwherethefunctionacceptsthreevariables.TheES5methodofpassinganarraytothisfunctionusestheapply()function,wherethesecondargumentallowsanarraytobepassedtothefunctionbeingcalled.ES6spreadoperatorsgiveamuchcleanerandprecisewaytodealwiththissituation.WhilecallingsumAll(),weusethespreadoperator(...)andpassthenumbersarraytothefunctioncall.Thearrayisthensplitintoindividualvariables-a,b,andc.
Spread operators improve the capabilities of arrays in JavaScript. If you want to create an arraythatismadeupofanotherarray,theexistingarraysyntaxdoesnotsupportthis.Youhavetousepush,splice,andconcattoachievethis.However,usingspreadoperators,thisbecomestrivial:
varmidweek=['Wed','Thu'];varweekend=['Sat','Sun'];varweek=['Mon','Tue',...midweek,'Fri',...weekend];//["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]console.log(week);
Intheprecedingexample,weareconstructingaweekarrayusingtwoarrays,midweekandweekend,usingthespreadoperator.
![Page 118: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/118.jpg)
Predefinedfunctions
ThereareanumberoffunctionsthatarebuiltintotheJavaScriptengineandareavailableforyoutouse.Let'stakealookatthem.Whiledoingso,you'llhaveachancetoexperimentwithfunctions,theirargumentsandreturnvalues,andbecomecomfortableworkingwithfunctions.Thefollowingisalistofthebuilt-infunctions:
parseInt()parseFloat()isNaN()isFinite()encodeURI()decodeURI()encodeURIComponent()decodeURIComponent()eval()
Note
Theblackboxfunction
Often,whenyouinvokefunctions,yourprogramdoesn'tneedtoknowhowthesefunctionsworkinternally.Youcanthinkofafunctionasablackbox,giveitsomevalues(asinputarguments),andthentaketheoutputresultitreturns.Thisistrueforanyfunction-onethat'sbuiltintotheJavaScriptengine,onethatyoucreate,oronethataco-workerorsomeoneelsecreated.
parseInt()
TheparseInt()functiontakesanytypeofinput(mostoftenastring)and triestomakeanintegeroutofit.Ifitfails,itreturnsNaN,asshowninthefollowingcode:
>parseInt('123');123>parseInt('abc123');NaN>parseInt('1abc23');1>parseInt('123abc');123
The function accepts an optional second parameter, which is the radix, telling the function whattypeofnumbertoexpect-decimal,hexadecimal,binary,andsoon.Forexample,tryingtoextractadecimalnumberoutoftheFFstringmakesnosense,sotheresultisNaN,butifyoutryFFasahexadecimal,thenyouget255,asshowninthefollowingpieceofcode:
>parseInt('FF',10);NaN
![Page 119: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/119.jpg)
>parseInt('FF',16);255
Anotherexamplewouldbeparsingastringwithabase10(decimal)andbase8(octal):
> parseInt('0377', 10);377>parseInt('0377',8);255
IfyouomitthesecondargumentwhencallingparseInt(),thefunctionwillassume10(adecimal),withthefollowingexceptions:
Ifyoupassastringbeginningwith0x,thentheradixisassumedtobe16(ahexadecimalnumberisassumed).Ifthestringyoupassstartswith0,thefunctionassumesradix8(anoctalnumberisassumed).Considerthefollowingexamples:
>parseInt('377');377>console.log(0o377);255>parseInt('0x377');887
Thesafestthingtodoistoalwaysspecifytheradix.Ifyouomittheradix,yourcodewillprobablystillworkin99percentofcases(becausemostoftenyouparsedecimals);however,everyonceinawhile,itmightcauseyouabitofhairlosswhiledebuggingsomeedgecases.Forexample,imagineyouhaveaformfieldthatacceptscalendardaysormonthsandtheusertypes06or08.
Note
ECMAScript5removestheoctalliteralvaluesandavoidstheconfusionwithparseInt()andunspecifiedradix.
parseFloat()
TheparseFloat()functionissimilartotheparseInt()function,butitalsolooksfordecimalswhentryingtofigureoutanumberfromyourinput.Thisfunctiontakesonlyoneparameter,whichisasfollows:
>parseFloat('123');123>parseFloat('1.23');1.23>parseFloat('1.23abc.00');1.23>parseFloat('a.bc1.23');
![Page 120: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/120.jpg)
NaN
AswithparseInt(),parseFloat()givesupatthefirstoccurrenceofanunexpectedcharacter,eventhoughtherestofthestringmighthaveusablenumbersinit:
>parseFloat('a123.34');NaN>parseFloat('12a3.34');12
TheparseFloat()functionunderstandsexponentsintheinput(unlikeparseInt()):
>parseFloat('123e-2');1.23>parseFloat('1e10');10000000000>parseInt('1e10');1
isNaN()
UsingisNaN(),youcancheckifaninputvalueisavalidnumberthatcan safelybeusedinarithmeticoperations.ThisfunctionisalsoaconvenientwaytocheckwhetherparseInt(),parseFloat(),oranyarithmeticoperationsucceeded:
>isNaN(NaN);true>isNaN(123);false>isNaN(1.23);false>isNaN(parseInt('abc123'));true
Thefunctionwillalsotrytoconverttheinputtoanumber:
>isNaN('1.23');false>isNaN('a1.23');true
TheisNaN()functionisusefulbecausethespecialvalueNaNisnotequaltoanything,includingitself.Inotherwords,NaN===NaNisfalse.So,NaNcannotbeusedtocheckifavalueisavalidnumber.
isFinite()
TheisFinite()functioncheckswhethertheinputisanumberthatisneitherInfinitynorNaN:
>isFinite(Infinity);false
![Page 121: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/121.jpg)
>isFinite(-Infinity);false>isFinite(12);true>isFinite(1e308);true>isFinite(1e309);false
Ifyouarewonderingabouttheresultsreturnedbythelasttwocalls,rememberfromthepreviouschapterthatthebiggestnumberinJavaScriptis1.7976931348623157e+308,so1e309iseffectivelyinfinity.
Encode/decodeURIs
InaUniformResourceLocator(URL)oraUniformResourceIdentifier(URI),somecharactershavespecialmeanings.Ifyouwanttoescapethosecharacters,youcanusetheencodeURI()orencodeURIComponent()functions.ThefirstonewillreturnausableURL,whilethesecondoneassumesyou'reonlypassingapartoftheURL,suchasaquerystringforexample,andwillencodeallapplicablecharacters,asfollows:
>varurl='http://www.packtpub.com/script.php?q=thisandthat';>encodeURI(url);"http://www.packtpub.com/script.php?q=this%20and%20that">encodeURIComponent(url);"http%3A%2F%2Fwww.packtpub.com%2Fscript.php%3Fq%3Dthis%20and%20that"
TheoppositesofencodeURI()andencodeURIComponent()aredecodeURI()anddecodeURIComponent(),respectively.
Sometimes,inlegacycode,youmightseethefunctionsescape()andunescape()usedtoencodeanddecodeURLs,butthesefunctionshavebeendeprecated;theyencodedifferentlyandshouldnotbeused.
eval()
Theeval()functiontakesastringinputandexecutesitasaJavaScriptcode,asfollows:
>eval('varii=2;');>ii;2
So,eval('varii=2;')isthesameasvarii=2;
Theeval()functioncanbeusefulsometimes,butitshouldbeavoidedifthereareotheroptions.Mostofthetime,therearealternatives,andinmostcases,thealternativesaremoreelegantandeasiertowriteandmaintain.EvalisevilisamantrayoucanoftenhearfromseasonedJavaScriptprogrammers.Thedrawbacksofusingeval()areasfollows:
![Page 122: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/122.jpg)
Security:JavaScriptispowerful,whichalsomeansitcancausedamage.Ifyoudon'ttrustthesourceoftheinputyoupasstoeval(),justdon'tuseit.Performance:It'sslowertoevaluatelivecodethantohavethecodedirectlyinthescript.
Abonus-thealert()function
Let'stakealookatanothercommonfunction-alert().It'snotpartofthecoreJavaScript(it'snowheretobefoundintheECMAspecification),butit'sprovidedbythehostenvironment-thebrowser.Itshowsastringoftextinamessagebox.Itcanalsobeusedasaprimitivedebuggingtool,althoughthedebuggersinmodernbrowsersaremuchbettersuitedforthispurpose.
Here'sascreenshotshowingtheresultofexecutingthealert("HiThere")code:
Beforeusingthisfunction,bearinmindthatitblocksthebrowserthread,meaningthatnoothercodewillbeexecuteduntiltheuserclosesthealert.IfyouhaveabusyAjax-typeapplication,it'sgenerallynotagoodideatousealert().
![Page 123: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/123.jpg)
Scope of variablesIt's important to note, especially if you have come to JavaScript from another language, thatvariablesinJavaScriptarenotdefinedinablockscope,butinafunctionscope.Thismeansthatifavariableisdefinedinsideafunction,it'snotvisibleoutsideofthefunction.However,ifit'sdefinedinsideaniforaforcodeblock,it'svisibleoutsidetheblock.Thetermglobalvariablesdescribesvariablesyoudefineoutsideofanyfunction(intheglobalprogramcode),asopposedtolocalvariables,whicharedefinedinsideafunction.Thecodeinsideafunctionhasaccesstoallglobalvariablesaswellastoitsownlocalones.
Inthenextexample:
Thef()functionhasaccesstotheglobalvariableOutsidethef()function,thelocalvariable doesn'texist
varglobal=1;functionf(){varlocal=2;global++;returnglobal;}
Let'stestthis:
>f();2>f();3>local;ReferenceError:localisnotdefined
It'salsoimportanttonotethatifyoudon'tusevartodeclareavariable,thisvariableisautomaticallyassigneda globalscope.Let'sseeanexample:
![Page 124: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/124.jpg)
Whathappened?Thef()functioncontainsthelocalvariable.Beforecallingthefunction,thevariabledoesn'texist.Whenyoucallthefunctionforthefirsttime,thelocalvariableiscreatedwithaglobalscope.Then,ifyouaccessthelocalvariableoutsidethefunction,itwillbeavailable.
Note
Bestpracticetips
Minimizethenumberofglobalvariablesinordertoavoidnamingcollisions.Imaginetwopeopleworkingontwodifferentfunctionsinthesamescript,andtheybothdecidetousethesamenamefortheirglobalvariable.Thiscouldeasilyleadtounexpectedresultsandhard-to-findbugs.Alwaysdeclareyourvariableswiththevarstatement.Considerasinglevarpattern.Defineallvariablesneededinyourfunctionattheverytopofthefunctionsoyouhaveasingleplacetolookforvariablesand,hopefully,preventaccidentalglobals.
![Page 125: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/125.jpg)
Variablehoisting
Here'saninterestingexamplethatshowsanimportantaspectoflocalversusglobalscoping:
var a = 123;
functionf(){alert(a);vara=1;alert(a);}
f();
Youmightexpectthatthefirstalert()functionwilldisplay123(thevalueoftheglobalvariablea)andthesecondwilldisplay1(thelocalvariablea).But,thisisnotthecase.Thefirstalertwillshowundefined.Thisisbecause,insidethefunction,thelocalscopeismoreimportantthantheglobalscope.So,alocalvariableoverwrites anyglobalvariablewiththesamename.Atthetimeofthefirstalert(),theavariablewasnotyetdefined(hencetheundefinedvalue),butitstillexistedinthelocalspaceduetothespecialbehaviorcalledhoisting.
WhenyourJavaScriptprogramexecutionentersanewfunction,allthevariablesdeclaredanywhereinthefunctionaremoved,elevated,orhoistedtothetopofthefunction.Thisisanimportantconcepttokeepinmind.Further,onlythedeclarationishoisted,meaningonlythepresenceofthevariableismovedtothetop.Anyassignmentsstaywheretheyare.Intheprecedingexample,thedeclarationofthelocalvariableawashoistedtothetop.Onlythedeclarationwashoisted, butnottheassignmentto1.It'sasifthefunctionwaswritteninthefollowingway:
vara=123;
functionf(){vara;//sameas:vara=undefined;alert(a);//undefineda=1;alert(a);//1}
Youcanalsoadoptthesinglevarpatternmentionedpreviouslyinthebestpracticesection.Inthiscase,you'llbedoingasortofmanualvariablehoistingtopreventconfusionwiththeJavaScripthoistingbehavior.
![Page 126: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/126.jpg)
Block scopeES6 provides additional scope while declaring variables. We looked at function scope and how itaffectsvariablesdeclaredwiththevarkeyword.IfyouarecodinginES6,blockscopewillmostlyreplaceyourneedtousevariablesdeclaredusingvar.Although,ifyouarestillwithES5,wewantyoutomakesurethatyoulookathoistingbehaviorcarefully.
ES6introducestheletandconstkeywordsthat allowustodeclarevariables.
Variablesdeclaredwithletareblock-scoped.Theyexistonlywithinthe currentblock.Variablesdeclaredwithvararefunctionscoped,aswesawearlier.Thefollowingexampleillustratestheblockscope:
vara=1;{leta=2;console.log(a);//2}console.log(a);//1
Thescopebetweenanopeningbrace'{'andaclosingbrace'}'isablock.IfyouarecomingfromabackgroundinJavaorC/C++,theconceptofablockscopewillbeveryfamiliartoyou.Inthoselanguages,programmersintroducedblocksjusttodefineascope.InJavaScript,however,therewasaneedtoidiomaticallyintroduceblocksastheydidn'thaveascopeassociatedtoit.However,ES6allowsyoutocreateblock-scopedvariablesusingtheletkeyword.Asyoucanseeintheprecedingexample,variableacreatedinsidetheblockisavailablewithintheblock.Whiledeclaringblock-scopedvariables,itisgenerallyrecommendedtoaddtheletdeclarationatthetopoftheblock.Let'slookatanotherexampletoclearlydistinguishfunctionandblockscope:
functionswap(a,b){//<--functionscopestartshereif(a>0&&b>0){//<--blockscopestartsherelettmp=a;a=b;b=tmp;}//<--blockscopeendshereconsole.log(a,b);
console.log(tmp); // tmp is not defined as it is availableonlyintheblockscopereturn[a,b];}swap(1,2);
Asyoucansee,tmpisdeclaredwithletandisavailableonlyintheblockinwhichitwasdefined.Forallpracticalpurposes,youshouldmaximizeyouruseofblock-scopedvariables.Unlessthereissomethingveryspecificyouaretryingtodothatmakesitnecessaryforyoutouse
![Page 127: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/127.jpg)
vardeclarations,makesureyoupreferblockscopedvariables.However,incorrectlyusingtheletkeywordcancauseacoupleofproblems.First,youcannotredeclarethesamevariablewithinthesamefunctionorblockscopeusingtheletkeyword:
functionblocker(x){if(x){letf;letf;//duplicatedeclaration"f"}}
InES6,variablesdeclaredbytheletkeywordarehoistedtoblockscope.However,referencingthevariablebeforeitsdeclarationisanerror.
AnotherkeywordintroducedinES6isconst.Avariabledeclaredwiththeconstkeywordcreatesaread-onlyreferencetoavalue.Thisdoesnotmeanthatthevalueheldbythereferenceisimmutable. However, the variable identifier cannot be reassigned. Constants are block-scopedjustlikevariablescreatedusingtheletkeyword.Also,youhavetoassignavaluetothevariablewhiledeclaringthem.
Althoughitsoundslikeitdoes,consthasnothingtodowithimmutablevalues.Constantscreateimmutablebinding.Thisisanimportantdistinctionandneedstobeunderstoodcorrectly.Let'sconsiderthefollowingexample:
constcar={}car.tyres=4
Thisisavalidcode;hereweareassigningvalue {}toaconstantcar.Onceassigned,thisreferencecannotbechanged.InES6,youshoulddothefollowing:
Useconstwherepossible.Usethemforallvariableswhosevaluesdon'tchange:
Uselet
Avoidvar.
![Page 128: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/128.jpg)
Functions are dataFunctions in JavaScript are actually data. This is an important concept that we'll need later on.Thismeansthatyoucancreateafunctionandassignittoavariable,asfollows:
varf=function(){return1;};
Thiswayofdefiningafunctionissometimesreferredtoasfunctionliteralnotation.
Thefunction(){return1;}partisafunctionexpression.Afunctionexpressioncanoptionallyhaveaname,inwhichcaseitbecomesanamedfunctionexpression(NFE).So,thisisalsoallowed,althoughrarelyseeninpractice(andcausesIEtomistakenlycreatetwovariablesintheenclosingscope-fandmyFunc):
varf=functionmyFunc(){return1;};
Asyoucansee,there'snodifferencebetweenanamedfunctionexpressionandafunctiondeclaration. But they are, in fact, different. The only way to distinguish between the two is to lookatthecontextinwhichtheyareused.Functiondeclarationsmayonlyappearinprogramcode(inabodyofanotherfunctionorinthemainprogram).You'llseemanymoreexamplesoffunctionslateroninthebookthatwillclarifytheseconcepts.
Whenyouusethetypeofoperatoronavariablethatholdsafunctionvalue,itreturnsthestring"function"asshowninthefollowingexample:
>functiondefine(){return1;}
>varexpress=function(){return1;};
>typeofdefine;"function"
>typeofexpress;"function"
So,JavaScriptfunctionsaredata,butaspecialkindofdatawiththefollowingtwoimportantfeatures:
TheycontaincodeTheyareexecutable(theycanbeinvoked)
![Page 129: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/129.jpg)
Asyouhaveseenbefore,thewaytoexecuteafunctionisbyaddingparenthesesafteritsname.Asthenextexampledemonstrates,thisworksregardlessofhowthefunctionwasdefined.Intheexample,youcanalsoseehowafunctionistreatedasaregularvalue;itcanbecopiedtoadifferentvariable,asfollows:
>varsum=function(a,b){returna+b;};
>varadd=sum;>typeofadd;function>add(1,2);3
Asfunctionsaredataassignedtovariables,thesamerulesfornamingfunctionsapplyasfornamingvariables-afunctionnamecannotstartwithanumberanditcancontainanycombinationofletters,numbers,theunderscorecharacter,and thedollarsign.
![Page 130: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/130.jpg)
Anonymousfunctions
Asyounowknow,thereexistsafunctionexpressionsyntaxwhereyoucanhaveafunctiondefinedlikethefollowing:
varf=function(a){returna;};
Thisisalsooftencalledananonymousfunction(asitdoesn'thaveaname),especiallywhensuchafunctionexpressionisusedevenwithoutassigningittoavariable.Inthiscase,therecanbetwoelegantusesforsuchanonymousfunctions,whichareasfollows:
Youcanpassananonymousfunctionasaparametertoanotherfunction.Thereceivingfunctioncandosomethingusefulwiththefunctionthatyoupass.Youcandefineananonymousfunctionandexecuteitrightaway.
Let'sseethesetwoapplicationsofanonymousfunctionsinmoredetail.
![Page 131: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/131.jpg)
Callbackfunctions
Asafunctionisjustlikeanyotherdataassignedtoavariable,itcanbedefined,copied,andalsopassedasanargumenttootherfunctions.
Here'sanexampleofafunctionthatacceptstwofunctionsasparameters,executesthem,andreturnsthesumofwhateachofthemreturns:
functioninvokeAdd(a,b){returna()+b();}
Now, let's define two simple additional functions using a function declaration pattern that onlyreturnshardcodedvalues:
functionone(){return1;}functiontwo(){return2;}
Nowyoucanpassthosefunctionstotheoriginalfunction,invokeAdd(),andgetthefollowingresult:
>invokeAdd(one,two);3
Anotherexampleofpassingafunctionasaparameteristouseanonymousfunctions(functionexpressions).Insteadofdefiningone()andtwo(),youcansimplydothefollowing:
>invokeAdd(function(){return1;},function(){return2;});3
Or,youcanmakeitmorereadable,asshowninthefollowingcode:
>invokeAdd(function(){return1;},function(){return2;});3
Or,youcandothefollowing:
>invokeAdd(function(){return1;},function(){
![Page 132: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/132.jpg)
return2;});3
Whenyoupassafunction,A,toanotherfunction,B,andthenBexecutesA,it'softensaidthatAisacallbackfunction.IfAdoesn'thaveaname,thenyoucansaythatit'sananonymouscallbackfunction.
Whenarecallbackfunctionsuseful?Let'sseesomeexamplesthatdemonstratethebenefitsofcallbackfunctions,namely:
Theyletyoupassfunctionswithouttheneedtonamethem,whichmeanstherearefewervariablesfloatingaroundYoucandelegatetheresponsibilityofcallingafunctiontoanotherfunction,whichmeansthere is less code to writeTheycanhelpwithperformancebydeferringtheexecutionorbyunblockingcalls
Callbackexamples
Take a look at this common scenario-you have a function that returns a value, which you then passtoanotherfunction.Inourexample,thefirstfunction,multiplyByTwo(),acceptsthreeparameters,loopsthroughthem,multipliesthembytwo,andreturnsanarraycontainingtheresult.Thesecondfunction,addOne(),takesavalue,addsonetoit,andreturnsit,asfollows:
functionmultiplyByTwo(a,b,c){vari,ar=[];for(i=0;i<3;i++){ar[i]=arguments[i]*2;}returnar;}
functionaddOne(a){returna+1;}
Let'stestthesefunctions:
>multiplyByTwo(1,2,3);[2,4,6]>addOne(100);101
Now,let'ssayyouwanttohaveanarray,myarr,thatcontainsthreeelements,andeachoftheelementsistobepassedthroughbothfunctions.First,let'sstartwithacalltomultiplyByTwo():
>varmyarr=[];>myarr=multiplyByTwo(10,20,30);[20,40,60]
![Page 133: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/133.jpg)
Now,loopthrougheachelement,passingittoaddOne():
>for(vari=0;i<3;i++){myarr[i]=addOne(myarr[i]);}>myarr;[21,41,61]
Asyoucansee,everythingworksfine,butthere'sroomforimprovement.Forexample,thereweretwoloops.Loopscanbeexpensiveiftheygothroughalotofrepetitions.Youcanachievethesameresultwithonlyoneloop.Here'showtomodifymultiplyByTwo()sothatitacceptsacallbackfunctionandinvokesthatcallbackoneveryiteration:
functionmultiplyByTwo(a,b,c,callback){vari,ar=[];for(i=0;i<3;i++){ar[i]=callback(arguments[i]*2);}returnar;}
Usingthemodifiedfunction,alltheworkisdonewithjustonefunctioncall,whichpassesthestartvaluesandthecallbackfunction,asfollows:
>myarr=multiplyByTwo(1,2,3,addOne);[3,5,7]
InsteadofdefiningaddOne(),youcanuseananonymousfunction,thereforesavinganextraglobalvariable:
>multiplyByTwo(1,2,3,function(a){returna+1;});[3,5,7]
Anonymousfunctionsareeasytochangeshouldtheneedarise:
>multiplyByTwo(1,2,3,function(a){returna+2;});[4,6,8]
![Page 134: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/134.jpg)
Immediatefunctions
Sofar,wehavediscussedusinganonymousfunctionsascallbacks.Let'sseeanotherapplicationofananonymousfunction-callingafunctionimmediatelyafterit'sdefined.Here'sanexample:
(function(){alert('boo');}
)();
Thesyntaxmaylookalittlescaryatfirst,butallyoudoissimplyplaceafunctionexpressioninsideparenthesesfollowedbyanothersetofparentheses.Thesecondsetsaysexecutenowandisalsotheplacetoputanyargumentsthatyouranonymousfunctionmightaccept,forexample:
(function(name){alert('Hello'+name+'!');})('dude');
Alternatively,youcanmovetheclosingofthefirstsetofparenthesestotheend.Bothofthesework:
(function(){// ...
}());
//vs.
(function(){//...})();
Onegoodapplicationofimmediate(self-invoking)anonymousfunctionsiswhenyouwanttohavesomeworkdonewithoutcreatingextraglobalvariables.Adrawback,ofcourse,isthatyoucannotexecutethesamefunctiontwice.Thismakesimmediatefunctionsbestsuitedforone-offorinitialization tasks.
Animmediatefunctioncanalsooptionallyreturnavalueifyouneedone.It'snotuncommontoseecodethatlookslikethefollowing:
varresult=(function(){//somethingcomplexwith//temporarylocalvariables...//...//returnsomething;}());
![Page 135: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/135.jpg)
Inthiscase,youdon'tneedtowrapthefunctionexpressioninparentheses;youonlyneedtheparenthesesthatinvokethefunction.So,thefollowingpieceofcodealsoworks:
varresult=function(){//somethingcomplexwith//temporarylocalvariables//returnsomething;}();
Thissyntaxworks,butmaylookslightlyconfusing;withoutreadingtheendofthefunction,youdon'tknowifresultisafunctionorthereturnvalueoftheimmediatefunction.
![Page 136: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/136.jpg)
Inner(private)functions
Bearinginmindthatafunctionisjustlikeanyothervalue,there'snothingthatstopsyoufromdefiningafunctioninsideanotherfunction,here's theexample:
functionouter(param){functioninner(theinput){returntheinput*2;}
return 'The result is ' + inner(param);}
Usingafunctionexpression,thiscanalsobewrittenasfollows:
varouter=function(param){varinner=function(theinput){returntheinput*2;};return'Theresultis'+inner(param);};
Whenyoucalltheglobalouter()function,itwillinternallycallthelocalinner()function.Asinner()islocal,it'snotaccessibleoutsideouter(),soyoucansayit'saprivatefunction:
>outer(2);"Theresultis4">outer(8);"Theresultis16">inner(2);ReferenceError:innerisnotdefined
Thebenefitsofusingprivatefunctionsareasfollows:
Youcankeeptheglobalnamespaceclean,whichislesslikelytocausenamingcollisionsPrivacy-youcanexposeonlythosefunctionstotheoutsideworldthatyoudecide,andkeepthefunctionalitythatisnotmeanttobeconsumedbytherestoftheapplicationtoyourself
![Page 137: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/137.jpg)
Functionsthatreturnfunctions
Asmentionedearlier,afunctionalwaysreturnsa value,andifitdoesn'tdoitexplicitlywithreturn,thenitdoessoimplicitlybyreturningundefined.Afunctioncanreturnonlyonevalue,andthisvaluecanjustaseasilybeanotherfunction,forexample:
functiona(){alert('A!');returnfunction(){alert('B!');
};}
Inthisexample,thea()functiondoesitsjob(saysA!)andreturnsanotherfunctionthatdoessomethingelse(saysB!).Youcanassignthereturnvaluetoavariableandthenusethisvariableasanormalfunction,asfollows:
>varnewFunc=a();>newFunc();
Here,thefirstlinewillalertA!andthesecondwillalertB!.
Ifyouwanttoexecutethereturnedfunctionimmediatelywithoutassigningittoanewvariable,youcansimplyuseanothersetofparentheses.Theendresultwillbethesame:
>a()();
![Page 138: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/138.jpg)
Function,rewritethyself!
Asafunctioncanreturnafunction,youcanusethenewfunctiontoreplacetheoldone.Continuingwiththepreviousexample,youcantakethevaluereturnedbythecalltoa()tooverwritetheactuala() function:
> a = a();
TheprecedinglineofcodealertsA!,butthenexttimeyoucalla()italertsB!.Thisisusefulwhenafunctionhassomeinitialone-offworktodo.Thefunctionoverwritesitselfafterthefirstcallinordertoavoiddoingunnecessaryrepetitiveworkeverytimeit'scalled.
Intheprecedingexample,thefunctionwasredefinedfromtheoutsideandthereturnedvaluewasassignedbacktothefunction.But,thefunctioncanactuallyrewriteitselffromtheinside,asshowninthefollowingexample:
functiona(){alert('A!');a=function(){alert('B!');};}
Ifyoucallthisfunctionforthefirsttime,itwilldothefollowing:
AlertA!(considerthisasbeingtheone-offpreparatorywork)Redefinetheglobalvariableaandassigninganewfunctiontoit
Everysubsequenttimethatthefunctioniscalled,itwillalertB!.
Here'sanotherexamplethatcombinesseveralofthetechniquesdiscussedinthelastfewsectionsofthischapter:
vara=(function(){
functionsomeSetup(){varsetup='done';}
functionactualWork(){alert('Worky-worky');
}
someSetup();returnactualWork;
}());
![Page 139: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/139.jpg)
Fromthisexample,youcannotethefollowingthings:
Youhaveprivatefunctions;someSetup()andactualWork().Youhaveanimmediatefunction:ananonymousfunctionthatcallsitselfusingtheparenthesesfollowingitsdefinition.Thefunctionexecutesforthefirsttime,callssomeSetup(),andthenreturnsareferencetotheactualWorkvariable,whichisafunction.Noticethattherearenoparenthesesinthereturnstatementbecauseyou'rereturningafunctionreference,nottheresultofinvokingthisfunction.Asthewholethingstartswithvara=,thevaluereturnedbytheself-invokedfunctionisassignedtoa.
Ifyouwanttotestyourunderstandingofthetopicsjustdiscussed,answerthefollowingquestions.Whatwilltheprecedingcodealertbeinthefollowingcases:
Itisinitiallyloaded?Youcalla()afterwards?
Thesetechniquescouldbereallyusefulwhenworkinginthebrowserenvironment.Differentbrowserscanhavedifferentwaysofachievingthesameresult.Ifyouknowthatthebrowserfeatureswon'tchangebetweenfunctioncalls,youcanhaveafunctiondeterminethebestwaytodotheworkinthecurrentbrowser,thenredefineitselfsothatthebrowsercapabilitydetectionisdoneonlyonce.You'llseeconcreteexamplesofthisscenariolaterinthisbook.
![Page 140: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/140.jpg)
ClosuresThe rest of the chapter is about closures (what better way to close a chapter?). Closures can be alittlehardtograspinitially,sodon'tfeeldiscouragedifyoudon'tgetitduringthefirstread.Youshouldgothroughtherestofthechapterandexperimentwiththeexamplesonyourown,butifyoufeelyoudon'tfullyunderstandtheconcept,youcancomebacktoitlaterwhenthetopicsdiscussedpreviouslyinthischapterhavehadachancetosinkin.
Beforemovingontoclosures,let'sfirstreviewandexpandontheconceptofscopeinJavaScript.
![Page 141: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/141.jpg)
Scopechain
Asyouknow,inJavaScript,thereisnocurlybracesscope,butthereisafunctionscope.Avariabledefinedinafunctionisnotvisibleoutsidethefunction,butavariabledefinedinacodeblock(forexampleaniforaforloop)isvisibleoutsidetheblock,forexample:
>vara=1;>functionf(){varb=1;returna;
}>f();1>b;ReferenceError:bisnotdefined
Theavariableisintheglobalspace,whilebisinthescopeofthefunctionf().So,wehavethefollowing:
Insidef(),bothaandbarevisibleOutsidef(),aisvisible,butbisnot
If you define an inner()function nested inside outer(), it will have access to variables in itsown scope, plus the scope of its parents. This is known as a scope chain, and the chain can be aslong(deep)asyouneedittobe:
varglobal=1;functionouter(){varouter_local=2;functioninner(){varinner_local=3;returninner_local+outer_local+global;}returninner();}
Let'stestiftheinner()functionhasaccesstoallvariables:
>outer();6
![Page 142: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/142.jpg)
Breakingthechainwithaclosure
Let'sintroduceclosureswithanillustrationandlookatthefollowingcodeandseewhat'shappeningthere:
vara="globalvariable";varF=function(){varb="localvariable";varN=function(){
var c = "inner local";};};
First,thereistheglobalscopeG.Thinkofitastheuniverse,asifitcontainseverything:
![Page 143: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/143.jpg)
Itcancontainglobalvariablessuchasa1anda2andglobalfunctionssuchasF:
Functionshavetheirownprivatespaceandcanuseittostoreothervariables,suchasb,andinnerfunctions,suchasN(forinner).Atsomepoint,youwillendupwithapicturelikethefollowing:
![Page 144: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/144.jpg)
Ifyou'reatpointa,you'reinsidetheglobalspace.Ifyou'reatpointb,whichisinsidethespaceoftheFfunction,thenyouhaveaccesstotheglobalspaceandtotheFspace.Ifyou'reatpointc,whichisinsidetheNfunction,thenyoucanaccesstheglobalspace,theFspace,andtheNspace.Youcannotreachfromatob,becausebisinvisibleoutsideF.But,youcangetfromctobifyouwantorfromNtob.TheinterestingpartisthattheclosureeffecthappenswhensomehowNbreaksoutofFandendsupintheglobalspace.
![Page 145: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/145.jpg)
Whathappensthen?Nisinthesameglobalspaceasa.And,asfunctionsremembertheenvironmentinwhichtheyweredefined,NwillstillhaveaccesstotheFspace,andhence,canaccessb.Thisisinteresting,becauseNiswhereaisandyetNdoeshaveaccesstob,butadoesn't.
Additionally,howdoesNbreakthechain?Bymakingitselfglobal(omittingvar)orbyhavingFdeliver(orreturn)ittotheglobalspace.Let'sseehowthisisdoneinpractice.
Closure #1
Takealookatthefollowingfunction,whichisthesameasbefore,onlyFreturnsNandalsoNreturnsb,towhichithasaccessviathescopechain:
vara="globalvariable";varF=function(){varb="localvariable";varN=function(){varc="innerlocal";
return b;};returnN;};
TheFfunctioncontainsthebvariable,whichislocal,andthereforeinaccessiblefromtheglobalspace:
>b;ReferenceError:bisnotdefined
The N function has access to its private space, to the F() function's space, and to the global space.So, it can see b. As F() is callable from the global space (it's a global function), you can call itand assign the returned value to another global variable. The result - a new global function thathasaccesstotheF()function'sprivatespace:
>varinner=F();>inner();"localvariable"
Closure#2
Thefinalresultofthenextexamplewillbethesameasthepreviousexample,butthewaytoachieveitisalittledifferent.F()doesn'treturnafunction,butinsteaditcreatesanewglobalfunction,inner(),insideitsbody.
Let'sstartbydeclaringa placeholderfortheglobalfunction-to-be.Thisisoptional,butit'salwaysgoodtodeclareyourvariables.Then,youcandefinetheF()functionasfollows:
![Page 146: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/146.jpg)
varinner;//placeholdervarF=function(){varb="localvariable";varN=function(){returnb;};inner=N;};
Now,let'sseewhathappensifyouinvokeF():
>F();
Anewfunction,N(),isdefinedinsideF()andassignedtotheglobalinnerfunction.Duringdefinitiontime,N()wasinsideF(),soithadaccesstotheF()function'sscope.Theinner()functionwillkeepitsaccesstotheF()function'sscope,eventhoughit'spartoftheglobalspace,forexample:
>inner();"localvariable".
Adefinitionandclosure#3
Everyfunctioncanbeconsideredaclosure.Thisisbecauseeveryfunctionmaintainsasecretlinktotheenvironment(thescope)inwhichitwascreated.But,mostofthetime,thisscopeisdestroyedunlesssomethinginterestinghappens(asshownintheprecedingcode)thatcausesittobemaintained.
Basedonwhatyou'veseensofar,youcansaythataclosureiscreatedwhenafunctionkeepsalinktoitsparentscopeevenaftertheparenthasreturned.And,everyfunctionisaclosurebecause,attheveryleast,everyfunctionmaintainsaccesstotheglobalscope,whichisneverdestroyed.
Let'sseeonemoreexampleofaclosure,thistimeusingthefunctionparameters.Functionparameters behave like local variables to this function, but they are implicitly created; you don'tneedtousevarforthem.Youcancreateafunctionthatreturnsanotherfunction,whichinturnreturnsitsparent'sparameter,asfollows:
functionF(param){varN=function(){returnparam;};param++;returnN;}
Youcanusethefunctionasfollows:
>varinner=F(123);
![Page 147: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/147.jpg)
>inner();124
Noticehowparam++wasincrementedafterthefunctionwasdefinedandyet,whencalled,inner()returnedtheupdatedvalue.Thisdemonstratesthatthefunctionmaintainsareferencetothescopewhereitwasdefined,andnottothevariablesandtheirvaluesfoundinthescopeduringthefunctionexecution.
![Page 148: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/148.jpg)
Closuresinaloop
Let'stakealookatacanonicalrookiemistakewhenitcomestoclosures.Itcaneasilyleadtohard-to-spotbugs,becauseonthesurface,everythinglooksnormal.
Let'sloopthreetimes,eachtimecreatinganewfunctionthatreturnstheloopsequencenumber.Thenewfunctionswillbeaddedtoanarrayandthearrayisreturnedattheend.Here'sthefunction:
functionF(){vararr=[],i;for(i=0;i<3;i++){arr[i]=function(){returni;};}returnarr;}
Let'srunthefunction,assigningtheresulttothearrarray:
>vararr=F();
Nowyouhaveanarrayofthreefunctions.Let'sinvokethembyaddingparenthesesaftereacharrayelement.Theexpectedbehavioristoseetheloopsequenceprintedoutas0,1,and2.Let'stry:
>arr[0]();3>arr[1]();3>arr[2]();3
Hmm,notquiteasexpected.Whathappenedhere?Allthreefunctionspointtothesamelocalvariable:i.Why?Thefunctionsdon'tremembervalues,theyonlykeepalink(reference)totheenvironmentwheretheywerecreated.Inthiscase,theivariablehappenstoliveintheenvironmentwherethethreefunctionsweredefined.So,allfunctions,whentheyneedtoaccessthevalue,reachbacktotheenvironmentandfindthemostcurrentvalueofi.Aftertheloop,theivariable'svalueis3.So,allthreefunctionspointtothesamevalue.
Whythreeandnottwoisanothergoodquestiontothinkaboutforbetterunderstandingtheforloop.
So,howdoyouimplementthecorrectbehavior?Theansweristouseanotherclosure,asshowninthefollowingpieceofcode:
![Page 149: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/149.jpg)
functionF(){vararr=[],i;for(i=0;i<3;i++){arr[i]=(function(x){returnfunction(){returnx;};}(i));}returnarr;}
Thisgivesyoutheexpectedresultasfollows:
>vararr=F();>arr[0]();0>arr[1]();1>arr[2]();2
Here,insteadofjustcreatingafunctionthatreturnsi,youpasstheivariable'scurrentvaluetoanotherimmediatefunction.Inthisfunction,ibecomesthelocalvaluex,andxhasadifferentvalueeverytime.
Alternatively,youcanuseanormal(asopposedtoanimmediate)innerfunctiontoachievethesameresult.Thekeyistousethemiddlefunctiontolocalizethevalueofiateveryiteration,asfollows:
functionF(){
functionbinder(x){returnfunction(){returnx;};}
vararr=[],i;for(i=0;i<3;i++){arr[i]=binder(i);}returnarr;}
![Page 150: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/150.jpg)
Getterandsetter
Let'sseetwomoreexamplesofusingclosures.Thefirstoneinvolvesthecreationofthegetterandsetterfunctions.Imaginethatyouhaveavariablethatshouldcontainaspecifictypeofvalueoraspecificrangeofvalues.Youdon'twanttoexposethisvariablebecauseyoudon'twantjustanypartofthecodetobeabletoalteritsvalue.Youcanprotectthisvariableinsideafunctionandprovidetwoadditionalfunctions-onetogetthevalueandonetosetit.Theonethatsetsitcouldcontainsomelogictovalidateavaluebeforeassigningittotheprotectedvariable.Let'smakethevalidationpartsimple(forthesakeofkeepingtheexampleshort)andonlyacceptnumbervalues.
Youcanplaceboththegetterandthesetterfunctionsinsidethesamefunctionthatcontainsthesecretvariablesothattheysharethesamescope:
vargetValue,setValue;
(function () {
varsecret=0;
getValue=function(){returnsecret;};
setValue=function(v){if(typeofv==="number"){secret=v;}};
}());
Inthiscase,thefunctionthatcontainseverythingisanimmediatefunction.ItdefinessetValue()andgetValue()asglobalfunctions,whilethesecretvariableremainslocalandinaccessibledirectly,asshowninthefollowingexample:
>getValue();0>setValue(123);>getValue();123>setValue(false);>getValue();123
![Page 151: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/151.jpg)
Iterator
Thelastclosureexample(alsothelastexampleinthischapter)showstheuseofaclosuretoaccomplishaniteratorfunctionality.
Youalreadyknowhowtoloopthroughasimplearray,buttheremightbecaseswhereyouhaveamorecomplicateddatastructurewithdifferentrulesastowhatthesequenceofvalueshas.Youcanwrapthecomplicatedwho'snextlogicintoaneasy-to-usenext()function.Then,youcansimplycallnext()everytimeyouneedtheconsecutivevalue.
Forthisexample,let'sjustuseasimplearrayandnotacomplexdatastructure.Here'saninitializationfunctionthattakesaninputarrayandalsodefinesasecretpointer,i,thatwillalwayspointtothenextelementinthearray:
functionsetup(x){vari=0;returnfunction(){returnx[i++];};}
Calling the setup() function with a data array will create the next() function for you, asfollows:
>varnext=setup(['a','b','c']);
Fromthereit'seasyandfun;callingthesamefunctionoverandoveragaingivesyouthenextelement,whichisasfollows:
>next();"a"
> next();"b">next();"c"
![Page 152: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/152.jpg)
IIFE versus blocksAs ES5 did not provide block scope, a popular pattern to achieve block scope was to useimmediatelyinvokedfunctionexpressions(IIFE),forexample:
(function(){varblock_scoped=0;}());console.log(block_scoped);//referenceerror
WithES6'ssupportforblockscopes,youcansimplyusealetorconstdeclaration.
![Page 153: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/153.jpg)
Arrow functionsJavaScript uses almost all variations of arrows. With ES6, it introduces a new syntax for writingfunctions.WehavealwayswrittenfunctionexpressionsinJavaScript.ItisidiomatictowritecodelikethisinJavaScript(thisexampleisinjQuery):
$("#submit-btn").click(function(event){validateForm();submitMessage();});
ThisisatypicaljQueryeventhandler.Theeventhandlerclick()functionacceptsafunctionasaparameterandwewillsimplycreateaninlineanonymousfunctionexpressionandpassittotheclickfunction.ThisstyleofwritinganonymousfunctionexpressionsisknownasLambdafunctions.Severalotherlanguagessupportthisfeature.Thoughlambdasaremoreorlessstandardinnewlanguages,JavaScriptwasresponsibleforpopularizingtheirusage.However,thelambdasyntaxinJavaScripthasnotbeenveryconcise.ES6arrowfunctionsfillthatgapandprovideaconcisesyntaxtowritefunctions.
Arrowfunctionprovideamoreconcisesyntaxthanthetraditionalfunctionexpressions;forexample,considerthefollowingpieceofcode:
constnum=[1,2,3]const squares = num.map(function(n){
returnn*n;});console.log(squares);//[1,4,9]
Arrowfunctionssyntaxcansimplifythefunctiontothefollowinglineofcode:
constsquares_6=num.map(n=>n*n)
Asyoucansee,thereisnofunctionorreturnkeywordanywhere.Ifyourfunctionhasonlyoneargument,youwillendupwritingthefunctionasidentifer=>expression.
Whenyouneedmultiplearguments,youneedtowraptheargumentlistinbraces:
Noparameters:()=>{...}Oneparameter:a=>{...}Morethanoneparameters:(a,b)=>{...}
Arrowfunctionscanhaveboththestatementblockbodiesaswellasexpressionbodies:
n=>{returnn+n}//statementblockn=>n+n//expression
Bothareequivalentbutthesecondvariationisconciseandpreferred.Arrowfunctionsare
![Page 154: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/154.jpg)
alwaysanonymous.Oneimportantaspectofarrowfunctionsthatwewilldiscussalittlelateristhatarrowfunctionsdonotbindtheirownvaluesofthethiskeyword-thevalueislexicallyderivedfromthesurroundingscope.Aswehavenotyetlookedatthethiskeywordindetail,wewilldeferthediscussiontoalaterpartofthisbook.
![Page 155: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/155.jpg)
Exercises1. Writeafunctionthatconvertsahexadecimalcolor,forexampleblue(#0000FF),intoitsRGBrepresentation,rgb(0,0,255).NameyourfunctiongetRGB()andtestitwiththefollowingcode(hint:treatthestringasanarrayofcharacters):
>vara=getRGB("#00FF00");>a;"rgb(0,255,0)"
2. Whatdoeachofthesefollowinglinesprintintheconsole?
>parseInt(1e1);> parseInt('1e1');
>parseFloat('1e1');>isFinite(0/10);>isFinite(20/0);>isNaN(parseInt(NaN));
3. Whatdoesthisfollowingcodealert?
vara=1;functionf(){functionn(){alert(a);}vara=2;n();}f();
4. Allthesefollowing examplesalert"Boo!".Canyouexplainwhy?Example1:
varf=alert;eval('f("Boo!")');
Example2:
vare;varf=alert;eval('e=f')('Boo!');
Example3:
(function(){returnalert;})()('Boo!');
![Page 156: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/156.jpg)
SummaryYou have now completed the introduction to the fundamental concepts related to functions inJavaScript.Thishaslaidthegroundworkthatwillallowyoutoquicklygrasptheconceptsofobject-orientedJavaScriptandthepatternsusedinmodernJavaScriptprogramming.Sofar,we'vebeenavoidingtheOOfeatures,butasyouhavereachedthispointinthebook,it'sonlygoingtogetmoreinterestingfromhereonin.Let'stakeamomenttoreviewthetopicsdiscussedinthischapter:
Thebasicsofhowtodefineandinvoke(call)afunctionusingeitherafunctiondeclarationsyntaxorafunction expressionFunctionparametersandtheirflexibilityBuilt-infunctions-parseInt(),parseFloat(),isNaN(),isFinite(),andeval()-andthefourfunctionstoencode/decodeaURLThe scope of variables in JavaScript-no curly braces scope, variables have only functionscopeandthescopechainFunctionsasdata-afunctionislikeanyotherpieceofdatathatyouassigntoavariableandalotofinterestingapplicationsfollowfromthis,suchas:
PrivatefunctionsandprivatevariablesAnonymousfunctionsCallbacksImmediatefunctionsFunctionsoverwritingthemselves
ClosuresArrowfunctions
![Page 157: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/157.jpg)
Chapter 4. ObjectsNow that you've mastered JavaScript's primitive data types, arrays, and functions, it's time to staytruetothepromiseofthebooktitleandtalkaboutobjects.
JavaScripthasaneccentrictakeontheclassicalObject-orientedprogramming.Object-orientedprogrammingisoneofthemostpopularprogrammingparadigmsandhasbeenamainstayinmostofprogramminglanguageslikeJavaandC++.TherearewelldefinedideasproposedbyclassicalOOPthatmostoftheselanguagesadopt.JavaScript,however,hasadifferenttakeonit.WewilllookJavaScript'swayofsupportingOOP.
Inthischapter,youwilllearnthefollowingtopics:
HowtocreateanduseobjectsWhataretheconstructorfunctionsWhattypesofbuilt-inJavaScriptobjectsexistandwhattheycandoforyou
![Page 158: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/158.jpg)
From arrays to objectsAs you already know fromChapter 2, Primitive Data Types, Arrays, Loops, and Conditions, anarrayisjustalistofvalues.Eachvaluehasanindex(anumerickey)thatstartsfromzeroandincrementsbyoneforeachvalue.Considerthefollowingexample:
>varmyarr=['red','blue','yellow','purple'];>myarr;["red","blue","yellow","purple"].>myarr[0];"red">myarr[3];"purple"
Ifyouputtheindexesinonecolumnandthevaluesinanother,you'llendupwithatableofkey/valuepairsshownasfollows:
Key Value
0 red
1 blue
2 yellow
3 purple
Anobjectissimilartoanarray,butthedifferenceisthatyoudefinethekeysyourself.You'renotlimitedtousingonlynumericindexes,andyoucanusefriendlierkeyssuchasfirst_name,age,andsoon.
Let'stakealookatasimpleobjectandexamineitsparts:
varhero={breed:'Turtle',occupation:'Ninja'};
Youcanseethat:
ThenameofthevariablethatreferstotheobjectisheroInsteadof[and],whichyouusetodefineanarray,youuse{and}forobjectsYouseparatetheelements(calledproperties)containedintheobjectwithcommasThekey/valuepairsaredividedbycolons,asinkey:value
![Page 159: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/159.jpg)
Thekeys(namesoftheproperties)canoptionallybeplacedinquotationmarks.Forexample,thesekeysareallthesame:
varhero={occupation:1};varhero={"occupation":1};varhero={'occupation':1};
It'srecommendedthatyoudon'tquotethenamesoftheproperties(it'slesstyping),buttherearecaseswhenyoumustusequotes.Someofthecasesarestatedhere:
IfthepropertynameisoneofthereservedwordsinJavaScript(seeAppendixA,ReservedWords)Ifitcontainsspacesorspecialcharacters(anythingotherthanletters,numbers,andthe_and$characters)Ifitstartswithanumber
Inotherwords,ifthenameyouhavechosenforapropertyisnotavalidnameforavariableinJavaScript,thenyouneedtowrapitinquotes.
Havealookatthisbizarre-lookingobject:
var o = {$omething:1,'yesorno':'yes','!@#$%^&*':true};
Thisisavalidobject.Thequotesarerequiredforthesecondandthethirdproperties;otherwise,you'llgetanerror.
Laterinthischapter,you'llseeotherwaystodefineobjectsandarrays,inadditionto[]and{}.However,first,let'sintroducethisbitofterminology-defininganarraywith[]iscalledarrayliteralnotation,anddefininganobjectusingcurlybraces{}iscalledobjectliteralnotation.
![Page 160: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/160.jpg)
Elements,properties,methods,andmembers
Whentalkingaboutarrays,yousaythattheycontainelements.Whentalkingaboutobjects,yousaythattheycontainproperties.Thereisn'tanysignificantdifferenceinJavaScript;it'sjusttheterminologythatpeopleareusedto,probablyfromotherprogramminglanguages.
Apropertyofanobjectcanpointtoafunction,becausefunctionsarejustdata.Propertiesthatpointtofunctionsarealsocalledmethods.Inthefollowingexample,talkisamethod:
vardog={name:'Benji',talk:function(){alert('Woof,woof!');}};
Asyouhaveseeninthepreviouschapter,it'salsopossibletostorefunctionsasarrayelementsandinvokethem,butyou'llnotseemuchcodelikethisinpractice:
>vara=[];>a[0]=function(what){alert(what);};>a[0]('Boo!');
Youcanalsoseepeopleusingthewordmemberstorefertothepropertiesofanobject,mostoftenwhenitdoesn'tmatterifthepropertyisafunctionornot.
![Page 161: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/161.jpg)
Hashesandassociativearrays
Insomeprogramminglanguages,thereisadistinctionbetween:
A regular array, also called an indexed or enumerated array (the keys are numbers)Anassociativearray,alsocalledahashoradictionary(thekeysarestrings)
JavaScriptusesarraystorepresentindexedarraysandobjectstorepresentassociativearrays.IfyouwantahashinJavaScript,youuseanobject.
![Page 162: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/162.jpg)
Accessinganobject'sproperties
Therearetwowaystoaccessthepropertyofanobject:
Using the square bracket notation, for example, hero['occupation']Using the dot notation, for example, hero.occupation
Thedotnotationiseasiertoreadandwrite,butitcannotalwaysbeused.Thesamerulesapplyforquotingpropertynames.Ifthenameofthepropertyisnotavalidvariablename,youcannotusethedotnotation.
Let'staketheheroobjectagain:
varhero={breed:'Turtle',occupation:'Ninja'};
Followingisanexampleforaccessingapropertywiththedotnotation:
>hero.breed;"Turtle"
Let'sseeanexampleforaccessingapropertywiththebracketnotation:
>hero['occupation'];"Ninja"
Considerthefollowingexampleforaccessinganon-existingpropertyreturnsundefined:
>'Haircoloris'+hero.hair_color;"Haircolorisundefined"
Objectscancontainanydata,includingotherobjects:
varbook={name:'Catch-22',published:1961,author:{firstname:'Joseph',lastname:'Heller'}};
Togettothefirstnamepropertyoftheobjectcontainedintheauthorpropertyofthebookobject,youcanusethefollowinglinesofcode:
>book.author.firstname;"Joseph"
![Page 163: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/163.jpg)
Letseeanexampleusingthesquarebracketsnotation:
>book['author']['lastname'];"Heller"
Itworksevenifyoumixboth:
>book.author['lastname'];"Heller">book['author'].lastname;"Heller"
Anothercasewhereyouneedsquarebracketsiswhenthenameofthepropertyyouneedtoaccessisnotknownbeforehand.Duringruntime,it'sdynamicallystoredinavariable:
>varkey='firstname';>book.author[key];"Joseph"
![Page 164: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/164.jpg)
Callinganobject'smethods
Youknowamethodisjustapropertythathappenstobeafunction,soyouaccessmethodsinthesamewayinwhichyouwouldaccessproperties-usingthedotnotationorusingsquarebrackets.Calling(invoking)amethodisthesameascallinganyotherfunction-youjustaddparenthesesafterthemethodname,whicheffectivelysaysExecute!:
>varhero={breed:'Turtle',occupation:'Ninja',say:function(){return'Iam'+hero.occupation;}};>hero.say();"IamNinja"
Ifthereareanyparametersthatyouwanttopasstoamethod,youwouldproceedasyouwouldwithnormalfunctions:
>hero.say('a','b','c');
Asyoucanusethearray-likesquarebracketstoaccessaproperty,itmeansyoucanalsousebracketstoaccessandinvokemethods:
>hero['say']();
This is not a common practice, unless the method name is not known at the time of writing code,butitisinsteaddefinedatruntime:
varmethod='say';hero[method]();
Note
Noquotesunlessyouhavetousethedotnotation toaccessmethodsandproperties,anddon'tquotepropertiesinyourobjectliterals.
![Page 165: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/165.jpg)
Alteringproperties/methods
JavaScriptallowsyoutoalterthepropertiesandmethodsofexistingobjectsatanytime.Thisincludesaddingnewpropertiesordeletingthem.Youcanstartwithablankobjectandaddpropertieslater.Let'sseehowyoucangoaboutdoingthis.
Anobjectwithoutpropertiesisshownasfollows:
>varhero={};
Note
A"blank"object
Inthissection,youstartedwitha"blank"object,varhero={}.Blankisinquotesbecausethisobjectisnotreallyemptyanduseless.Althoughatthisstageithasnopropertiesofitsown,ithasalreadyinheritedsome.
You'lllearnmoreaboutownversusinheritedpropertieslater.So,anobjectinES3isneverreallyblankorempty.InES5though,thereisawaytocreateacompletelyblankobjectthatdoesn'tinheritanything,butlet'snotgetaheadtoomuch.
1. Followingisthecodetoaccessannon-existingproperty:
>typeofhero.breed;"undefined"
2. Addingtwopropertiesandamethod:
>hero.breed='turtle';>hero.name='Leonardo';>hero.sayName=function(){returnhero.name;};
3. Callingthemethod:
>hero.sayName();"Leonardo"
4. Deletingaproperty:
>deletehero.name;true
5. Ifyoucallthemethodagain,itwillnolongerfindthedeletednameproperty:
>hero.sayName();"undefined"
Note
![Page 166: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/166.jpg)
Malleableobjects
Youcanalwayschangeanyobjectatanytime,suchasaddingandremovingpropertiesandchanging their values. However, there are exceptions to this rule. A few properties of some built-inobjectsarenotchangeable(forexample,Math.PI,asyou'llseelater).Also,ES5allowsyoutopreventchangestoobjects.You'lllearnmoreaboutitinAppendixC,Built-inObjects.
![Page 167: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/167.jpg)
Usingthethisvalue
Inthepreviousexample, thesayName()methodusedhero.nametoaccessthenamepropertyoftheheroobject.Whenyou'reinsideamethodthough,thereisanotherwaytoaccesstheobjectthemethodbelongsto.Thismethodisusingthespecialvaluethis:
>varhero={name:'Rafaelo',sayName:function(){returnthis.name;}};>hero.sayName();"Rafaelo"
So,whenyousaythis,you'reactuallysaying-thisobjectorthecurrentobject.
![Page 168: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/168.jpg)
Constructorfunctions
Thereisanotherwaytocreateobjects-usingconstructorfunctions.Let'slookatanexample:
function Hero() {this.occupation='Ninja';}
Inordertocreateanobjectusingthisfunction,youcanusethenewoperatorasfollows:
>varhero=newHero();>hero.occupation;"Ninja"
Abenefitofusingconstructorfunctionsisthattheyacceptparameters,whichcanbeusedwhencreating new objects. Let's modify the constructor to accept one parameter and assign it to thenameproperty:
functionHero(name){this.name=name;this.occupation='Ninja';this.whoAreYou=function(){return"I'm"+this.name+"andI'ma"+this.occupation;};}
Now, you can create different objects using the same constructor:
>varh1=newHero('Michelangelo');>varh2=newHero('Donatello');>h1.whoAreYou();"I'mMichelangeloandI'maNinja">h2.whoAreYou();"I'mDonatelloandI'maNinja"
Note
Byconvention,youshouldcapitalizethefirstletterofyourconstructorfunctionssothatyouhaveavisualcluethattheyarenotintendedtobecalledasregularfunctions.
Ifyoucallafunctionthatisdesignedtobeaconstructorbutyouomitthenewoperator,itisnotanerror.However,itdoesn'tgiveyoutheexpectedresult:
>varh=Hero('Leonardo');>typeofh;"undefined"
![Page 169: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/169.jpg)
Whathappenedhere?Thereisnonewoperator,soanewobjectwasnotcreated.Thefunctionwascalledlikeanyotherfunction,sothevariablehcontainsthevaluethatthefunctionreturns.Thefunctiondoesnotreturnanything(there'snoreturnfunction),soitactuallyreturnsundefined,whichgetsassignedtothevariableh.
Inthiscase,whatdoesthisreferto?Itreferstotheglobalobject.
![Page 170: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/170.jpg)
Theglobalobject
Youhavealreadylearnedabitaboutglobalvariables(andhowyoushouldavoidthem).YoualsoknowthatJavaScriptprogramsruninsideahostenvironment(thebrowser,forexample).Nowthatyouknowaboutobjects,it'stimeforthewholetruth,thehostenvironmentprovidesaglobalobject,andallglobalvariablesareaccessibleaspropertiesoftheglobalobject.
Ifyourhostenvironmentisthewebbrowser,theglobalobjectiscalledwindow.Anotherwaytoaccesstheglobalobject(andthisisalsotrueinmostotherenvironments)istousethiskeywordoutsideaconstructorfunction,forexampleintheglobalprogramcodeoutsideanyfunction.
As an illustration, you can declare a global variable outside any function as follows:
>vara=1;
Then,youcanaccessthisglobalvariableinvariousways:
AsavariableaAsapropertyoftheglobalobject,forexample,window['a']orwindow.aAsapropertyoftheglobalobjectreferredtoasthis:
>vara=1;>window.a;1>this.a;1
Let'sgobacktothecasewhereyoudefineaconstructorfunctionandcallitwithoutthenewoperator.Insuchcases,thisreferstotheglobalobjectandallthepropertiessettothisbecomepropertiesofwindow.
Declaringaconstructorfunctionandcallingitwithoutnewreturns"undefined":
>functionHero(name){this.name=name;}>varh=Hero('Leonardo');
> typeof h;"undefined">typeofh.name;TypeError:Cannotreadproperty'name'ofundefined
AsyouhadthiskeywordinsidethefunctionHero,aglobalvariable(apropertyoftheglobalobject)callednamewascreated:
>name;"Leonardo"
> window.name;
![Page 171: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/171.jpg)
"Leonardo"
Ifyoucallthesameconstructorfunctionusingnew,thenanewobjectisreturned,andthisreferstoit:
>varh2=newHero('Michelangelo');>typeofh2;"object">h2.name;"Michelangelo"
Thebuilt-inglobalfunctionsyouhaveseeninChapter3,Functions,canalsobeinvokedasmethods of the window object. So, the following two calls have the same result:
>parseInt('101dalmatians');101>window.parseInt('101dalmatians')101
![Page 172: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/172.jpg)
Theconstructorproperty
Whenanobjectiscreated,aspecialpropertyisassignedtoitbehindthescenes-theconstructorproperty.Itcontainsareferencetotheconstructorfunctionusedtocreatethisobject.
Continuingfromthepreviousexample:
>h2.constructor;functionHero(name){this.name=name;
}
Astheconstructorpropertycontainsareferencetoafunction,youmightaswellcallthisfunctiontoproduceanewobject.Thefollowingcodeislikesaying,"Idon'tcarehowobjecth2wascreated,butIwantanotheronejustlikeit":
>varh3=newh2.constructor('Rafaello');>h3.name;"Rafaello"
Ifanobjectwascreatedusingtheobjectliteralnotation,itsconstructoris thebuilt-inObject()constructorfunction(thereismoreaboutthislaterinthischapter):
>varo={};>o.constructor;functionObject(){[nativecode]}>typeofo.constructor;"function"
![Page 173: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/173.jpg)
Theinstanceofoperator
Withtheinstanceofoperator,youcantestwhetheranobjectwascreatedwithaspecificconstructorfunction:
>functionHero(){}>varh=newHero();>varo={};>hinstanceofHero;true>hinstanceofObject;true>oinstanceofObject;true
Notethatyoudon'tputparenthesesafterthefunctionname(youdon'tusehinstanceofHero()).Thisisbecauseyou'renotinvokingthisfunction,butjustreferringtoitbyname,aswithanyothervariable.
![Page 174: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/174.jpg)
Functionsthatreturnobjects
Inadditiontousingconstructorfunctionsandthenewoperatortocreateobjects,youcanalsouseanormalfunctiontocreateobjectswithoutthenewoperator.Youcanhaveafunctionthatdoesabitofpreparatoryworkandhasanobjectasareturnvalue.
Forexample,here'sasimplefactory()functionthatproducesobjects:
functionfactory(name){return{name:name};}
Considerthefollowingexampleusingthefactory()function:
>varo=factory('one');>o.name;"one">o.constructor;functionObject(){[nativecode]}
Infact,youcanalsouseconstructorfunctionsandreturnobjectsdifferentfromthiskeyword.Thismeansyoucanmodifythedefaultbehavioroftheconstructorfunction.Let'sseehow.
Here'sthenormalconstructorscenario:
> function C() {this.a=1;}>varc=newC();>c.a;1
However,now,lookatthisscenario:
>functionC2(){this.a=1;return{b:2};}
> var c2 = new C2();>typeofc2.a;"undefined">c2.b;2
Whathappenedhere?Insteadofreturningthethisobject,whichcontainsthepropertya,theconstructorreturnedanotherobjectthatcontainsthepropertyb.Thisispossibleonlyifthereturn
![Page 175: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/175.jpg)
valueisanobject.Otherwise,ifyoutrytoreturnanythingthatisnotanobject,theconstructorwillproceedwithitsusualbehaviorandreturnthis.
Ifyouthinkabouthowobjectsarecreatedinsideconstructorfunctions,youcanimaginethatavariable called this is defined at the top of the function and then returned at the end. Consider thefollowing code:
functionC(){//varthis={};//pseudocode,youcan'tdothisthis.a=1;//returnthis;}
![Page 176: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/176.jpg)
Passingobjects
Whenyouassignanobjecttoadifferentvariable orpassittoafunction,youonlypassareferencetothatobject.Consequently,ifyoumakeachangetothereference,you'reactuallymodifyingtheoriginalobject.
Here'sanexampleofhowyoucanassignanobjecttoanothervariableandthenmakeachangetothecopy.Asaresult,the originalobjectisalsochanged:
>varoriginal={howmany:1};>varmycopy=original;>mycopy.howmany;1>mycopy.howmany=100;100>original.howmany;100
Thesamethingapplieswhenpassingobjectstofunctions:
>varoriginal={howmany:100};>varnullify=function(o){o.howmany=0;};>nullify(original);>original.howmany;0
![Page 177: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/177.jpg)
Comparingobjects
Whenyoucompareobjects,you'llgettrueonlyifyoucomparetworeferencestothesameobject.Ifyoucomparetwodistinctobjectsthathappentohavetheexactsamemethodsandproperties,theresultwouldbefalse.
Let'screatetwoobjectsthatlookthesame:
>varfido={breed:'dog'};>varbenji={breed:'dog'};
Comparingthemreturnsfalse:
>benji===fido;false>benji==fido;
false
Youcancreateanewvariable,mydog,andassignoneoftheobjectstoit.Thisway,thevariablemydogactuallypointstothesameobject:
>varmydog=benji;
In this case, benji is mydog because they are the same object (changing the mydog variable'sproperties will change the benji variable's properties). The comparison returns true:
>mydog===benji;true
Asfidoisadifferentobject,itdoesnotcomparetomydog:
>mydog===fido;false
![Page 178: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/178.jpg)
ObjectsintheWebKitconsole
Beforedivingintothebuilt-inobjectsinJavaScript,let'squicklysayafewwordsaboutworkingwithobjectsintheWebKitconsole.
Afterplayingaroundwiththeexamplesinthischapter,youmighthavealreadynoticedhowobjectsaredisplayedintheconsole.Ifyoucreateanobjectandtypeitsname,you'llgetanarrowpointingtothewordobject.
Theobjectisclickableandexpandstoshowyoualistofallofthepropertiesoftheobject.Ifaproperty is also an object, there is an arrow next to it too, so you can expand this as well. This ishandyasitgivesyouaninsightintoexactlywhatthisobjectcontains.Considerthefollowingexample:
Note
Youcanignore__proto__fornow;there'smore aboutitinthenextchapter.
Loggingusingtheconsole.logmethod
Theconsolealsooffersyouanobjectcalledconsoleandafewmethods,suchasconsole.log()andconsole.error(),whichyoucanusetodisplayanyvalueyouwantintheconsole.
![Page 179: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/179.jpg)
Theconsole.log()methodisconvenientwhenyouwanttoquicklytestsomething,aswellaswhenyouwanttodumpsomeintermediatedebugginginformationinyourrealscripts.Here'showyoucanexperimentwithloops,forexample:
> for (var i = 0; i < 5; i++) {console.log(i);}01234
![Page 180: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/180.jpg)
ES6objectliterals
ES6introducesamuchsuccinctsyntaxwhileusingobjectliterals.ES6offersseveralshorthandsforpropertyinitializationandfunctiondefinitions.ES6shorthandscloselyresembleafamiliarJSONsyntax.Considerthefollowingcodefragment:
leta=1letb=2letval={a:a,b:b}console.log(val)//{"a":1,"b":2}
This is a typical way to assign property values. If the name of the variable and the property key isthesame,ES6allowsyoutouseshorthandsyntax.Theprecedingcodecanbewrittenasfollows:
leta=1letb=2letval={a,b}console.log(val)//{"a":1,"b":2}
Similarsyntaxisavailableformethoddefinitionsaswell.Aswehavediscussed,methodsaresimplypropertiesofanobjectwhosevaluesarefunctions.Considerthefollowingexample:
varobj={prop:1,modifier:function(){
console.log(this.prop);}}
ThereisacompactwaytodefinemethodsinES6.Yousimplydropthefunctionkeywordand:.TheequivalentcodeinES6wouldlooklikethefollowing:
varobj={prop:1,modifier(){console.log(this.prop);}}
ES6allowsyoutocomputethekeyofaproperty.UntilES6,youcouldonlyusefixedpropertynames.Hereisanexample:
varobj={prop:1,modifier:function(){console.log(this.prop);}}obj.prop=2;obj.modifier();//2
![Page 181: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/181.jpg)
Asyoucansee,wearelimitedtousingfixedkey names:propandmodifierinthiscase.However,ES6allowsyoutousecomputedpropertykeys.Itispossibletocreatepropertykeysdynamicallyusingvaluesreturnedbyafunctionaswell:
letvehicle="car"functionvehicleType(){return"truck"}letcar={[vehicle+"_model"]:"Ford"}lettruck={[vehicleType()+"_model"]:"Mercedez"}console.log(car)//{"car_model":"Ford"}console.log(truck)//{"truck_model":"Mercedez"}
Weareusingthevalueofvariablevehicletoconcatenatewithafixedstringtoderivethepropertykeywhilecreatingthecarobject.Inthesecondsnippet,wearecreatingapropertybyconcatenatingafixedstringwiththevaluereturnedbyafunction.Thiswayofcomputingpropertykeysprovidesgreatflexibilitywhilecreatingobjects,andalotofboilerplateandrepetitivecodecanbeeliminated.
Thissyntaxisapplicabletomethoddefinitionaswell:
letobject_type="Vehicle"letobj={["get"+object_type](){return"Ford"}}
![Page 182: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/182.jpg)
Object properties and attributesEach object has a few properties. Each property, in turn, has a key and attributes. A property'sstateisstoredintheseattributes.Allpropertieshavethefollowingattributes:
Enumerable(boolean):Thisindicatesifyoucanenumeratethepropertiesoftheobject.Systempropertiesarenon-enumerablewhileuserpropertiesareenumerable.Unlessthereisastrongreason,thispropertyshouldremainuntouched.Configurable(boolean):Ifthisattributeisfalse,thepropertycannotbedeletedoredited(itcannotchangeanyofitsattribute).
YoucanusetheObject.getOwnPropertyDescriptor()methodtoretrieveanobject'sownproperties:
letobj={age:25}console.log(Object.getOwnPropertyDescriptor(obj,'age'));//{"value":25,"writable":true,"enumerable":true,"configurable":true}
Meanwhile,thepropertycanbedefinedusingtheObject.defineProperty()method:
letobj={age:25}Object.defineProperty(obj,'age',{configurable:false})console.log(Object.getOwnPropertyDescriptor(obj,'age'));//{"value":25,"writable":true,"enumerable":true,"configurable":false}
Thoughyouwouldneverusethesemethods,itisimportanttounderstandobjectpropertiesandattributes.Inthenextsection,wewilldiscusshowsomeoftheobjectmethodsareusedincontextofsomeoftheseproperties.
![Page 183: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/183.jpg)
ES6 object methodsES6 introduces a few static helper methods for objects. Object.assign is a helper method thatreplaces popular mixins to perform a shallow copy of an object.
![Page 184: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/184.jpg)
CopypropertiesusingObject.assign
Thismethodisusedtocopypropertiesofthetargetobjectintothesourceobject.Inotherwords,thismethodmergesthesourceobjectwiththetargetobjectandmodifiesthetargetobject:
leta={}Object.assign(a,{age:25})console.log(a)//{"age":25}
ThefirstparametertoObject.assignisthetargetonwhichsourcepropertiesarecopied.Thesametargetobjectisreturnedtothecaller.Existingpropertiesareoverwritten,whilepropertiesthataren'tpartofthesourceobjectareignored:
leta={age:23,gender:"male"}Object.assign(a,{age:25})//ageoverwritten,butgenderignoredconsole.log(a)//{"age":25,"gender":"male"}
Object.assigncantakemultiplesourceobjects.YoucanwriteObject.assign(target,source1,source2).Hereisanexample:
console.log(Object.assign({a:1,b:2},{a:2},{c:4},{b:3}))//Object{//"a":2,//"b":3,//"c":4//
Inthissnippet,weareassigningpropertiesfrommultiplesourceobjects.Also,noticehowObject.assign()returnsthetargetobject,whichweinturnuseinsideconsole.log().
Onepointtonoteisthatonlyenumerableown(non-inherited)propertiescanbecopiedusingObject.assign().Propertiesfromtheprototypechain(willbediscussedlaterinthischapterwhenwetalkaboutInheritance)arenotconsidered.Ourearlierdiscussionofenumerablepropertieswillhelpyouunderstandthisdistinction.
Inthefollowingexample,wewillcreateanon-enumerablepropertyusingdefineProperty()andvalidatethefactthatObject.assign()ignoresthatproperty:
leta={age:23,gender:"male"}Object.defineProperty(a,'superpowers',{enumberable:false,value:
'ES6'})console.log(
Thepropertydefinedassuperpowershastheenumerableattributesettofalse.Whilecopyingproperties,thispropertyisignored.
![Page 185: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/185.jpg)
ComparevalueswithObject.is
ES6providesaslightlyprecisewayofcomparingvalues.Wehavediscussedthestrictequalityoperator===.However,forNaNand-0and+0,thestrictequalityoperatorbehavesinconsistently.Hereisanexample:
console.log(NaN===NaN)//falseconsole.log(-0===+0)//true//ES6Object.isconsole.log(Object.is(NaN,NaN))//true
console.log(Object.is(-0,+0)) //false
Apartfromthesetwocases,Object.is()cansafelybereplacedwiththe===operator.
![Page 186: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/186.jpg)
DestructuringYou will be working with objects and arrays all the time when you code. JavaScript object andarraynotationsresembletheJSONformat.Youwilldefineobjectsandarrays,andthenretrieveelementsfromthem.ES6givesaconvenientsyntaxthatsignificantlyimprovesthewayweaccessproperties/membersfromobjectsandarrays.Let'sconsideratypicalcodeyouwouldoftenwrite:
varconfig={server: 'localhost',
port:'8080'}varserver=config.server;varport=config.port;
Here,weextractedvaluesofserverandportfromtheconfigobjectandassignedthemtolocalvariables.Prettystraightforward!However,whenthisobjecthasabunchofproperties,someofthemnested,thissimpleoperationcangetverytedioustowrite.
ES6destructuringsyntaxallowsanobjectliteralontheleft-handsideofanassignmentstatement.Inthefollowingexample,wewilldefineanobjectconfigwithafewproperties.Later,wewillusedestructuringtoassigntheobjectconfigtoassignvaluestoindividualpropertiesontheleft-handsideoftheassignmentstatement:
letconfig={server:'localhost',port:'8080',timeout:900,}let{server,port}=configconsole.log(server,port)//"localhost""8080"
Asyoucanseeserverandportarelocalvariablesthatgotassignedpropertiesfromtheconfigobjectbecausethenameofthepropertieswerethesameasthatofthelocalvariables.Youcanalsopickparticularpropertieswhileyouassignthemtolocalvariables.Hereisanexample:
let{timeout:t}=configconsole.log(t)//900
Here,weareonlypickingtimeoutfromtheconfigobjectandassignittoalocalvariablet.
Youcanalsousethedestructuringsyntaxtoassignvaluestoalreadydeclaredvariables.Inthiscase,youhavetoputparenthesesaroundtheassignment:
letconfig={server: 'localhost',
port:'8080',timeout:900,
![Page 187: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/187.jpg)
}letserver='127.0.0.1';letport='80';({server,port}=config)//assignmentsurroundedby()console.log(server,port)//"localhost""8080"
Asthedestructuringexpressionevaluatestotheright-handsideoftheexpression,it'spossibletouseitanywhereyouwouldexpectavalue.Forexample,inafunctioncall,asshownhere:
letconfig={server:'localhost',port:'8080',timeout:900,}
let server='127.0.0.1';letport='80';lettimeout='100';
functionstartServer(configValue){console.log(configValue)}startServer({server,port,timeout}=config)
Ifyouspecifyalocalvariablewithapropertynamethatdoesnotexistintheobject,thelocalvariablegetsanundefinedvalue.However,whileusingvariablesinthe destructuringassignment,youcanoptionallyspecifydefaultvalues:
letconfig={server:'localhost',port:'8080'}let{server,port,timeout=0}=configconsole.log(timeout)
Inthisexample,foranon-existentpropertytimeout,weprovidedadefaultvaluetopreventgetting undefined values assigned to local variables.
Destructuringworksonarraysaswell,andthesyntaxisalsoverysimilar tothatoftheobjects.Wejustneedtoreplaceobjectliteralsyntaxwitharray:literals:
constarr=['a','b']const[x,y]=arrconsole.log(x,y)/"a""b"
Asyoucansee,thisistheexactsamesyntaxwesawearlier.Wedefinedanarrayarrandlaterusedthedestructuringsyntaxtoassignelementsofthatarraytotwolocalvariables,xandy.Here,theassignmenthappensbasedontheorderofelementsinthearray.Asyouonlycareaboutthepositionofelements,youcanskipsomeofthemifyouwantto.Hereisanexample:
constdays=['Thursday','Friday','Saturday','Sunday']
![Page 188: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/188.jpg)
const[,,sat,sun]=daysconsole.log(sat,sun)//"Saturday""Sunday"
Here,weknowthatweneedelementsfrompositions2and3(anarray'sindexstartsfrom0),andhence,weignoreelementsatpositions0and1.Arraydestructuringcaneliminatetheuseofatempvariablewhileswappingvaluesoftwovariables.Considerthefollowing:
leta=1,b=2;[b,a]=[a,b]console.log(a,b)//21
Youcanusetherestoperator(...)toextractremainingelementsandassignthemtoanarray.Therestoperatorcanonlybeusedasthelastoperatorduringdestructuring:
const[x,...y]=['a','b','c'];//x='a';y=['b','c']
![Page 189: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/189.jpg)
Built-in objectsEarlier in this chapter, you came across the Object() constructor function. It's returned when youcreate objects with the object literal notation and access their constructor property. Object()is one of the built-in constructors; there are a few others, and in the rest of this chapter you'll seeallofthem.
Thebuilt-inobjectscanbedividedintothreegroups:
Datawrapperobjects:TheseareObject,Array,Function,Boolean,Number,andString.TheseobjectscorrespondtothedifferentdatatypesinJavaScript.Thereisadatawrapperobjectforeverydifferentvaluereturnedbytypeof(discussedinChapter2,PrimitiveDataTypes,Arrays,Loops,andConditions),withtheexceptionofundefinedandnull.Utilityobjects:TheseareMath,Date,andRegExp,andcancomeinhandy.Errorobjects:TheseincludethegenericErrorobjectaswellasothermorespecificobjectsthatcanhelpyourprogramrecoveritsworkingstatewhensomethingunexpectedhappens.
Onlyahandfulofmethodsofthebuilt-inobjectswillbediscussedinthischapter.Forafullreference,seeAppendixC,Built-inObjects.
Ifyou'reconfusedaboutwhatabuilt-inobjectisandwhatabuilt-inconstructoris,well,theyarethesamething.Inamoment,you'llseehowfunctionsand,therefore,constructorfunctions,arealsoobjects.
![Page 190: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/190.jpg)
Object
ObjectistheparentofallJavaScriptobjects,whichmeansthateveryobjectyoucreateinheritsfromit.Tocreateanewemptyobject,youcanusetheliteralnotationortheObject()constructorfunction.Thefollowingtwolinesare equivalent:
>varo={};>varo=newObject();
Asmentionedbefore,anempty(orblank)objectisnotcompletelyuseless,becauseitalreadycontainsseveralinheritedmethodsandproperties.Inthisbook,emptymeansanobjectlike{}thathasnopropertiesofitsown,otherthantheonesitautomaticallygets.Let'slookatafewofthepropertiesthatevenblankobjectsalreadyhave:
Theo.constructorpropertyreturnsareferencetotheconstructorfunctionTheo.toString()isamethodthatreturnsastringrepresentationoftheobjectTheo.valueOf()returnsasingle-valuerepresentationoftheobject;often,thisistheobjectitself
Let'sseethesemethodsinaction.First,createanobject:
>varo=newObject();
CallingtoString()returnsastringrepresentationoftheobject:
>o.toString();"[objectObject]"
ThetoString()methodwillbecalledinternallybyJavaScriptwhenanobjectisusedinastringcontext.Forexample,alert()worksonlywithstrings,soifyoucallthealert()functionpassinganobject,thetoString()methodwillbecalledbehindthescenes.Thesetwolinesproducethesameresult:
>alert(o);>alert(o.toString());
Anothertypeofstringcontextisthestringconcatenation.Ifyoutrytoconcatenateanobjectwithastring,theobject'stoString()methodiscalledfirst:
>"Anobject:"+o;"Anobject:[objectObject]"
ThevalueOf()methodisanothermethodthatallobjectsprovide.Forthesimpleobjects(whoseconstructorisObject()),thevalueOf()methodreturnstheobjectitself:
>o.valueOf()===o;true
![Page 191: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/191.jpg)
Tosummarize:
Youcancreateobjectseitherwithvaro={};(objectliteralnotation,thepreferredmethod)orwithvaro=newObject();Anyobject,nomatterhowcomplex,inheritsfromtheObjectobjectandtherefore,offersmethodssuchastoString()andpropertiessuchasaconstructor
![Page 192: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/192.jpg)
Array
Array()isabuilt-infunctionthatyoucanuseasaconstructortocreatearrays:
>vara=newArray();
Thisisequivalenttothearrayliteralnotation:
>vara=[];
No matter how the array is created, you can add elements to it as usual:
>a[0]=1;>a[1]=2;>a;[1,2]
WhenusingtheArray()constructor,youcanalsopassvaluesthatwillbeassignedtothenewarray'selements:
>vara=newArray(1,2,3,'four');>a;[1,2,3,"four"]
Anexceptiontothisiswhenyoupassasinglenumbertotheconstructor.Inthiscase,thenumberisconsideredtobethelengthofthearray:
>vara2=newArray(5);>a2;[undefinedx5]
Asarraysarecreatedwithaconstructor,doesthismeanthatarraysareinfactobjects?Yes,andyoucanverifythisusingthetypeofoperator:
>typeof[1,2,3];"object"
Asarraysareobjects,thismeansthattheyinherit thepropertiesandmethodsoftheparentobject:
>vara=[1,2,3,'four'];>a.toString();"1,2,3,four">a.valueOf();[1,2,3,"four"]>a.constructor;functionArray(){[nativecode]}
Arraysareobjects,butofaspecialtypebecause:
Thenamesoftheirpropertiesareautomaticallyassignedusingnumbersstartingfrom0.
![Page 193: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/193.jpg)
Theyhavealengthpropertythatcontainsthenumberofelementsinthearray.Theyhavemorebuilt-inmethodsinadditiontothoseinheritedfromtheparentobject.
Let'sexaminethedifferencesbetweenanarrayandanobject,startingbycreatingtheemptyarraya and the empty object o:
>vara=[],o={};
Arrayobjectshavealengthpropertyautomaticallydefinedforthem,whilenormalobjectsdonot:
>a.length;0>typeofo.length;"undefined"
It'soktoaddbothnumericandnon-numericpropertiestobotharraysandobjects:
> a[0] = 1;>o[0]=1;>a.prop=2;>o.prop=2;
Thelengthpropertyisalwaysuptodatewiththenumberofnumericproperties,whileitignoresthenon-numericones:
>a.length;1
The length property can also be set by you. Setting it to a greater value than the current numberof items in the array makes room for additional elements. If you try to access these non-existingelements,you'llgetthevalueundefined:
>a.length=5;5>a;[1,undefinedx4]
Settingthelengthpropertytoalowervalueremovesthetrailingelements:
>a.length=2;2>a;[1,undefinedx1]
Afewarraymethods
Inadditiontothemethodsinheritedfromtheparentobject,arrayobjectsalsohavespecializedmethodsforworkingwitharrays,suchassort(),join(),andslice(),amongothers(see
![Page 194: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/194.jpg)
AppendixC,Built-inObjects,forthecompletelist).
Let'stakeanarrayandexperimentwithsomeofthesemethods:
>vara=[3,5,1,7,'test'];
Thepush()methodappendsanewelementtotheendofthearray.Thepop()methodremovesthelastelement.Thea.push('new')methodworkslikea[a.length]='new',anda.pop()islikea.length-.
The push() method returns the length of the changed array, whereas pop() returns the removedelement:
>a.push('new');6>a;[3,5,1,7,"test","new"]>a.pop();"new">a;[3,5,1,7,"test"]
Thesort()methodsortsthearrayandreturnsit.Inthenextexample,aftersort,bothaandbpointtothesamearray:
>varb=a.sort();>b;[1,3,5,7,"test"]>a===b;true
Thejoin()methodreturnsastringcontainingthevaluesofalltheelementsinthearraygluedtogetherusingthestringparameterpassedtojoin():
>a.join('isnot');"1isnot3isnot5isnot7isnottest"
Theslice()methodreturnsapieceofthearraywithoutmodifyingthesourcearray.Thefirstparametertoslice()is thestartindex(zero-based),andthesecondistheendindex(bothindicesarezero-based).Startindexisincluded,whiletheendindexisnot.Takealookatthefollowingexample:
>b=a.slice(1,3);[3,5]>b=a.slice(0,1);[1]
> b = a.slice(0, 2);[1,3]
![Page 195: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/195.jpg)
Afteralltheslicing,thesourcearrayisstillthesame:
>a;[1,3,5,7,"test"]
Thesplice()methodmodifiesthesourcearray. Itremovesaslice,returnsit,andoptionallyfillsthegapwithnewelements.Thefirsttwoparametersdefinethestartindexandlength(numberofelements)oftheslicetoberemoved;theotherparameterspassthenewvalues:
>b=a.splice(1,2,100,101,102);[3,5]>a;[1,100,101,102,7,"test"]
Fillingthegapwithnewelementsisoptional,soyoucanskipit:
>a.splice(1,3);[100,101,102]>a;[1,7,"test"]
![Page 196: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/196.jpg)
ES6 array methodsArrays get a bunch of useful methods. Libraries such as lodash and underscore provided featuresmissinginthelanguagesofar.Withthenewhelpermethods,arraycreationandmanipulationismuchmorefunctionalandeasytocode.
![Page 197: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/197.jpg)
Array.from
Convertingarray-likevaluestoarrayshasalwaysbeenabitofachallengeinJavaScript.Peoplehaveemployedseveralhacksandwrittenlibrariestojustletyouhandlearrayseffectively.
ES6introducesaveryhelpfulmethodtoconvertarray-likeobjectsanditerablevaluesintoarrays.Array-likevaluesareobjectsthathavealengthpropertyandindexedelements.Everyfunctionhasanimplicitargumentsvariablethatcontainsalistofallargumentspassedtothefunction.Thisvariableisanarray-likeobject.BeforeES6,theonlywaywecouldconverttheargumentsobjecttoanarraywastoiteratethroughitandcopythevaluesovertoanewarray:
functiontoArray(args){varresult=[];for(vari=0,len=args.length;i<len;i++){result.push(args[i]);}returnresult;}functiondoSomething(){varargs=toArray(arguments);console.log(args)}doSomething("hellow","world")//Array[//"hellow",//"world"
//]
Here,wearecreatinganewarraytocopyoverallelementsoftheargumentsobject.Thisiswastefulandneedsalotofunnecessarycoding.Array.from()isaconcisewaytoconvertarray-likeobjectsintoarrays.WecanconvertthisexampletoamoresuccinctoneusingArray.from():
functiondoSomething(){console.log(Array.from(arguments))}doSomething("hellow","world")//Array[//"hellow",//"world"//]
YoucanprovideyourownmappingschemewhilecallingArray.from()byprovidingamappingfunction.Thisfunctionisinvokedonalltheelementsoftheobjectandconvertsit.Thisisausefulconstructformanycommonusecases,forexample:
functiondoSomething(){console.log(Array.from(arguments,function(elem){returnelem+"mapped";}));
![Page 198: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/198.jpg)
}
Inthisexample,wearedeconstructingtheargumentsobjectusingArray.fromandforeachelementinargumentsobject,wearecallingafunction.
![Page 199: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/199.jpg)
CreatingarraysusingArray.of
CreatinganarrayusingtheArray()constructorcausesabitofaproblem.Theconstructorbehavesdifferentlybasedonthenumberandtypeofarguments.WhenyoupassasinglenumericvaluetotheArray()constructor,anarrayofundefinedelementsiscreated,withthevalueofthelengthassignedtothevalueoftheargument:
letarr=newArray(2)console.log(arr)//[undefined,undefined]console.log(arr.length)//2
Ontheotherhand,ifyou passonlyonenon-numericvalue,itbecomesthe onlyiteminthearray:
letarr=newArray("2")console.log(arr)//["2"]console.log(arr.length)//1
Thisisnotall.Ifyoupassmultiplevalues,theybecomeelementsofthearray:
letarr=newArray(1,"2",{obj:"3"})console.log(arr.length)//3
So,clearly,thereneedstobeabetterwaytocreatearraystoavoidsuchconfusion.ES6introducestheArray.ofmethodthatworksliketheArray()constructor, butguaranteesonestandardbehavior.Array.ofcreatesanarrayfromitsarguments,regardlessoftheirnumberandtype:
letarr=Array.of(1,"2",{obj:"3"})console.log(arr.length)//3
![Page 200: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/200.jpg)
Array.prototypemethods
ES6introducesseveralinterestingmethodsaspartofarrayinstances.Thesemethodshelpwitharrayiterationandsearchingelementsinthearray,bothofwhichareveryfrequentandusefuloperations.
Herearethemethodsusedforiteratingoverarrays:
Array.prototype.entries()
Array.prototype.values()
Array.prorotype.keys()
Allthreemethodsreturnaniterator.ThisiteratorcanbeusedtocreatearraysusingArray.from()andcanbeusedinforloopsforiteration:
letarr=['a','b','c']for(constindexofarr.keys()){console.log(index)//012}for(constvalueofarr.values()){console.log(value)//abc}for(const[index,value]ofarr.entries()){console.log(index,value)}//0"a"//1"b"//2"c"
Similarly,therearenewmethodsforsearchingwithinarrays.Lookingfor anelementinanarrayusuallyinvolvediteratingthroughtheentirelistandcomparingthemwithavalue,astherewerenobuilt-inmethodsforthis.ThoughindexOf()andlastIndexOf()helpedfindasinglevalue,therewasnowaytofindelementsbasedoncomplexconditions.WithES6,thefollowingbuild-inmethodshelpwiththiskeyword.
Array.prototype.find
Array.prototype.findIndex
Boththesemethodsaccepttwoarguments-firstisthecallbackfunction(whichcontainsthepredicatecondition)and thesecondisanoptionalthiskeyword.Thecallbackacceptsthreearguments:thearrayelement,indexofthatelement,andthearray.Thecallbackreturnstrueiftheelementmatchesthepredicate:
letnumbers=[1,2,3,4,5,6,7,8,9,10];console.log(numbers.find(n=>n>5));//6console.log(numbers.findIndex(n=>n>5));//5
![Page 201: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/201.jpg)
Function
Youalreadyknowthatfunctionsareaspecialdatatype.However,itturnsoutthatthere'smoretoitthanthat:functionsare actuallyobjects.Thereisabuilt-inconstructorfunctioncalledFunction()thatallowsforanalternative(butnotnecessarilyrecommended)waytocreateafunction.
Thefollowingexampleshowsthreewaystodefineafunction:
>functionsum(a,b){//functiondeclarationreturna+b;}
> sum(1, 2);3>varsum=function(a,b){//functionexpressionreturna+b;};>sum(1,2)3>varsum=newFunction('a','b','returna+b;');>sum(1,2)3
WhenusingtheFunction()constructor,youpasstheparameternamesfirst(asstrings)andthenthesourcecodeforthebodyofthefunction(againasastring).TheJavaScriptengineneedstoevaluatethesourcecodeyoupassandcreatethenewfunctionforyou.Thissourcecodeevaluationsuffersfromthesamedrawbacksastheeval()function,sodefiningfunctionsusingtheFunction()constructorshouldbeavoidedwhenpossible.
IfyouusetheFunction()constructortocreatefunctionsthathavelotsofparameters,bearinmindthattheparameterscanbepassedasasinglecomma-delimitedlist;so,forexample,thesearethesame:
>varfirst=newFunction('a,b,c,d','returnarguments;');>first(1,2,3,4);[1,2,3,4]>varsecond=newFunction(
'a, b, c','d','returnarguments;');>second(1,2,3,4);[1,2,3,4]>varthird=newFunction('a','b',
![Page 202: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/202.jpg)
'c','d','returnarguments;');>third(1,2,3,4);[1,2,3,4]
Note
DonotusetheFunction()constructor.Aswitheval()andsetTimeout()(discussedlaterinthebook),alwaystrytostayawayfrompassingJavaScriptcodeasastring.
Propertiesoffunctionobjects
Likeanyotherobject,functionshaveaconstructorpropertythatcontainsareferencetotheFunction()constructor function.Thisistruenomatterwhichsyntaxyouusedtocreatethefunction:
>functionmyfunc(a){returna;}
> myfunc.constructor;functionFunction(){[nativecode]}
Functionsalsohavealengthproperty,whichcontainsthenumberofformalparametersthefunctionexpects:
>functionmyfunc(a,b,c){returntrue;}>myfunc.length;3
Usingtheprototypeproperty
Oneofthemostwidelyusedpropertiesoffunctionobjectsistheprototypeproperty.You'llseethispropertydiscussedindetailinthenextchapter,butfornow,let'sjustsay:
TheprototypepropertyofafunctionobjectpointstoanotherobjectItsbenefitsshineonlywhenyouusethisfunctionasaconstructorAllobjectscreatedwiththisfunctionkeepareferencetotheprototypepropertyandcanuseitspropertiesastheirown
Let'slookataquickexampletodemonstratetheprototypeproperty.Takeasimpleobjectthathasapropertynameandamethodsay()method:
varninja={name:'Ninja',say:function(){return'Iama'+this.name;
![Page 203: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/203.jpg)
}};
Whenyoucreateafunction(evenonewithoutabody),youcanverifythat itautomaticallyhasaprototypepropertythatpointstoanewobject:
>functionF(){}>typeofF.prototype;"object"
Itgetsinterestingwhenyoumodifytheprototypeproperty.Youcanaddpropertiestoit,oryoucanreplacethedefaultobjectwithanyotherobject.Let'sassignninjato theprototype:
>F.prototype=ninja;
Now,andhere'swherethemagichappens,usingtheF()functionasaconstructorfunction,youcancreateanewobject,baby_ninja,whichwillhaveaccesstothepropertiesofF.prototype(whichpointstoninja)asifitwereitsown:
>varbaby_ninja=newF();>baby_ninja.name;"Ninja">baby_ninja.say();"IamaNinja"
Therewillbemuchmoreonthistopiclater.Infact,thenextchapterisallabouttheprototypeproperty.
Methodsoffunctionobjects
Functionobjects,beingadescendantofthetopparentobject,getthedefaultmethodssuchastoString().Wheninvokedonafunction,thetoString()methodreturnsthesourcecodeofthefunction:
>functionmyfunc(a,b,c){returna+b+c;}>myfunc.toString();"functionmyfunc(a,b,c){returna+b+c;}"
Ifyoutrytopeekintothesourcecodeofthebuilt-infunctions,you'llgetthe[nativecode]stringinsteadofthebodyofthefunction:
> parseInt.toString();"functionparseInt(){[nativecode]}"
Asyoucansee,youcanusetoString()todifferentiatebetweennativemethodsanddeveloper-
![Page 204: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/204.jpg)
definedones.
Note
Thebehaviorofthefunction'stoString()isenvironmentdependent,anditdiffersamongbrowsersintermsofspacingandnewlines.
Callandapply
Functionobjectshavecall()andapply()methods.Youcanusethemtoinvokeafunctionandpassanyargumentstoit.
Thesemethodsalsoallowyourobjectstoborrowmethodsfromotherobjectsandinvokethemastheirown.Thisisaneasyandpowerfulwaytoreusecode.
Let'ssayyouhaveasome_objobject,whichcontainsthesay()method:
varsome_obj={name:'Ninja',say:function(who){return'Haya'+who+',Iama'+this.name;}};
Youcancallthesay()method,whichinternallyusesthis.nametogainaccesstoitsownnameproperty:
>some_obj.say('Dude');"HayaDude,IamaNinja"
Now,let'screateasimpleobject,my_obj,whichonlyhasanameproperty:
>varmy_obj={name:'Scriptingguru'};
Themy_objlikesthesome_objobject'ssay()methodsomuchthatitwantstoinvokeitasitsown.Thisispossibleusingthecall()methodofthesay()functionobject:
>some_obj.say.call(my_obj,'Dude');"HayaDude,IamaScriptingguru"
Itworked!Butwhathappenedhere?Youinvokedthecall()methodofthesay()functionobjectbypassingtwoparameters-themy_objobjectandtheDudestring.Theresultisthatwhensay()isinvoked,thereferencestothethisvaluethatitcontainspointtomy_obj.Thisway,this.namedoesn'treturnNinja,butScriptingguruinstead.
Ifyouhavemoreparameterstopasswheninvokingthecall()method,youjustkeepaddingthem:
![Page 205: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/205.jpg)
some_obj.someMethod.call(my_obj,'a','b','c');
Ifyoudon'tpassanobjectasafirstparametertocall()oryoupassnull,theglobalobjectisassumed.
Themethodapply()worksthesamewayascall(),butwiththedifferencethatallparametersyouwanttopasstothemethodoftheotherobjectarepassedasanarray.Thefollowingtwolinesareequivalent:
some_obj.someMethod.apply(my_obj,['a','b','c']);some_obj.someMethod.call(my_obj,'a','b','c');
Continuingthepreviousexample,youcanusethefollowinglineofcode:
>some_obj.say.apply(my_obj,['Dude']);"HayaDude,IamaScriptingguru"
Theargumentsobjectrevisited
Inthepreviouschapter,youhaveseenhow,frominsideafunction,youhaveaccesstosomethingcalledarguments,whichcontainsthevaluesofalltheparameterspassedtothefunction:
>functionf(){return arguments;
}>f(1,2,3);[1,2,3]
Theargumentslookslikeanarray,butitisactuallyanarray-likeobject.Itresemblesanarraybecauseitcontainsindexedelementsandalengthproperty.However,thesimilarityendsthere,asargumentsdoesn'tprovideanyofthearraymethods,suchassort()or slice().
However,youcanconvertargumentstoanarrayandbenefitfromallthe arraygoodies.Here'swhatyoucando,practicingyournewly-learnedcall()method:
>functionf(){varargs=[].slice.call(arguments);returnargs.reverse();}
>f(1,2,3,4);[4,3,2,1]
Asyoucansee,youcanborrowslice()using[].sliceorthemoreverboseArray.prototype.slice.
![Page 206: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/206.jpg)
Lexical this in arrow functionsWe discussed ES6 arrow functions and the syntax in detail in the last chapter. However, animportantaspectofarrowfunctionsisthattheybehavedifferentlyfromnormalfunctions.Thedifferenceissubtlebutimportant.Arrowfunctionsdonothavetheirownvalueofthis.Thevalueofthisinanarrowfunctionisinheritedfromtheenclosing(lexical)scope.
Functionshaveaspecialvariablethisthatreferstotheobjectviawhich themethodwasinvoked.Asthevalueofthisisdynamicallygivenbasedonthefunctioninvocation,itissometimescalleddynamicthis.Afunctionisexecutedintwoscopes-lexicalanddynamic.Alexicalscopeisascopethatsurroundsthefunctionscope,andthedynamicscopeisthescopethatcalledthefunction(usuallyanobject)
InJavaScript,traditionalfunctionsplayseveralroles.Theyarenon-methodfunctions(akasubroutinesorfunctions),methods(partofanobject),andconstructors.Whenfunctionsdothedutyofasubroutine,thereisasmallproblemduetodynamicthis.Assubroutinesarenotcalledonanobject,thevalueofthisisundefinedinastrictmodeandsettothe globalscopeotherwise.Thismakeswritingcallbacksdifficult.Considerthefollowingexample:
vargreeter={default:"Hello",greet:function(names){names.forEach(function(name){console.log(this.default+name);//Cannotreadproperty'default'ofundefined})}}console.log(greeter.greet(['world','heaven']))
WearepassingasubroutinetotheforEach()functiononthenamesarray.Thissubroutinehasanundefinedvalueofthis,andunfortunately,itdoesnothaveaccesstothisoftheoutermethodgreet.Clearly,thissubroutineneedsalexicalthis,derivethisfromthesurroundingscopeofthegreetmethod.Traditionally,tofixthislimitation,weassignthelexicalthisintoavariable,whichisthenaccessibletothesubroutineviaclosure.
Wecanfixtheearlierexampleasfollows:
vargreeter={default:"Hello",greet:function(names){letthat=thisnames.forEach(function(name){console.log(that.default+name);})}
![Page 207: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/207.jpg)
}console.log(greeter.greet(['world','heaven']))
Thisisareasonablehacktosimulatelexicalthis.However,theproblemwithsuchhacksisthatitcreatestoomuchnoiseforthepersonwritingorreviewingthiscode.First,youhavetounderstandthequirkofthebehaviorofthis.Evenifyouunderstandthisbehaviorwell,youwillneedtocontinuouslyremainonthelookoutforsuchhacksinyourcode.
Arrowfunctionshavelexicalthisanddonotrequiresuchahack.Theyaremoresuitedassubroutinesbecauseofthis.Wecancoverttheprecedingexampletouse lexicalthisusingthearrowfunction:
vargreeter={default:"Hello",greet:function(names){
names.forEach(name=> {console.log(this.default+name);//lexical'this'availableforthissubroutine})}}console.log(greeter.greet(['world','heaven']))
![Page 208: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/208.jpg)
Inferringobjecttypes
Youcanseethatyouhavethisarray-likeargumentsobjectlookingsomuchlikeanarrayobject.Howcanyoureliablytellthedifferencebetween thetwo?Additionally,typeofreturnsanobjectwhenusedwitharrays.Therefore,howcanyoutellthedifferencebetweenanobjectandanarray?
ThesilverbulletistheObjectobject'stoString()method.Itgivesyoutheinternalclassnameusedtocreateagivenobject:
>Object.prototype.toString.call({});"[objectObject]">Object.prototype.toString.call([]);"[objectArray]"
YouhavetocalltheoriginaltoString()methodasdefinedintheprototypeoftheObjectconstructor.Otherwise,ifyoucalltheArrayfunction'stoString(),itwillgiveyouadifferentresult,asit'sbeenoverriddenforthespecificpurposesofthearrayobjects:
>[1,2,3].toString();"1,2,3"
Theprecedingcodeissameas:
>Array.prototype.toString.call([1,2,3]);"1,2,3"
Let'shavesomemorefunwithtoString().Makeahandyreferencetosavetyping:
> var toStr = Object.prototype.toString;
Thefollowingexampleshowshowwecandifferentiatebetweenanarray andthearray-likeobjectarguments:
>(function(){returntoStr.call(arguments);}());"[objectArguments]"
YoucaneveninspectDOMelements:
>toStr.call(document.body);"[objectHTMLBodyElement]"
![Page 209: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/209.jpg)
Boolean
Yourjourneythroughthe built-inobjectsinJavaScriptcontinues,andthenextthreearefairlystraightforward.TheyareBoolean,number,andstring.Theymerelywraptheprimitivedatatypes.
YoualreadyknowalotaboutBooleansfromChapter2,PrimitiveDataTypes,Arrays,Loops,andConditions.Now,let'smeettheBoolean()constructor:
>varb=newBoolean();
It'simportanttonotethatthiscreatesanewobject,b,andnotaprimitiveBooleanvalue.Togettheprimitivevalue,youcancallthevalueOf()method(inheritedfromObjectclassandcustomized):
>varb=newBoolean();>typeofb;"object">typeofb.valueOf();"boolean">b.valueOf();false
Overall,objectscreatedwiththeBoolean()constructorarenottoouseful,astheydon'tprovideanymethodsorpropertiesotherthantheinheritedones.
TheBoolean()function,whencalledasanormalfunctionwithoutnew,convertsnon-BooleanstoBooleans(whichislikeusingadoublenegation!!value):
>Boolean("test");true>Boolean("");false>Boolean({});true
Apartfromthesixfalsevalues,everythingelseistrueinJavaScript,includingallobjects.ThisalsomeansthatallBooleanobjectscreatedwithnewBoolean()arealsotrue,astheyareobjects:
>Boolean(newBoolean(false));true
Thiscanbeconfusing,andsinceBooleanobjectsdon'tofferanyspecialmethods,it'sbesttojuststickwithregularprimitiveBooleanvalues.
![Page 210: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/210.jpg)
Number
SimilartoBoolean(),theNumber()functioncanbeusedas:
Aconstructorfunction(withnew)tocreateobjects.Anormalfunctioninordertotrytoconvertanyvaluetoanumber.Thisissimilartotheuseof parseInt() or parseFloat():
>varn=Number('12.12');>n;12.12>typeofn;"number">varn=newNumber('12.12');>typeofn;"object"
Asfunctionsareobjects,theycanalsohaveproperties.TheNumber()functionhasconstantbuilt-inpropertiesthatyoucannotmodify:
>Number.MAX_VALUE;1.7976931348623157e+308>Number.MIN_VALUE;5e-324>Number.POSITIVE_INFINITY;Infinity>Number.NEGATIVE_INFINITY;-Infinity>Number.NaN;NaN
Thenumberobjectsprovidethreemethods-toFixed(),toPrecision(),andtoExponential()(seeAppendixC,Built-inObjects,formoredetails):
>varn=newNumber(123.456);>n.toFixed(1);"123.5"
NotethatyoucanusethesemethodswithoutexplicitlycreatingaNumberobjectfirst.Insuchcases,theNumberobjectiscreated(anddestroyed)foryoubehindthescenes:
>(12345).toExponential();"1.2345e+4"
Likeallobjects,theNumberobjectalsoprovidethetoString()method.WhenusedwithNumberobject,thismethodacceptsanoptionalradixparameter(10beingthedefault):
>varn=newNumber(255);>n.toString();"255"
![Page 211: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/211.jpg)
>n.toString(10);"255">n.toString(16);"ff">(3).toString(2);"11">(3).toString(10);"3"
![Page 212: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/212.jpg)
String
YoucanusetheString()constructorfunctiontocreatestringobjects.Stringobjectsprovideconvenientmethodsfortextmanipulation.
Here'sanexamplethatshowsthedifferencebetweenaStringobjectandaprimitivestringdatatype:
>varprimitive='Hello';>typeofprimitive;"string">varobj=newString('world');>typeofobj;"object"
AStringobjectissimilartoanarrayofcharacters.Stringobjectshaveanindexedpropertyforeachcharacter(introducedinES5,butlongsupportedinmanybrowsers,exceptoldIEs),andtheyalsohavealengthproperty.
>obj[0];"w">obj[4];
"d">obj.length;5
ToextracttheprimitivevaluefromtheStringobject,youcanusethevalueOf()ortoString()methodinheritedfromObject.You'llprobablyneverneedtodothis,astoString()iscalledbehindthescenesifyouuseanobjectinaprimitivestringcontext:
>obj.valueOf();"world">obj.toString();
"world">obj+"";"world"
Theprimitivestringsarenotobjects,sotheydon'thaveanymethodsorproperties.However,JavaScriptalsooffersyouthesyntaxtotreatprimitivestringsasobjects(justlikeyoualreadysawwithprimitivenumbers).
Inthefollowingexample,Stringobjectsarebeingcreated(andthendestroyed)behindthesceneseverytimeyoutreataprimitivestringasifitwereanobject:
>"potato".length;6
> "tomato"[0];"t"
![Page 213: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/213.jpg)
>"potatoes"["potatoes".length-1];"s"
HereisonefinalexampletoillustratethedifferencebetweenaprimitivestringandaStringobject.Inthisexample,weareconvertingthemtoBoolean.Theemptystringisafalsyvalue,butanystringobjectistruthy(becauseallobjectsaretruthy):
>Boolean("");false>Boolean(newString(""));true
Similar to Number() and Boolean(), if you use the String() function without new, it convertsthe parameter to a primitive:
>String(1);"1"
IfyoupassanobjecttoString(),thisobject'stoString()methodwillbecalledfirst:
>String({p:1});"[objectObject]">String([1,2,3]);"1,2,3">String([1,2,3])===[1,2,3].toString();true
Afewmethodsofstringobjects
Let'sexperimentwithafewofthemethodsyoucancallonstringobjects(seeAppendixC,Built-inObjects,forthecompletelist).
Startoffbycreatingastringobject:
>vars=newString("Couchpotato");
ThetoUpperCase()andtoLowerCase()methodstransformthecapitalizationofthestring:
>s.toUpperCase();"COUCHPOTATO">s.toLowerCase();"couchpotato"
ThecharAt()methodtellsyouthecharacterfoundatthepositionyouspecify,whichisthesameasusingsquarebrackets(treatingastringasanarrayofcharacters):
>s.charAt(0);"C">s[0];"C"
![Page 214: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/214.jpg)
Ifyoupassanon-existentpositiontocharAt(),yougetanemptystring:
>s.charAt(101);""
TheindexOf()methodallowsyoutosearchwithinastring.Ifthereisamatch,themethodreturnsthepositionatwhichthefirstmatchisfound.Thepositioncountstartsat0,sothesecondcharacterinCouchisoatposition1:
>s.indexOf('o');1
Youcanoptionallyspecifywhere(atwhatposition)tostartthesearch.Thefollowingfindsthesecondo,becauseindexOf()isinstructedtostartthesearchatposition2:
>s.indexOf('o',2);7
ThelastIndexOf()startsthesearchfromtheendofthestring(butthepositionofthematchisstillcountedfromthebeginning):
>s.lastIndexOf('o');11
You can search , not only for characters, but also for strings, and the search is case sensitive:
>s.indexOf('Couch');0
Ifthereisnomatch,thefunctionreturnsposition-1:
>s.indexOf('couch');-1
Foracase-insensitivesearch,youcantransformthestringtolowercasefirstandthensearch:
>s.toLowerCase().indexOf('couch'.toLowerCase());0
Ifyouget0,thismeansthatthematchingpartofthestringstartsatposition0.Thiscancauseconfusionwhenyoucheckwithif,becauseifconvertstheposition0toaBooleanfalsevalue.So,whilethisissyntacticallycorrect,itislogicallywrong:
if(s.indexOf('Couch')){...}
TheproperwaytocheckwhetherastringcontainsanotherstringistocomparetheresultofindexOf()tothenumber-1:
if(s.indexOf('Couch')!==-1){...}
![Page 215: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/215.jpg)
Theslice()andsubstring()returnapieceofthestringwhenyouspecifythestartandendpositions:
>s.slice(1,5);"ouch">s.substring(1,5);"ouch"
Notethatthesecondparameteryoupassistheendposition,notthelength ofthepiece.Thedifferencebetweenthesetwomethodsishowtheytreatnegativearguments.substring()treatsthemaszeros,whileslice()addsthemtothelengthofthestring.So,ifyoupassparameters(1,-1)tobothmethods,it'sthesameassubstring(1,0)andslice(1,s.length-1):
>s.slice(1,-1);"ouchpotat">s.substring(1,-1);"C"
There'salsothenon-standardmethodsubstr(),butyoushouldtrytoavoiditinfavorofsubstring().
Thesplit()methodcreatesanarrayfromthestringusinganotherstringthatyoupassasaseparator:
>s.split("");["Couch","potato"]
Thesplit()methodistheoppositeofthejoin()method,whichcreatesastringfromanarray:
>s.split('').join('');"Couchpotato"
Theconcat()gluesstringstogether,inthesamewayinwhichthe+operatordoesforprimitivestrings:
>s.concat("es");"Couch potatoes"
Notethatwhilesomeoftheprecedingmethodsdiscussedreturnnewprimitivestrings,noneofthemmodifythesourcestring.Afterallthemethodcallslistedpreviously,theinitialstringisstillthesame:
>s.valueOf();"Couchpotato"
YouhaveseenhowtouseindexOf()andlastIndexOf()tosearchwithinstrings,buttherearemorepowerfulmethods(search(),match(),andreplace())thattakeregularexpressionsasparameters.You'llseetheselaterintheRegExp()constructorfunction.
![Page 216: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/216.jpg)
Atthispoint,you'redonewithallofthedatawrapperobjects,solet'smoveontotheutilityobjectsMath,Date,andRegExp.
![Page 217: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/217.jpg)
Math
Mathisalittledifferentfromtheotherbuilt-inglobalobjectsyouhaveseenpreviously.It'snotafunction,and,therefore,cannotbeusedwithnewtocreateobjects.Mathisabuilt-inglobalobjectthatprovidesanumberofmethodsandpropertiesformathematicaloperations.
TheMathobject'spropertiesareconstants,soyoucan'tchangetheirvalues.Theirnamesareallinuppercasetoemphasizethedifferencebetweenthemandanormalproperty(similartotheconstantpropertiesoftheNumber()constructor).Let'sseeafewoftheseconstantproperties:
TheconstantPI:
>Math.PI;3.141592653589793
Squarerootof2:
>Math.SQRT2;1.4142135623730951
Euler'sconstant:
>Math.E;2.718281828459045
Naturallogarithmof2:
>Math.LN2;0.6931471805599453
Naturallogarithmof10:
>Math.LN10;2.302585092994046
Now,youknowhowtoimpressyourfriendsthenexttimethey(forwhateverreason)startwondering,"Whatwasthevalueofe?Ican'tremember."JusttypeMath.Eintheconsoleandyouhavetheanswer.
Let'stakealookatsome ofthemethodstheMathobjectprovides(thefulllistisinAppendixC,Built-inObjects).
Generatingrandomnumbers:
>Math.random();0.3649461670235814
Therandom()functionreturnsanumberbetween0and1,soifyouwantanumberbetween,let'ssay,0and100,youcanusethefollowinglineofcode:
![Page 218: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/218.jpg)
>100*Math.random();
Fornumbersbetweenanytwovalues,usetheformula((max-min)*Math.random())+min.Forexample,arandomnumberbetween2and10canbeobtainedusingtheformulaasfollows:
>8*Math.random()+2;9.175650496668485
Ifyouonlyneedaninteger,youcanuseoneofthefollowingroundingmethods:
floor()torounddownceil()toroundupround()toroundtothenearest
Forexample,togeteither0or1,youcanusethefollowinglineofcode:
>Math.round(Math.random());
Ifyouneedthelowestorthehighestamongasetofnumbers,youhavethemin()andmax()methods.So,ifyouhave aformonapagethatasksforavalidmonth,you canmakesurethatyoualwaysworkwithsanedata(avaluebetween1and12):
>Math.min(Math.max(1,input),12);
TheMathobjectalsoprovidestheabilitytoperformmathematicaloperationsforwhichyoudon'thaveadesignatedoperator.Thismeansthatyoucanraisetoapowerusingpow(),findthesquarerootusingsqrt(),andperformallthetrigonometricoperations-sin(),cos(),atan(),andsoon.
Forexample,tocalculate2tothepowerof8,youcanusethefollowinglineofcode:
>Math.pow(2,8);256
To calculate the square root of 9, you can use the following line of code:
>Math.sqrt(9);3
![Page 219: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/219.jpg)
Date
Date()isaconstructorfunctionthatcreatesdate objects.Youcancreateanewobjectbypassing:
Nothing (defaults to today's date)Adate-likestringSeparatevaluesfor day,month,time,andsoonAtimestamp
Hereisanobjectinstantiatedwithtoday'sdate/time(usingthebrowser'stimezone):
> new Date();WedFeb27201323:49:28GMT-0800(PST)
TheconsoledisplaystheresultofthetoString()methodcalledontheDateobject,soyougetthislongstringWedFeb27201323:49:28GMT-0800(PST)asarepresentationofthedateobject.
HereareafewexamplesofusingstringstoinitializeaDateobject.Notehowmanydifferentformatsyoucanusetospecifythedate:
>newDate('20151112');ThuNov12201500:00:00GMT-0800(PST)>newDate('112016');FriJan01201600:00:00GMT-0800(PST)>newDate('1mar20165:30');TueMar01201605:30:00GMT-0800(PST)
TheDateconstructorcanfigureoutadatefromdifferentstrings,butthisisnotreallyareliablewayofdefiningaprecisedate,forexample,whenpassinguserinputtotheconstructor.AbetterwayistopassnumericvaluestotheDate()constructorrepresenting:
YearMonth-0(January)to11(December)Day-1to31Hour-0to23Minutes-0to59Seconds-0to59Milliseconds-0to999
Let'slookatsomeexamples.
Passingalltheparametersbywritingthefollowinglineofcode:
>newDate(2015,0,1,17,05,03,120);TueJan01201517:05:03GMT-0800(PST)
![Page 220: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/220.jpg)
Passingdateandhourbywritingthefollowinglineofcode:
>newDate(2015,0,1,17);TueJan01201517:00:00GMT-0800(PST)
Watchoutforthefactthatthemonthstartsfrom0,so1isFebruary:
>newDate(2016,1,28);SunFeb28201600:00:00GMT-0800(PST)
Ifyoupassavaluegreaterthantheoneallowed,yourdateoverflowsforward.Asthere'snoFebruary30in2016,thismeansithastobeMarch1(2016isaleapyear):
>newDate(2016,1,29);MonFeb29201600:00:00GMT-0800(PST)>newDate(2016,1,30);TueMar01201600:00:00GMT-0800(PST)
Similarly,December32becomesJanuary1ofthenextyear:
>newDate(2012,11,31);MonDec31201200:00:00GMT-0800(PST)>newDate(2012,11,32);TueJan01201300:00:00GMT-0800(PST)
Finally,adateobjectcanbeinitializedwithatimestamp(thenumberofmillisecondssincetheUNIXepoch,where0millisecondsisJanuary1,1970):
>newDate(1357027200000);TueJan01201300:00:00GMT-0800(PST)
IfyoucallDate()withoutnew,yougetastringrepresentingthecurrentdate,whetherornotyoupassanyparameters.Thefollowingexamplegivesthecurrenttime(currentwhenthisexamplewasrun):
>Date();WedFeb27201323:51:46GMT-0800(PST)>Date(1,2,3,"itdoesn'tmatter");WedFeb27201323:51:52GMT-0800(PST)>typeofDate();"string">typeofnewDate();"object"
Methodstoworkwithdateobjects
Onceyou'vecreatedadateobject,therearelotsofmethodsyoucancallonthatobject.Mostofthemethodscanbedividedintoset*()andget*()methods,forexample,getMonth(),setMonth(),getHours(),setHours(),andsoon.Let'sseesomeexamples.
![Page 221: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/221.jpg)
Creatingadateobjectbywritingthefollowingcode:
>vard=newDate(2015,1,1);>d.toString();SunFeb01201500:00:00GMT-0800(PST)
SettingthemonthtoMarch(monthsstartfrom0):
>d.setMonth(2);1425196800000>d.toString();SunMar01201500:00:00GMT-0800(PST)
Gettingthemonthbywritingthefollowingcode:
>d.getMonth();2
Inadditiontoallthemethodsofdateobjects,therearealsotwomethods(plusonemoreaddedinES5)thatarepropertiesoftheDate()function/object.Thesedonotneed adateobject;theyworkjustliketheMathobjectmethods.Inclass-basedlanguages,suchmethodswouldbecalledstaticbecausetheydon'trequireaninstance.
TheDate.parse()methodtakesastringandreturnsatimestamp:
>Date.parse('Jan11,2018');1515657600000
The Date.UTC() method takes all the parameters for year, month, day, and so on, and produces atimestamp inUniversal Time (UT):
>Date.UTC(2018,0,11);1515628800000
AsthenewDate()constructorcanaccepttimestamps,youcanpasstheresultofDate.UTC()toit.Usingthefollowingexample,youcanseehowUTC()workswithUniversalTime,whilenewDate()workswithlocaltime:
>newDate(Date.UTC(2018,0,11));WedJan10201816:00:00GMT-0800(PST)>newDate(2018,0,11);ThuJan11201800:00:00GMT-0800(PST)
TheES5additiontotheDateconstructoristhenow()method,whichreturnsthecurrenttimestamp.ItprovidesamoreconvenientwaytogetthetimestampinsteadofusingthegetTime()methodonaDateobjectasyouwouldinES3:
>Date.now();1362038353044
![Page 222: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/222.jpg)
>Date.now()===newDate().getTime();true
Youcanthinkoftheinternalrepresentationofthe datebeinganintegertimestampandallothermethodsbeingsugarontopofit.So,itmakessensethatvalueOf()isatimestamp:
>newDate().valueOf();1362418306432
Also,datescasttointegerswiththe+operator:
>+newDate();1362418318311
Calculatingbirthdays
Let'slookatonefinalexampleofworkingwithDateobjects.Iwascuriousaboutwhichdaymybirthdayfallsonin2016:
>vard=newDate(2016,5,20);>d.getDay();1
Startingthecountfrom0 (Sunday),1meansMonday.Isthatso?
>d.toDateString();"MonJun202016"
ok,goodtoknow,butMondayisnotnecessarilythebestdayforaparty.So,howaboutaloopthatshowshowmanytimesJune20isaFridayfromyear2016toyear3016,orbetteryet,let'sseethedistributionofallthedaysoftheweek.Afterall,withalltheprogressinDNAhacking,we'reallgoingtobealiveandkickingin3016.
First,let'sinitializeanarraywithsevenelements,oneforeachdayoftheweek.Thesewillbeusedascounters.Then,asaloopgoesupto3016,let'sincrementthecounters:
varstats=[0,0,0,0,0,0,0];
Hereistheloop:
for(vari=2016;i<3016;i++){stats[newDate(i,5,20).getDay()]++;}
Hereistheresult:
>stats;[140, 146, 140, 145, 142, 142, 145]
142Fridaysand145Saturdays.Woo-hoo!
![Page 223: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/223.jpg)
RegExp
Regularexpressionsprovideapowerfulwaytosearchandmanipulatetext.Differentlanguageshavedifferentimplementations(thinkdialects)oftheregularexpressionsyntax.JavaScriptusesthePerl5syntax.
Insteadofsayingregular expression,peopleoftenshortenittoregexorregexp.
Aregularexpressionconsistsof:
ApatternyouusetomatchtextZeroormoremodifiers(alsocalledflags)thatprovidemoreinstructionsonhowthepatternshouldbeused
Thepatterncanbeassimpleasliteraltexttobematchedverbatim,butthat'srare,andinsuchcasesyou'rebetteroffusingindexOf().Mostofthetime,thepatternismorecomplexandcouldbedifficulttounderstand.Masteringregularexpressions'patternsisalargetopic,whichwon'tbediscussedinfulldetailhere.Instead,you'llseewhatJavaScriptprovidesintermsofsyntax,objects, and methods in order to support the use of regular expressions. You can also refer toAppendixD,RegularExpressions,tohelpyouwhenyou'rewritingpatterns.
JavaScriptprovidestheRegExp()constructor,whichallowsyoutocreateregularexpressionobjects:
>varre=newRegExp("j.*t");
Thereisalsothemoreconvenientregexpliteralnotation:
>varre=/j.*t/;
Intheprecedingexample,j.*tistheregularexpressionpattern.Itmeans"matchesanystringthatstartswithj,endswitht,andhaszeroormorecharactersinbetween".Theasterisk(*)means"zeroormoreofthepreceding,"andthedot(.)means"anycharacter".ThepatternneedstobequotedwhenpassedtoaRegExp()constructor.
PropertiesofRegExpobjects
Regularexpressionobjectshavethefollowingproperties:
global:Ifthispropertyisfalse,whichisthedefault,thesearchstopswhenthefirstmatchisfound.Setthistotrueifyouwantallmatches.ignoreCase:Whenthematchiscaseinsensitive,thispropertydefaultstofalse(meaningthedefaultisacase-sensitivematch).multiline:Searchmatchesthatmayspanovermorethanonelinedefaulttofalse.lastIndex:Thepositionatwhichtostartthesearch;thisdefaultsto0.
![Page 224: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/224.jpg)
source:ThiscontainstheRegExppattern.
Noneoftheseproperties,exceptforlastIndex,canbechangedoncetheobjecthasbeencreated.
Thefirstthreeitemsintheprecedinglistrepresenttheregexmodifiers.Ifyoucreatearegexobjectusingtheconstructor,youcanpassanycombinationofthefollowingcharactersasasecondparameter:
gforglobaliforignoreCasemformultiline
Theseletterscanbeinanyorder.Ifaletterispassed,thecorrespondingmodifierpropertyissettotrue.Inthefollowingexample,allmodifiersaresettotrue:
>varre=newRegExp('j.*t','gmi');
Let'sverify:
>re.global;true
Once set, the modifier cannot be changed:
>re.global=false;>re.global;true
Tosetanymodifiersusingtheregexliteral,youaddthemaftertheclosingslash:
>varre=/j.*t/ig;>re.global;true
MethodsofRegExpobjects
Regexobjectsprovidetwomethodsyoucanusetofindmatches-test()andexec().Theybothacceptastringparameter.Thetest()methodreturnsaBoolean(truewhenthere'samatch,falseotherwise),whileexec()returnsanarrayofmatchedstrings.Obviously,exec()isdoingmorework,sousetest()onlyifyoureallyneedtodosomethingwiththematches.Peopleoftenuseregularexpressionstovalidatedata.Inthiscase,test()shouldbeenough.
Inthefollowingexample,thereisnomatchbecauseofthecapitalJ:
>/j.*t/.test("Javascript");false
![Page 225: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/225.jpg)
Acase-insensitivetestgivesapositiveresult:
>/j.*t/i.test("Javascript");true
Thesametestusingexec()returnsanarray,andyoucanaccessthefirstelementasshownhere:
>/j.*t/i.exec("Javascript")[0];"Javascript"
Stringmethodsthatacceptregularexpressionsasarguments
Previouslyinthischapter,youlearnedaboutstringobjectsandhowyoucanusetheindexOf()andlastIndexOf()methodstosearchwithintext.Usingthesemethods,youcanonlyspecifyliteralstringpatternstosearch.Amorepowerfulsolutionwouldbetouseregularexpressionstofindtext.Stringobjectsofferyouthisability.
Stringobjectsprovidethefollowingmethodsthatacceptregularexpressionobjectsasparameters:
match():Returnsanarrayofmatchessearch():Returnsthepositionofthefirstmatchreplace():Allowsyoutosubstitutematchedtextwithanotherstringsplit():Acceptsaregexpwhensplittingastringintoarrayelements
search()andmatch()
Let'slookatsomeexamplesofusingthesearch()andmatch()methods. First,youcreateastringobject:
>vars=newString('HelloJavaScriptWorld');
Usingmatch(),yougetanarraycontainingonlythefirstmatch:
>s.match(/a/);["a"]
Usingthegmodifier,youperformaglobalsearch,sotheresultarraycontainstwoelements:
>s.match(/a/g);["a","a"]
Acase-insensitivematchisasfollows:
>s.match(/j.*a/i);["Java"]
Thesearch()methodgivesyouthepositionofthematchingstring:
>s.search(/j.*a/i);
![Page 226: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/226.jpg)
5
replace()
Thereplace()methodallowsyoutoreplacethematchedtextwithsomeotherstring.Thefollowingexampleremovesallcapitalletters(itreplacesthemwithblankstrings):
>s.replace(/[A-Z]/g,'');"elloavacriptorld"
Ifyouomitthegmodifier,you'reonlygoingtoreplacethefirstmatch:
>s.replace(/[A-Z]/,'');"elloJavaScriptWorld"
Whenamatchisfound,ifyouwanttoincludethematchedtextinthereplacementstring,youcanaccessitusing$&.Here'showtoaddanunderscorebeforethematchwhilekeepingthematch:
>s.replace(/[A-Z]/g,"_$&");"_Hello_Java_Script_World"
Whentheregularexpressioncontainsgroups(denotedbyparentheses),thematchesofeachgroupareavailableas$1forthefirstgroup,$2thesecond,andsoon:
>s.replace(/([A-Z])/g,"_$1");"_Hello_Java_Script_World"
Imagineyouhavearegistrationformonyourwebpagethatasksforane-mailaddress,username,and password. The user enters their e-mail IDs, and then, your JavaScript kicks in and suggeststheusername,takingitfromthee-mailaddress:
>varemail="[email protected]";>varusername=email.replace(/(.*)@.*/,"$1");>username;"stoyan"
Replacecallbacks
Whenspecifyingthereplacement,youcanalsopassafunctionthatreturnsastring.Thisgivesyoutheabilitytoimplementanyspeciallogicyoumayneedbeforespecifying thereplacements:
>functionreplaceCallback(match){return"_"+match.toLowerCase();}
>s.replace(/[A-Z]/g,replaceCallback);"_hello_java_script_world"
Thecallbackfunctionreceivesanumberofparameters(thepreviousexampleignoresallbutthefirstone):
![Page 227: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/227.jpg)
ThefirstparameteristhematchThelastisthestringbeingsearchedTheonebeforelastisthepositionofthematchTherestoftheparameterscontainanystringsmatchedbyanygroupsinyourregexpattern
Let's test this. First, let's create a variable to store the entire arguments array passed to thecallbackfunction:
>varglob;
Next,definearegularexpressionthathasthreegroupsandmatchese-mailaddressesintheformatsomething@something.something:
>varre=/(.*)@(.*)\.(.*)/;
Finally,let'sdefineacallbackfunctionthatstorestheargumentsinglobandthenreturnsthereplacement:
varcallback=function(){glob=arguments;returnarguments[1]+'at'+arguments[2]+'dot'+arguments[3];};
Now,performatest:
>"[email protected]".replace(re,callback);"stoyanatphpieddotcom"
Here'swhatthecallbackfunctionreceivedasarguments:
>glob;["[email protected]","stoyan","phpied","com",0,"[email protected]"]
split()
Youalreadyknowaboutthesplit()method,whichcreatesanarrayfromaninputstringandadelimiterstring.Let'stakeastringofcomma-separatedvaluesandsplitit:
>varcsv='one,two,three,four';>csv.split(',');["one","two","three","four"]
Becausetheinputstringhappenstohaverandominconsistentspacesbeforeandafterthecommas,thearrayresulthasspacestoo.Witharegularexpression,youcanfixthisusing\s*,whichmeanszeroormorespaces:
>csv.split(/\s*,\s*/);
![Page 228: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/228.jpg)
["one","two","three","four"]
PassingastringwhenaRegExpisexpected
Onelastthingtonoteisthatthefourmethodsthat youhavejustseen(split(),match(),search(),andreplace())canalsotakestringsasopposedtoregularexpressions.Inthiscase,thestringargumentisusedtoproduceanewregexasifitwerepassedtonewRegExp().
Anexampleofpassinga stringtoreplaceisshownasfollows:
>"test".replace('t','r');"rest"
Theprecedinglinesofcodearethesameasthefollowingone:
>"test".replace(newRegExp('t'),'r');"rest"
When you pass a string, you cannot set modifiers the way you do with a normal constructor orregexliteral.There'sacommonsourceoferrorswhenusingastringinsteadofaregularexpressionobjectforstringreplacements,andit'sduetothefactthatthegmodifierisfalsebydefault.Theoutcomeisthatonlythefirststringisreplaced,whichisinconsistentwithmostotherlanguagesandalittleconfusing.Hereisanexample:
>"pool".replace('o','*');"p*ol"
Mostlikely,youwanttoreplacealloccurrences:
>"pool".replace(/o/g,'*');"p**l"
Errorobjects
Errorshappen,andit'sgoodtohavethemechanismsinplacesothatyourcodecanrealizethattherehasbeenanerrorconditionandcanrecoverfromitinagracefulmanner.JavaScriptprovidesthetry,catch,andfinallystatementstohelpyoudealwitherrors.Ifanerroroccurs,anerrorobjectisthrown.Errorobjectsarecreatedusingoneofthesebuilt-inconstructors-EvalError,RangeError,ReferenceError,SyntaxError,TypeError,andURIError.AlltheseconstructorsinheritfromError.
Let'sjustcauseanerrorandseewhathappens.What'sasimplewaytocauseanerror?Justcallafunctionthatdoesn'texist.Typethisintotheconsole:
>iDontExist();
You'll get something like the following:
![Page 229: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/229.jpg)
Thedisplayoferrorscanvarygreatlybetweenbrowsersandotherhostenvironments.Infact,mostrecentbrowserstendtohidetheerrorsfromtheusers.However,youcannotassumethatallofyourusershavedisabledthedisplayoferrors,anditisyourresponsibilitytoensureanerror-freeexperienceforthem.Thepreviouserrorpropagatedtotheuser,becausethecodedidn'ttrytotrap(catch)thiserror.Thecodedidn'texpecttheerrorandwasnotpreparedtohandleit.Fortunately,it'strivialtotraptheerror.Allyouneedisthetrystatementfollowedbyacatchstatement.
Thiscodehidestheerrorfromtheuser:
try{iDontExist();}catch(e){//donothing}
Here you have:
Thetrystatementfollowedbyablockofcode.Thecatchstatementfollowedbyavariablenameinparenthesesandanotherblockofcode.
Therecanbeanoptionalfinallystatement(notusedinthisexample)followedbyablockofcode,whichisexecutedregardlessofwhethertherewasanerrorornot.
Inthepreviousexample, thecodeblockthatfollowsthecatchstatementdidn'tdoanything.However,thisistheplacewhereyouputthecodethatcanhelprecoverfromtheerror,oratleastgivefeedbacktotheuserthatyourapplicationisawarethattherewasaspecialcondition.
Thevariableeintheparenthesesafterthecatchstatementcontainsanerrorobject.Likeanyotherobject,itcontainspropertiesandmethods.Unfortunately,differentbrowsersimplementthesemethodsandpropertiesdifferently,buttherearetwopropertiesthatareconsistentlyimplemented-e.nameande.message.
![Page 230: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/230.jpg)
Let'strythiscodenow:
try{iDontExist();}catch(e){alert(e.name+':'+e.message);}finally{alert('Finally!');}
This will present an alert() showing e.name and e.message and then another alert() sayingFinally!.
InFirefoxandChrome,thefirstalertwillsayReferenceError:iDontExistisnotdefined.InInternetExplorer,itwillbeTypeError:Objectexpected.Thistellsustwothings:
Thee.namemethodcontainsthenameoftheconstructorthatwasusedtocreatetheerrorobjectAstheerrorobjectsarenotconsistentacrosshostenvironments(browsers),itwouldbesomewhattrickytohaveyourcodeactdifferentlydependingonthetypeoferror(thevalueof e.name)
YoucanalsocreateerrorobjectsyourselfusingnewError()oranyoftheothererrorconstructorsandthenlettheJavaScriptengineknowthatthere'sanerroneousconditionusingthethrowstatement.
Forexample,imagineascenariowhereyoucallthemaybeExists()functionandafterthatmakecalculations.Youwanttotrapallerrorsinaconsistentway,nomatterwhethertheerroristhatmaybeExists()doesn'texistorthatyourcalculationsfoundaproblem.Considerthefollowingcode:
try{vartotal=maybeExists();if(total===0){thrownewError('Divisionbyzero!');}else{alert(50/total);}}catch(e){alert(e.name+':'+e.message);}finally{alert('Finally!');}
ThiscodewillalertdifferentmessagesdependingonwhetherornotmaybeExists()isdefinedandthevaluesitreturns:
IfmaybeExists()doesn'texist,yougetReferenceError:maybeExists()isnotdefinedin
![Page 231: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/231.jpg)
FirefoxandTypeError:ObjectexpectedinIEIfmaybeExists()returns0,yougetError: Divisionbyzero!IfmaybeExists()returns2,yougetanalertthatsays25
Inallcases,therewillbeasecondalertthatsaysFinally!.
Insteadofthrowingagenericerror,thrownewError('Divisionbyzero!'),youcanbemorespecificifyouchooseto,forexample,throwthrownewRangeError('Divisionbyzero!').Alternatively,youdon'tneedaconstructor;youcansimplythrowanormalobject:
throw{name:"MyError",message:"OMG!Somethingterriblehashappened"}
Thisgivesyoucross-browsercontrolovertheerrorname.
![Page 232: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/232.jpg)
ExercisesLets solve the following exercise:
1. Lookatthefollowingcode:
functionF(){functionC(){returnthis;
}returnC();}varo=newF();
Doesthevalueofthisrefertotheglobalobjectortheobjecto?2. What'stheresultofexecutingthispieceofcode?
functionC(){this.a=1;returnfalse;}console.log(typeofnewC());
3. What'stheresultofexecutingthefollowingpieceofcode?
>c=[1,2,[1,2]];> c.sort();
>c.join('--');>console.log(c);
4. ImaginetheString()constructordidn'texist.Createaconstructorfunction,MyString(),thatactslikeString()ascloselyaspossible.You'renotallowedtouseanybuilt-instringmethodsorproperties,andrememberthattheString()doesn'texist.Youcanusethiscodetotestyourconstructor:
>vars=newMyString('hello');>s.length;5>s[0];"h">s.toString();"hello">s.valueOf();"hello">s.charAt(1);"e">s.charAt('2');"l">s.charAt('e');"h">s.concat('world!');
![Page 233: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/233.jpg)
"helloworld!">s.slice(1,3);"el">s.slice(0,-1);"hell">s.split('e');["h","llo"]>s.split('l');["he","","o"]
Note
Youcanuseaforlooptoloopthroughtheinputstring,treatingitasanarray.
5. UpdateyourMyString()constructortoincludeareverse()method.
Note
Trytoleveragethefactthatarrayshaveareverse()method.
6. ImaginethatArray()andthearrayliteralnotationdon'texist.CreateaconstructorcalledMyArray()thatbehavesasclosetoArray()aspossible.Testitwiththefollowingcode:
>vara=newMyArray(1,2,3,"test");>a.toString();"1,2,3,test">a.length;4>a[a.length-1];"test">a.push('boo');5>a.toString();"1,2,3,test,boo">a.pop();
"boo">a.toString();"1,2,3,test">a.join(',');"1,2,3,test">a.join('isn't');"1isn't2isn't3isn'ttest"
Ifyoufoundthisexerciseamusing,don'tstopwiththejoin()method;goonwithasmanymethodsaspossible.
7. ImagineMathdidn'texist.CreateaMyMathobjectthatalsoprovides thefollowingadditionalmethods:
MyMath.rand(min,max,inclusive):Thisgeneratesarandomnumberbetweenminandmax,inclusiveifinclusiveistrue(default)MyMath.min(array):ThisreturnsthesmallestnumberinagivenarrayMyMath.max(array):Thisreturnsthelargestnumberinagivenarray
![Page 234: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/234.jpg)
SummaryIn Chapter 2, Primitive Data Types, Arrays, Loops, and Conditions, you saw that there are fiveprimitivedatatypes(number,string,Boolean,null,andundefined),andwealsosaidthateverythingthatisnotaprimitivepieceofdataisanobject.Now,youalsoknowthat:
Objectsarelikearrays,butyouspecifythekeysObjectscontainpropertiesPropertiescanbefunctions(functionsaredata;remembervarf=function(){};).PropertiesthatarefunctionsarealsocalledmethodsArraysareactuallyobjectswithpredefinednumericpropertiesandanauto-incrementinglengthpropertyArrayobjectshaveanumberofconvenientmethods(suchassort()orslice())Functionsarealsoobjects,andtheyhaveproperties(suchaslengthandprototype)andmethods(suchascall()andapply())
Regardingthefiveprimitivedatatypes,apartfromundefinedandnull,theotherthreehavethecorrespondingconstructorfunctions-Number(),String(),andBoolean().Usingthese,youcancreateobjects,calledwrapperobjects,whichcontainmethodsforworkingwithprimitivedataelements.
Number(),String(),andBoolean()canbeinvoked:
Withthenewoperator,tocreatenewobjects.Withoutthenewoperator,toconvertanyvaluetothecorrespondingprimitivedatatype.
Otherbuilt-inconstructorfunctionsyou'renowfamiliarwithincludeObject(),Array(),Function(),Date(),RegExp(),andError().You'realsofamiliarwithMath-aglobalobjectthatisnotaconstructor.
Now,youcanseehowobjectshaveacentralroleinJavaScriptprogramming,asprettymucheverythingisanobjectorcanbewrappedbyanobject.
Finally,let'swrapuptheliteralnotationsyou'renowfamiliarwith:
Name Literal Constructor Example
Object {} newObject() {prop:1}
Array [] newArray() [1,2,3,'test']
Regularexpression /pattern/modifiers newRegExp('pattern','modifiers') /java.*/img
![Page 235: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/235.jpg)
Chapter 5. ES6 Iterators and GeneratorsSo far, we have discussed language constructs of JavaScript without looking at any specificlanguageversion.Inthischapter,however,wewillprimarilyfocusonafewlanguagefeaturesintroducedinES6.ThesefeatureshaveabigimpactonhowyouwriteJavaScriptcode.Notonlydotheyimprovethelanguagesignificantly,theyalsoofferseveralfunctionalprogrammingconstructsunavailabletoJavaScriptprogrammersthusfar.
Inthischapter,wewilltakealookatnewlyintroducediteratorsandgeneratorsinES6.Withthatknowledge,wewillproceedtotakeadetailedlookattheenhancedCollectionsconstructs.
![Page 236: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/236.jpg)
For...of loopFor...of loops are introduced in ES6 along with the iterable and iterator constructs. This newloop constructs replaces both the for...in and for...each loop constructs of ES5. As thefor...of loop supports the iteration protocol, it can be used on built-in objects such as arrays,strings, maps, sets, and so on, and custom objects that are iterables. Consider the following pieceofcodeasanexample:
constiter=['a','b'];for(constiofiter){console.log(i);}"a""b"
Thefor...ofloopworkswithiterablesandbuilt-inslikearraysareiterables.Ifyounotice,weareusingconstinsteadofvarwhenwedefinetheloopvariable.Thisisagoodpracticebecausewhenyouuseconst,afreshvariableiscreatedwithanewbindingandstoragespace.Youshoulduseconstovera vardeclarationwiththefor...ofloopwhenyoudon'tintendtomodifythevalueoftheloopvariableinsidetheblock.
Othercollectionssupportfor...oflooptoo.Forexample,asastringisasequenceofUnicodecharacters,for...ofloopworksjustfine:
for(letcof"String"){console.log(c);}//"s""t""r""i""n""g"
Themaindifferencebetweenthefor...inandfor...ofloopisthatthefor...inloopiteratesthroughallenumerablepropertiesofanobject.For...ofloophasaspecificpurpose,andthatistofollowtheiterationbehaviorbasedonhowtheobjectdefinestheiterableprotocol.
![Page 237: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/237.jpg)
Iterators and iterablesES6 introduces a new mechanism of iterating over data. Traversing a list of data and doingsomethingwithitisaverycommonoperation.ES6enhancestheiterationconstructs.Therearetwoprimaryconceptsinvolvedwiththischange-iteratorsanditerables.
![Page 238: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/238.jpg)
Iterators
AJavaScriptiteratorisanobjectthatexposesthenext()method.Thismethodreturnsthenextitemfromthecollectionintheformofanobjectthathastwoproperties-doneandvalue.Inthefollowingexample,wewillreturnaniteratorfromanarraybyexposingthenext()method:
//Takeanarrayandreturnaniteratorfunctioniter(array){varnextId=0;return{next:function(){if(nextId<array.length){return{value:array[nextId++],done:false};}else{return{done:true};}}}}varit=iter(['Hello','Iterators']);console.log(it.next().value);//'Hello'console.log(it.next().value);//'Iterators'console.log(it.next().done);//true
In the preceding example, we are returning value and done till we have elements in the array.When we exhaust elements in the array to return, we will return done as true, indicating that theiteration has no more values. Elements from an iterator are accessed using the next() methodrepeatedly.
![Page 239: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/239.jpg)
Iterables
Aniterableisanobjectthatdefinesitsiterationbehaviororinternaliteration.Suchobjectscanbeusedinthefor...of loopsintroducedinES6.Built-intypessuchasarraysandstringsdefinedefaultiterationbehavior.Foranobjecttobeiterable,itmustimplementthe@@iteratormethod,meaningtheobjectmusthaveapropertywith'Symbol.iterator'askey.
Anobjectbecomesiterableifitimplementsamethodwhosekeyis'Symbol.iterator'.Thismethodmustreturnaniteratorviathenext()method.Let'stakealookatthefollowingexampletoclarifythis:
//Aniterableobject//1.Hasamethodwithkeyhas'Symbol.iterator'//2.Thismethodreturnsaniteratorviamethod'next'letiter={0:'Hello',1:'Worldof',2:'Iterators',length:3,[Symbol.iterator](){letindex=0;return{next:()=>{letvalue=this[index];letdone=index>=this.length;index++;return{value,done};}};}};for(letiofiter){console.log(i);}"Hello"
"World of ""Iterators"
Let'sbreakthisexampledownintosmallerpieces.Wearecreatinganiterableobject.Wewillcreateaniterobjectusingobjectliteralsyntaxthatwearealreadyfamiliarwith.Onespecialaspectofthisobjectisa[Symbol.iterator]method.ThismethoddefinitionusesacombinationofcomputedpropertiesandES6shorthandmethoddefinitionsyntax,whichwealreadydiscussedinthelastchapter.Asthisobjectcontainsa[Symbol.iterator]method,thisobjectisiterable,oritfollowsaniterableprotocol.Thismethodalsoreturnstheiteratorobjectthatdefinestheiterationbehaviorviaexposingthenext()method.Nowthisobjectcanbeusedwiththefor...ofloop.
![Page 240: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/240.jpg)
GeneratorsClosely linked with iterators and iterables, generators are one of the most talked about features ofES6.Generatorfunctionsreturnageneratorobject;thistermsoundsconfusingatfirst.Whenyouwriteafunction,youalsoinstinctivelyunderstanditsbehavior-thefunctionstartsexecution,line-by-line,andfinishesexecutionwhenthelastlineisexecuted.Oncethefunctionislinearlyexecutedthisway,therestofthecodethatfollowsthefunctionisexecuted.
Inlanguageswheremultithreadingissupported,suchflowofexecutioncanbeinterruptedandpartiallyfinishedtaskscanbesharedbetweendifferentthreads,processes,andchannels.JavaScriptissingle-threaded,andyoudon'tneed todealwithchallengesaroundmultithreadingatthemoment.
However,generatorfunctionscanbepausedandresumedlater.Theimportantideahereisthatthegeneratorfunctionchoosestopauseitself,itcannotbepausedbyanyexternalcode.Duringexecution,thefunctionusestheyieldkeywordtopause.Onceageneratorfunctionispaused,itcanonlyberesumedbycodeoutsidethefunction.
Youcanpauseandresumeageneratorfunctionasmanytimesyouwantto.Withgeneratorfunctions,apopularpatternistowriteinfiniteloopsandpauseandresumethemwhenneeded.Thereareprosandconsofdoingthis,butthepatternhascaughtupalready.
Anotherimportantpointtounderstandisthatgeneratorfunctionsalsoallowtwo-waymessagepassing,inandoutofit.Wheneveryoupausethefunctionusingyieldkeyword,themessageissentoutofthegeneratorfunction,andwhenthefunctionisresumed,themessageispassedbacktothegeneratorfunction.
Let'slookatthefollowingexampletoclarifyhowthegeneratorfunctionswork:
function*generatorFunc(){console.log('1');//----------->Ayield;//----------->Bconsole.log('2');//----------->C}constgeneratorObj=generatorFunc();console.log(generatorObj.next());//"1"//Object{//"done":false,//"value":undefined
//}
Thisisaverysimplegeneratorfunction.However,thereareseveralinterestingaspectsthatneedcarefulunderstanding.
![Page 241: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/241.jpg)
First,noticeanasterix*immediatelyafterthekeywordfunction,thisisthesyntaxtoindicatethatthefunctionisageneratorfunction.Itisalsookaytokeeptheasteriximmediatelyprecedingthefunctionname.Bothofthefollowingarevaliddeclarations:
function*f(){}function*f(){}
Insidethefunction,therealmagicisaroundtheyieldkeyword.Whentheyieldkeywordisencountered,thefunctionpausesitself.Beforewemovefurther,let'sseehowthefunctionisinvoked:
constgeneratorObj=generatorFunc();generatorObj.next();//"1"
Whenweinvokethegeneratorfunction,itisnotexecutedlikeanormalfunction,butitreturnsagenerator object. You can use this generator object to control the execution of the generatorfunction.Thenext()methodonthegeneratorobjectresumestheexecutionofthefunction.
Whenwecallnext()thefirsttime,theexecutionproceedsupuntilthefirstlineofthefunction(markedby'A'),andpauseswhentheyieldkeywordisencountered.Ifwecallthenext()functionagain,itwillresumetheexecutiontothe nextlinefromthepointtheexecutionwaspausedlasttime:
console.log(generatorObj.next());//"2"//Object{//"done":true,//"value":undefined//}
Oncetheentirefunctionbodyisexecuted,anycallstonext()onthegeneratorobjecthavenoeffect.Wetalkedaboutgeneratorfunctionsallowingatwo-waymessagepassing.Howdoesthatwork?Inthepreviousexample,youcanseethatwheneverweresumethegeneratorfunction,wereceiveanobjectwithtwovalues,doneandvalue;inourcase,wereceivedundefinedasthevalue.Thisisbecausewedidnotreturnanyvaluewiththeyieldkeyword.Whenyoureturnavaluewiththeyieldkeyword,thecallingfunctionreceivesit.Considerthefollowingexample:
function* logger() {console.log('start')console.log(yield)console.log(yield)console.log(yield)return('end')}
vargenObj=logger();
//thefirstcallofnextexecutesfromthe
![Page 242: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/242.jpg)
startofthefunctionuntilthefirstyieldstatementconsole.log(genObj.next())//"start",Object{"done":false,"value":undefined}console.log(genObj.next('Save'))//"Save",Object{"done":false,"value":undefined}console.log(genObj.next('Our'))//"Our",Object{"done":false,"value":undefined}console.log(genObj.next('Souls'))//"Souls",Object{"done":true,"value":"end"}
Let'stracetheflowofexecutionofthisexamplestepbystep.Thegeneratorfunctionhasthreepausesoryields.Wecancreatethegeneratorobjectbywritingthefollowinglineofcode:
vargenObj=logger();
Wewillstarttheexecutionofthegeneratorfunctionbycallingthenextmethod;thismethodstartstheexecutiontillthefirstyield.Ifyounotice,wearenotpassinganyvaluetothenext()methodinthefirstcall.Thepurposeofthisnext()methodisjusttostartthegeneratorfunction.Wewillcallthenext()methodagain,butthistimewitha"Save"valuepassedasaparameter.Thisvalueisreceivedbyyieldwhenthefunctionexecutionisresumed,andwecanseethevalueprintedonconsole:
"Save",Object{"done":false,"value":undefined}
Wewillcallthenext()methodagainwithtwodifferentvalues,andtheoutputissimilartotheoneintheprecedingcode.Whenwecallthenext()methodthelasttime,theexecutionendsandthegeneratorfunctionreturnsanendvaluetothecallingpieceofcode.Attheendoftheexecution,youwillseedonesetastrueandvalueassignedthevaluereturnedbythefunction,thatis,end:
"Souls",Object{"done":true,"value":"end"}
Itisimportanttonotethatthepurposeofthefirstnext()methodistostarttheexecutionofthegeneratorfunction-ittakesustothefirstyieldkeywordandhence,anyvaluepassedtothefirstnext()methodisignored.
Fromthediscussionsofar,itisapparentthatgeneratorobjectsconformtotheiteratorcontract:
function*logger(){yield'a'yield'b'}vargenObj=logger();//thegeneratorobjectisbuiltusinggeneratorfunctionconsole.log(typeofgenObj[Symbol.iterator]==='function')//true//itisaniterableconsole.log(typeofgenObj.next==='function')//true//andaniterator(hasanext()method)console.log(genObj[Symbol.iterator]()===genObj)//true
![Page 243: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/243.jpg)
Thisexampleconfirmsthatgeneratorfunctionsalsoconformtotheiterablescontract.
![Page 244: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/244.jpg)
Iteratingovergenerators
Generatorsareiterators, andlikeallES6constructsthatsupportiterables,theycanbeusedtoiterateovergenerators.
Thefirstmethodistousethefor...ofloop,asshowninthefollowingcode:
function*logger(){yield'a'yield'b'}for(constioflogger()){console.log(i)}//"a""b"
Wearenotcreatingageneratorobjecthere.TheFor...ofloophassupportforiterablesandgeneratorsnaturallyfallintothisloop.
Thespreadoperatorcanbeusedtoturniterables intoarrays.Considerthefollowingexample:
function* logger() {yield'a'yield'b'}constarr=[...logger()]console.log(arr)//["a","b"]
Finally,youcanusethedestructuringsyntaxwithgenerators,asfollows:
function*logger(){yield'a'yield'b'}
const [x,y] = logger()console.log(x,y)//"a""b"
Generatorsplayanimportantroleinasynchronousprogramming.Shortly,wewilllookatasynchronousprogrammingandpromisesinES6.JavaScriptandNode.jsofferagreatenvironmenttowriteasynchronousprograms.Generatorscanhelpyouwritecooperativemultitaskingfunctions.
![Page 245: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/245.jpg)
CollectionsES6 introduces four data structures-Map, WeakMap, Set, and WeakSet. JavaScript, whencompared to other languages such as Python and Ruby, had a very weak standard library tosupporthashorMapdatastructuresordictionaries.SeveralhackswereinventedtosomehowachievethebehaviorofaMapbymappingastringkeywithanobject.Thereweresideeffectsofsuchhacks.Languagesupportforsuchdatastructureswassorelyneeded.
ES6supportsstandarddictionarydatastructures; wewilllookatmoredetailsaroundtheseinthenextsection.
![Page 246: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/246.jpg)
Map
Mapallowsarbitraryvaluesaskeys.Thekeysaremappedtovalues.Mapsallowfastaccesstovalues.Let'slookatsomeexamplesofmaps:
const m = new Map(); //Creates an empty Mapm.set('first',1);//Setavalueassociatedwithakeyconsole.log(m.get('first'));//Getavalueusingthekey
WewillcreateanemptyMapusingtheconstructor.Youcanusetheset() methodtoaddanentrytotheMapassociatingkeywithvalue,andoverwritinganyexistingentrywiththesamekey.Itscounterpartmethod,get(),getsthevalueassociatedwithakey,orundefinedifthereisnosuchentryinthemap.
Thereareotherhelpermethodsavailablewithmaps,whichareasfollows:
console.log(m.has('first'));//Checksforexistenceofakey//truem.delete('first');console.log(m.has('first'));//false
m.set('foo',1);m.set('bar', 0);
console.log(m.size);//2m.clear();//clearstheentiremapconsole.log(m.size);//0
YoucancreateaMapusingthefollowingiterable[key,value]pairsaswell:
constm2=newMap([[ 1, 'one' ],
[2,'two'],[3,'three'],]);
Youcanchaintheset() methodforacompactsyntaxasfollows:
constm3=newMap().set(1,'one').set(2,'two').set(3,'three');
Wecanuseanyvalueasakey.Forobjects,thekeycanonlybestrings,butwithcollections,thislimitationisremoved.Wecanuseanobjectasakeyaswell,thoughsuchuseisnotverypopular:
constobj={}constm2=newMap([[1,'one'],["two",'two'],[obj,'three'],]);console.log(m2.has(obj));//true
![Page 247: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/247.jpg)
Iteratingovermaps
Oneimportantthingtorememberisthatorderisimportantwithmaps.Mapsretaintheorderinwhichelementswereadded.
TherearethreeiterablesyoucanusetoiterateoveraMap,thatis,keys,values,andentries.
Thekeys()methodreturnsiterableoverthekeysofaMapasfollows:
constm=newMap([[1,'one'],[2,'two'],[3,'three'],]);for(constkofm.keys()){console.log(k);}//123
Similarly,thevalues()methodreturnsiterableoverthevaluesofaMap,asshowninthefollowingexample:
for(constvofm.values()){console.log(v);}//"one"//"two"//"three"
Theentries()methodreturnsentriesoftheMapinformofa[key,value]pair,asyoucanseeinthefollowingcode:
for(constentryofm.entries()){console.log(entry[0],entry[1]);}//1"one"//2"two"//3"three"
Youcanusedestructuringtomakethisconciseasfollows:
for(const[key,value]ofm.entries()){console.log(key, value);
}//1"one"//2"two"//3"three"
Anevenmoresuccinct:
for(const[key,value]ofm){
![Page 248: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/248.jpg)
console.log(key,value);}//1"one"//2"two"//3"three"
Convertingmapstoarrays
Thespreadoperator(...)comesinhandyifyouwanttoconvertaMaptoanarray:
constm=newMap([[1,'one'],[2,'two'],[3,'three'],]);constkeys=[...m.keys()]console.log(keys)//Array[//1,//2,//3//]
Asmapsareiterable,youcanconverttheentireMapintoanarrayusingspreadoperators:
constm=newMap([[1,'one'],[2,'two'],[3,'three'],]);constarr=[...m]console.log(arr)//Array[//[1,"one"],//[2,"two"],//[3,"three"]//]
![Page 249: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/249.jpg)
Set
ASetisacollectionofvalues.Youcanaddandremovevaluesfromit.Althoughthissoundssimilartoarrays,setsdon'tallowthesamevaluetwice.ValueinaSetcanbeofanytype.Sofar,youmustbewonderinghowdifferentisthisfromanArray?ASetisdesignedtodoonethingquickly-membershiptesting.Arraysarerelativelysloweratthis.SetoperationsaresimilartoMapoperations:
consts=newSet();s.add('first');s.has('first');//trues.delete('first');//trues.has('first');//false
Similartomaps,youcancreateaSetviaaniterator:
constcolors=newSet(['red',white,'blue']);
WhenyouaddavaluetotheSet,andthevaluealreadyexisted,nothinghappens.Similarly,ifyoudeleteavaluefromtheSet,andthevaluedidn'texistinthefirstplace,nothinghappens.Thereisnowaytocatchthisscenario.
![Page 250: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/250.jpg)
WeakMapandWeakSet
WeakMapandWeakSethavethesimilar,butrestricted,APIsastheMapandSetrespectively,andtheyworkmostlyliketheirstrongcounterparts.Thereareafewdifferencesthough,whichareasfollows:
WeakMaponlysupportsthenew,has(),get(),set(),anddelete()methodsWeakSetonlysupportsnew,has(),add(),anddelete()KeysofaWeakMapmustbeobjectsValuesofaWeakSetmustbeobjectsYoucan'titerateoverWeakMap;theonlywayyoucanaccessavalueisviaitskeyYoucan'titerateoveraWeakSetYoucan'tclearaWeakMaporaWeakSet
Let'sunderstandWeakMapfirst.ThedifferencebetweenaMapandaWeakMapisthataWeakMapallowsitselftobegarbagecollected.ThekeysinaWeakMapareweaklyheld.WeakMapkeysarenotcountedwhenthegarbagecollectordoesareferencecount(atechniquetoseeallalivereferences),andtheyaregarbagecollectedwhen possible.
WeakMapsareusefulwhenyoudon'thaveanycontroloverthelifecycleoftheobjectyouarekeepingintheMap.Youdon'tneedtoworryaboutmemoryleakwhenusingWeakMapsbecausetheobjectswillnotkeepthememoryoccupiedeveniftheirlifecycleislong.
SameimplementationdetailsapplytoWeakSetaswell.However,asyoucannotiterateoveraWeakSet,therearenotmanyusecasesforaWeakSet.
![Page 251: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/251.jpg)
SummaryIn this chapter, we took a detailed look at ES6 Generators. Generators are one of the mostanticipatedfeaturesofES6.Theabilitytopauseandresumeexecutionofafunctionopensupalotofpossibilitiesaroundco-operativeprogramming.Theprimarystrengthofgeneratorsisthattheyprovideasingle-threaded,synchronous-lookingcodestyle,whilehidingtheasynchronousnatureaway.Thismakesiteasierforustoexpressinaverynaturalwaywhattheflowofourprogram'ssteps/statementsiswithoutsimultaneouslyhavingtonavigateasynchronoussyntaxandgotchas.Weachieveseparationofconcernusinggeneratorsduetothis.
Generatorsworkhand-in-handwiththeiteratorsanditerablescontract.ThesearewelcomeadditiontoES6andsignificantlybooststhedatastructuresthelanguageoffers.Iteratorsprovideasimplewaytoreturna(potentiallyunbounded)sequenceofvalues.The@@iteratorsymbolisusedtodefinedefaultiteratorsforobjects,makingthemaniterable.
Themostimportantusecaseforiteratorsbecomesevidentwhenwewanttouseitinaconstructthatconsumesiterables,suchasthefor...ofloop.Inthischapterwealsolookedatanewloopconstructfor...ofintroducedinES6.for...ofworkswithalotofnativeobjectsbecausetheyhavedefault@@iteratormethodsdefined.WelookedatnewadditionstotheES6collectionslike-Maps,Sets,WeakMaps,andWeakSets.Thesecollectionshaveadditionaliteratormethods-.entries(),.values()and.keys().
ThenextchapterwilltakeadetailedlookatJavaScriptPrototypes.
![Page 252: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/252.jpg)
Chapter 6. PrototypeIn this chapter, you'll learn about the prototype property of the function objects. UnderstandinghowtheprototypeworksisanimportantpartoflearningtheJavaScriptlanguage.Afterall,JavaScriptisoftenclassifiedashavingaprototype-basedobjectmodel.There'snothingparticularlydifficultabouttheprototype,butit'sanewconcept,andassuch,maysometimestakeabitoftimetosinkin.Likeclosures(seeChapter3,Functions),theprototypeisoneofthosethingsinJavaScriptwhich,onceyouget,seemsoobviousandmakeperfectsense.Aswiththerestofthisbook,you'restronglyencouragedtotypeinandplayaroundwiththeexamples-thismakesitmucheasiertolearnandremembertheconcepts.
Inthischapter,wewillcoverthefollowingtopics:
EveryfunctionhasaprototypepropertyanditcontainsanobjectAddingpropertiestotheprototypeobjectUsingthepropertiesaddedtotheprototypeThedifferencebetweenownpropertiesandpropertiesoftheprototypeThe__proto__property,thesecretlinkeveryobjectkeepstoitsprototypeMethodssuchasisPrototypeOf(),hasOwnProperty(),andpropertyIsEnumerable()Enhancingbuilt-inobjects,suchasarraysorstrings,andwhythatcanbeabadidea
![Page 253: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/253.jpg)
The prototype propertyThe functions in JavaScript are objects, and they contain methods and properties. Some of themethodsthatyou'realreadyfamiliarwithareapply()andcall(),andsomeoftheotherpropertiesarelengthandconstructor.Anotherpropertyofthefunctionobjectsisprototype.
Ifyoudefineasimplefunction,foo(),youcanaccessitspropertiesasyouwoulddowithanyotherobject.Considerthefollowingcode:
>functionfoo(a,b){returna*b;}>foo.length;2>foo.constructor;functionFunction(){[nativecode]}
Theprototypepropertyisapropertythatisavailabletoyouassoonasyoudefinethefunction.Itsinitialvalueisanemptyobject:
>typeoffoo.prototype;"object"
It'sasifyouhaveaddedthispropertyyourself,asfollows:
>foo.prototype={};
Youcanaugmentthisemptyobjectwithpropertiesandmethods.Theywon'thaveanyeffectonthefoo()functionitself;they'llonlybeusedifyoucallfoo()asaconstructor.
![Page 254: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/254.jpg)
Addingmethodsandpropertiesusingtheprototype
Inthepreviouschapter,youlearnedhowtodefineconstructorfunctionsthatyoucanusetocreate(construct)newobjects.Themainideaisthat,insideafunctioninvokedwithnew,youwillhaveaccesstothethisvalue,whichreferstotheobjecttobereturnedbytheconstructor.Augmenting,whichisaddingmethodsandpropertiestothis,ishowyoucanaddfunctionalitytotheobjectbeingconstructed.
Let'stakealookattheconstructorfunction,Gadget(),whichusesthistoaddtwopropertiesandonemethodtotheobjectsitcreates,asfollows:
functionGadget(name,color){this.name=name;this.color=color;
this.whatAreYou = function () {return'Iama'+this.color+''+this.name;};}
Addingmethodsandpropertiestotheprototypepropertyoftheconstructorfunctionisanotherwaytoaddfunctionalitytotheobjectsthisconstructorproduces.Let'saddtwomoreproperties,priceandrating,aswellasagetInfo()method.Asprototypealreadypointstoanobject,youcanjustkeepadding propertiesandmethodstoit,asfollows:
Gadget.prototype.price=100;Gadget.prototype.rating=3;Gadget.prototype.getInfo=function(){return'Rating:'+this.rating+',price:'+this.price;};
Alternatively, instead of adding properties to the prototype object one by one, you canoverwrite the prototype completely, replacing it with an object of your choice, as shown in thefollowing example:
Gadget.prototype={price:100,rating:.../*andsoon...*/};
![Page 255: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/255.jpg)
Using the prototype's methods and propertiesAll the methods and properties you have added to the prototype are available as soon as youcreate a new object using the constructor. If you create a newtoy object using the Gadget()constructor, you can access all the methods and properties that are already defined, as you can seeinthefollowingcode:
>varnewtoy=newGadget('webcam','black');>newtoy.name;"webcam">newtoy.color;"black">newtoy.whatAreYou();"Iamablackwebcam">newtoy.price;100>newtoy.rating;3>newtoy.getInfo();"Rating:3,price:100"
It'simportanttonotethattheprototypeislive.ObjectsarepassedbyreferenceinJavaScript,andtherefore,theprototypeisnotcopiedwitheverynewobjectinstance.Whatdoesthismeaninpractice?Itmeansthatyoucanmodifytheprototypeatanytime,andalltheobjects,eventhosecreatedbeforethemodification,willseethechanges.
Let's continue the example by adding a new method to the prototype:
Gadget.prototype.get=function(what){returnthis[what];};
Eventhoughthenewtoyobjectwascreatedbeforetheget()methodwasdefined,thenewtoyobjectstillhasaccessto thenewmethod,whichisasfollows:
>newtoy.get('price');100>newtoy.get('color');"black"
![Page 256: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/256.jpg)
Ownpropertiesversusprototypeproperties
Intheprecedingexample,getInfo()wasusedinternallytoaccessthepropertiesoftheobject.Itcould'vealsousedGadget.prototypetoachievethesameoutput,asfollows:
Gadget.prototype.getInfo=function(){return'Rating:'+Gadget.prototype.rating+',price:'+Gadget.prototype.price;};
What'sthedifference?Toanswerthisquestion,let'sexamineindetailhowtheprototypeworks.
Let'stakethenewtoyobjectagain:
varnewtoy=newGadget('webcam','black');
Whenyoutrytoaccessapropertyofnewtoy,say,newtoy.name,theJavaScriptenginelooksthroughallofthepropertiesoftheobjectsearchingforonecalledname,andifitfindsit,itreturnsitsvalue,asfollows:
>newtoy.name;"webcam"
Whatifyoutrytoaccesstheratingproperty?TheJavaScriptengineexaminesallofthepropertiesofthenewtoyobjectanddoesn'tfindtheonecalledrating.Then,thescriptengineidentifiestheprototypeoftheconstructorfunctionusedtocreatethisobject(thesameasifyoudonewtoy.constructor.prototype).Ifthepropertyisfoundintheprototypeobject,thefollowingpropertyisused:
>newtoy.rating;3
Youcandothesameandaccesstheprototypedirectly.Everyobjecthasaconstructorproperty,whichisareferencetothefunctionthatcreatedtheobject,sointhiscaselookatthefollowingcode:
>newtoy.constructor===Gadget;true>newtoy.constructor.prototype.rating;3
Now,let'stakethislookuponestepfurther.Everyobjecthasaconstructor.Theprototypeisanobject,soitmusthaveaconstructortoo,which,inturn,hasaprototype.Youcangouptheprototypechain,andyou willeventuallyendupwiththebuilt-inObject()object,whichisthehighest-levelparent.Inpractice,thismeansthatifyoutrynewtoy.toString()andnewtoydoesn'thaveitsowntoString()method,anditsprototypedoesn'teither,intheend,you'llget
![Page 257: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/257.jpg)
theobject'stoString()method:
>newtoy.toString();"[objectObject]"
![Page 258: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/258.jpg)
Overwritingaprototype'spropertywithanownproperty
Astheprecedingdiscussiondemonstrates,ifoneofyourobjectsdoesn'thaveacertainpropertyofitsown,itcanuseone,ifitexists,somewhereuptheprototypechain.Whatiftheobjectdoeshaveitsownpropertyandtheprototypealsohasonewiththesamename?Then,theownpropertytakesprecedenceovertheprototype's.
Considerascenariowhereapropertynameexistsasbothanownpropertyandapropertyoftheprototypeobject:
>functionGadget(name){this.name=name;}>Gadget.prototype.name='mirror';
Creatinganewobjectandaccessingitsnamepropertygivesyoutheobject'sownnameproperty,asfollows:
>vartoy=newGadget('camera');>toy.name;"camera"
YoucantellwherethepropertywasdefinedusinghasOwnProperty(),whichisasfollows:
>toy.hasOwnProperty('name');true
Ifyoudeletethetoyobject'sownnameproperty,theprototype'sproperty withthesamenameshinesthrough:
>deletetoy.name;true>toy.name;"mirror">toy.hasOwnProperty('name');false
Ofcourse,youcanalwaysrecreatetheobject'sownpropertyasfollows:
>toy.name='camera';> toy.name;
"camera"
YoucanplayaroundwiththehasOwnProperty()methodtofindouttheoriginsofaparticularpropertyyou'recuriousabout.ThetoString()methodwasmentionedearlier.Whereisitcomingfrom?
![Page 259: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/259.jpg)
>toy.toString();"[objectObject]">toy.hasOwnProperty('toString');false>toy.constructor.hasOwnProperty('toString');false>toy.constructor.prototype.hasOwnProperty('toString');false>Object.hasOwnProperty('toString');false>Object.prototype.hasOwnProperty('toString');true
Enumeratingproperties
Ifyouwanttolistallthepropertiesofanobject,youcanuseafor...inloop.InChapter2,PrimitiveDataTypes,Arrays,Loops,andConditions,yousawthatyoucanalsoloopthroughalltheelementsofanarraywithfor...in,butasmentionedthere,forisbettersuitedforarraysandfor...inforobjects.Let'stakeanexampleofconstructingaquerystringforaURLfromanobject:
var params = {productid:666,section:'products'};
varurl='http://example.org/page.php?',i,query=[];
for(iinparams){query.push(i+'='+params[i]);}
url+=query.join('&');
Thisproducestheurlstringasfollows:
http://example.org/page.php?productid=666§ion=products.
Thefollowingareafewdetailstobeawareof:
Notallpropertiesshowupinafor...inloop.Forexample,thelength(forarrays)andconstructorpropertiesdon'tshowup.Thepropertiesthatdoshowuparecalledenumerable.YoucancheckwhichonesareenumerablewiththehelpofthepropertyIsEnumerable()methodthateveryobjectprovides.InES5,youcanspecifywhichpropertiesareenumerable,whileinES3youdon'thavethatcontrol.Prototypesthatcomethroughtheprototypechainalsoshowup,providedtheyareenumerable.Youcancheckwhetherapropertyisanobject'sownpropertyoraprototype's
![Page 260: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/260.jpg)
propertyusingthehasOwnProperty()method.ThepropertyIsEnumerable()methodreturnsfalseforalloftheprototype'sproperties,eventhosethatareenumerableandshowup inthefor...inloop.
Let'sseethesemethodsinaction.TakethissimplifiedversionofGadget():
functionGadget(name,color){this.name=name;
this.color = color;this.getName=function(){returnthis.name;};}Gadget.prototype.price=100;Gadget.prototype.rating=3;
Createanewobjectasfollows:
varnewtoy=newGadget('webcam','black');
Now,ifyouloopusingafor...inloop,youcanseealloftheobject'sproperties,includingthosethatcomefromtheprototype:
for(varpropinnewtoy){console.log(prop+'='+newtoy[prop]);}
Theresultalsocontainstheobject'smethods,asmethodsarejustpropertiesthathappentobefunctions:
name=webcamcolor=blackgetName=function(){returnthis.name;}price=100rating=3
Ifyouwanttodistinguishbetweentheobject'sownpropertiesandtheprototype'sproperties,usehasOwnProperty().Trythefollowingfirst:
>newtoy.hasOwnProperty('name');true
>newtoy.hasOwnProperty('price');false
Let'sloopagain,butthistime,showingonlytheobject'sownproperties:
for(varpropinnewtoy){if(newtoy.hasOwnProperty(prop)){console.log(prop+'='+newtoy[prop]);
![Page 261: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/261.jpg)
}}
Theresultisasfollows:
name=webcamcolor=blackgetName=function(){returnthis.name;
}
Now,let'strypropertyIsEnumerable().Thismethodreturnstruefortheobject'sownpropertiesthatarenotbuiltin,forexample:
>newtoy.propertyIsEnumerable('name');true
Mostbuilt-inpropertiesandmethodsarenotenumerable:
>newtoy.propertyIsEnumerable('constructor');false
Anypropertiescomingdowntheprototypechainarenotenumerable:
> newtoy.propertyIsEnumerable('price');false
However,notthatsuchpropertiesareenumerableifyoureachtheobjectcontainedintheprototypeandinvokeitspropertyIsEnumerable()method.Considerthefollowingcode:
>newtoy.constructor.prototype.propertyIsEnumerable('price');true
![Page 262: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/262.jpg)
UsingisPrototypeOf()method
ObjectsalsohavetheisPrototypeOf()method.Thismethodtellsyouwhetherthatspecificobjectisusedasaprototypeofanotherobject.
Let'stakeasimpleobjectnamedmonkey:
varmonkey={hair:true,feeds:'bananas',breathes:'air'};
Now,let'screateaHuman()constructorfunctionandsetitsprototypepropertytopointtomonkey:
functionHuman(name){this.name=name;}Human.prototype=monkey;
Now,ifyoucreateanewHumanobjectcalledgeorgeandaskIfmonkeytheprototypeofgeorge?,you'llgettrue:
>vargeorge=newHuman('George');>monkey.isPrototypeOf(george);true
Notethatyouhavetoknow,orsuspect,whotheprototypeisandthenaskisittruethatyourprototypeismonkey?inordertoconfirmyoursuspicion.But,whatifyoudon'tsuspectanything,andyouhavenoidea?Canyoujustasktheobjecttotellyouitsprototype?Theansweris,youcan'tinallbrowsers,butyoucaninmostofthem.MostrecentbrowsershaveimplementedtheadditiontoES5calledObject.getPrototypeOf().
>Object.getPrototypeOf(george).feeds;"bananas">Object.getPrototypeOf(george)===monkey;true
Forsomeofthepre-ES5environmentsthatdon'thavegetPrototypeOf(),youcanusethespecialproperty,__proto__.
![Page 263: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/263.jpg)
Thesecret__proto__link
Asyoualreadyknow,theprototypepropertyisconsultedwhenyoutrytoaccessapropertythatdoesnotexistinthecurrentobject.
Consideranotherobjectcalledmonkey,anduseitasaprototypewhencreatingobjectswiththeHuman()constructor:
>varmonkey={feeds:'bananas',breathes:'air'};>functionHuman(){}>Human.prototype=monkey;
Now,let'screateadeveloperobject,andgiveitthefollowingproperties:
>vardeveloper=newHuman();>developer.feeds='pizza';>developer.hacks='JavaScript';
Now,let'saccesstheseproperties(forexample,hacksisapropertyofthedeveloperobject):
>developer.hacks;"JavaScript"
Thefeedspropertycanalsobefoundintheobject,asfollows:
>developer.feeds;"pizza"
Thebreathespropertydoesn'texistasapropertyofthedeveloperobject,sotheprototypeislookedup,asifthereisasecretlinkorpassagewaythatleadstotheprototypeobject:
>developer.breathes;"air"
The secret link is exposed in most modern JavaScript environments as the __proto__ property,the word proto with two underscores before and after:
>developer.__proto__===monkey;true
Youcanusethissecretpropertyforlearningpurposes,butit'snotagoodideatouseitinyourrealscriptsbecauseitdoesnotexistinallbrowsers(notablyIE),soyour scriptswon'tbeportable.
Beawarethat__proto__isnotthesameasprototype,as__proto__isapropertyofthe
![Page 264: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/264.jpg)
instances(objects),whereasprototypeisapropertyoftheconstructorfunctionsusedtocreatethoseobjects:
>typeofdeveloper.__proto__;"object">typeofdeveloper.prototype;"undefined">typeofdeveloper.constructor.prototype;"object"
Onceagain,youshoulduse__proto__onlyforlearningordebuggingpurposes.Or,ifyou'reluckyenoughandyourcodeonlyneedstoworkinES5-compliantenvironments,youcanuseObject.getPrototypeOf().
![Page 265: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/265.jpg)
Augmenting built-in objectsThe objects created by the built-in constructor functions, such as Array, String, and evenObject and Function, can be augmented (or enhanced) through the use of prototypes. This meansthat you can, for example, add new methods to the Array prototype, and in this way you can makethem available to all arrays. Let's see how to do this.
InPHP,thereisafunctioncalledin_array(),whichtellsyouwhetheravalueexistsinanarray.InJavaScript,thereisnoinArray()method,although,inES5,there'sindexOf(),whichyoucanuseforthesamepurpose.So,let'simplementitandaddittoArray.prototype,asfollows:
Array.prototype.inArray=function(needle){for(vari=0,len=this.length;i<len;i++){if(this[i]===needle){returntrue;}}returnfalse;};
Now,allarrayshaveaccesstothenewmethod.Let'stestthefollowingcode:
>varcolors=['red','green','blue'];>colors.inArray('red');true>colors.inArray('yellow');false
Thatwasniceandeasy!Let'sdoitagain.Imagineyourapplicationoftenneedstospellwordsbackward,andyoufeelthereshouldbeabuilt-in reverse()methodforstringobjects.Afterall,arrayshavereverse().Youcaneasilyaddareverse()methodtotheStringprototypebyborrowingArray.prototype.reverse()(therewasasimilarexerciseattheendofChapter4,Objects):
String.prototype.reverse=function(){returnArray.prototype.reverse.apply(this.split('')).join('');};
Thiscodeusesthesplit()methodtocreateanarrayfromastring,thencallsthereverse()methodonthisarray,whichproducesareversedarray.Theresultingarrayisthenturnedbackintoastringusingthejoin()method.Let'stestthenewmethod:
>"bumblebee".reverse();"eebelbmub"
![Page 266: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/266.jpg)
Augmentingbuilt-inobjects-discussion
Augmentingbuilt-inobjectsthroughtheprototypeisapowerfultechnique,andyoucanuseittoshapeJavaScriptinanywayyoulike.Becauseofitspower,though,youshouldalwaysthoroughlyconsideryouroptionsbeforeusingthisapproach.
ThereasonisthatonceyouknowJavaScript,you'reexpectingittoworkthesameway,nomatterwhichthird-partylibraryorwidgetyou'reusing.Modifyingcoreobjectscanconfusetheusersandmaintainersofyourcodeandcreateunexpectederrors.
JavaScript evolves and browser's vendors continuously support more features. What you consideramissingmethodtodayanddecidetoaddtoacoreprototypecouldbeabuilt-inmethodtomorrow.Inthiscase,yourmethodisnolongerneeded.Additionally,whatifyouhavealreadywrittenalotofcodethat usesthemethodandyourmethodisslightlydifferentfromthenewbuilt-inimplementation?
Themostcommonandacceptableusecasetoaugmentbuilt-inprototypesistoaddsupportfornewfeatures(onesthatarealreadystandardizedbytheECMAScriptcommitteeandimplementedinnewbrowsers)tooldbrowsers.OneexamplewillbeaddinganES5methodtooldversionsofIE.Theseextensionsareknownasshimsorpolyfills.
Whenaugmentingprototypes,youwillfirstcheckifthemethodexistsbeforeimplementingityourself.Thisway,youcanusethenativeimplementationinthebrowserifoneexists.Forexample,let'saddthetrim()methodforstrings,whichisamethodthatexistsinES5butismissinginolderbrowsers:
if(typeofString.prototype.trim!=='function'){String.prototype.trim=function(){returnthis.replace(/^\s+|\s+$/g,'');};}>"hello".trim();"hello"
Tip
Bestpractice
Ifyoudecidetoaugmentabuilt-inobject,oritsprototypewithanewproperty,docheckfortheexistenceofthenewpropertyfirst.
![Page 267: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/267.jpg)
Prototypegotchas
Thefollowingarethetwoimportantbehaviorstoconsiderwhendealingwithprototypes:
The prototype chain is live, except for when you completely replace the prototype objectThe prototype.constructor method is not reliable
Let'screateasimpleconstructorfunctionandtwoobjects:
>functionDog(){this.tail=true;}>varbenji=newDog();>varrusty=newDog();
Even after you've created the benji and rusty objects, you can still add properties to theprototype of Dog() and the existing objects will have access to the new properties. Let's throw inthe say() method:
>Dog.prototype.say=function(){return'Woof!';};
Bothobjectshaveaccesstothenewmethod:
>benji.say();"Woof!"rusty.say();"Woof!"
Uptothispoint,ifyouconsultyourobjects,askingwhichconstructorfunctionwasusedtocreatethem,they'llreportitcorrectly:
>benji.constructor===Dog;true
> rusty.constructor === Dog;true
Now,let'scompletelyoverwritetheprototypeobjectwithabrandnewobject:
>Dog.prototype={paws:4,hair:true};
Itturnsoutthattheoldobjectsdonotgetaccesstothenewprototype'sproperties;theystillkeepthe secret link pointing to the old prototype object, as follows:
>typeofbenji.paws;"undefined"
![Page 268: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/268.jpg)
>benji.say();"Woof!">typeofbenji.__proto__.say;"function">typeofbenji.__proto__.paws;"undefined"
Anynewobjectsthatyouwillcreatefromnowonwillusetheupdatedprototype,whichisasfollows:
>varlucy=newDog();>lucy.say();TypeError:lucy.sayisnotafunction>lucy.paws;
4
Thesecret__proto__linkpointstothenewprototypeobject,asshowninthefollowinglinesofcode:
>typeoflucy.__proto__.say;"undefined">typeoflucy.__proto__.paws;"number"
Nowtheconstructorpropertyofthenewobjectnolongerreportscorrectly.YouwillexpectittopointtoDog(),butinsteaditpointstoObject(),asyoucanseeinthefollowingexample:
>lucy.constructor;functionObject(){[nativecode]}>benji.constructor;functionDog(){this.tail=true;}
Youcaneasilypreventthisconfusionbyresettingtheconstructorpropertyafteryouoverwritetheprototypecompletely,asfollows:
>functionDog(){}>Dog.prototype={};>newDog().constructor===Dog;false>Dog.prototype.constructor=Dog;>newDog().constructor===Dog;true
Tip
Bestpractice
Whenyouoverwritetheprototype,remembertoresettheconstructorproperty.
![Page 269: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/269.jpg)
ExercisesLets practice the following exercise:
1. CreateanobjectcalledshapethathasthetypepropertyandagetType()method.2. DefineaTriangle()constructorfunctionwhoseprototypeisshape.Objectscreatedwith
Triangle()shouldhavethreeownproperties-a,b,andc,representingthelengthsofthesidesofatriangle.
3. AddanewmethodtotheprototypecalledgetPerimeter().4. Testyourimplementationwiththefollowingcode:
>vart=newTriangle(1,2,3);>t.constructor===Triangle;true>shape.isPrototypeOf(t);true>t.getPerimeter();6
> t.getType();"triangle"
5. Loopovert,showingonlyyourownpropertiesandmethods,noneoftheprototype's.6. Makethefollowingcodework:
>[1,2,3,4,5,6,7,8,9].shuffle();[2,4,1,8,9,6,5,3,7]
![Page 270: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/270.jpg)
SummaryLet's summarize the most important topics you have learned in this chapter:
Allfunctionshaveapropertycalledprototype.Initially,itcontainsanemptyobject-anobjectwithoutanyownproperties.Youcanaddpropertiesandmethodstotheprototypeobject.Youcanevenreplaceitcompletelywithanobjectofyourchoice.Whenyoucreateanobjectusingafunctionasaconstructor(withnew),theobjectgetsasecretlinkpointingtotheprototypeoftheconstructorandcanaccesstheprototype'sproperties.Anobject'sownpropertiestakeprecedence overaprototype'spropertieswiththesamename.UsethehasOwnProperty()methodtodifferentiatebetweenanobject'sownpropertiesandprototypeproperties.Thereisaprototypechain.Whenyouexecutefoo.bar,andifyourfooobjectdoesn'thaveapropertycalledbar,theJavaScriptinterpreterlooksforabarpropertyintheprototype.Ifnoneisfound,itkeepssearchingintheprototype'sprototype,thentheprototypeoftheprototype'sprototype,anditwillkeepgoingallthewayuptoObject.prototype.Youcanaugmenttheprototypesofbuilt-inconstructorfunctions,and allobjectswillseeyouradditions.AssignafunctiontoArray.prototype.flipandallarrayswillimmediatelygetaflip()method,asin[1,2,3].flip().But,docheckwhetherthemethod/propertyyouwanttoaddalreadyexists,soyoucanfuture-proofyourscripts.
![Page 271: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/271.jpg)
Chapter 7. InheritanceIf you go back to Chapter 1, Object-Oriented JavaScript, and review the Object-orientedprogrammingsection,you'llseethatyoualreadyknowhowtoapplymostofthemtoJavaScript.Youknowwhatobjects,methods,andpropertiesare.Youknowthatthere arenoclassesinES5,althoughyoucanachievethemusingconstructorfunctions.ES6introducesthenotionofclasses;wewilltakeadetailedlookathowES6classesworkinthenextchapter.Encapsulation?Yes,theobjectsencapsulateboth thedataandthemeans(methods)todosomethingwiththedata.Aggregation?Sure,anobjectcancontainotherobjects.Infact,thisisalmostalwaysthecasesincemethodsarefunctionsandfunctionsarealsoobjects.
Now,let'sfocusontheinheritancepart.Thisisoneofthemostinterestingfeatures,asitallowsyoutoreuseexistingcode,thuspromotinglaziness,whichislikelytobewhatbroughthumanspeciestocomputerprogramminginthefirstplace.
JavaScriptisadynamiclanguage,andthereisusuallymorethanonewaytoachieveanygiventask.Inheritanceisnotanexception.Inthischapter,you'llseesomecommonpatternsforimplementinginheritance.Havingagoodunderstandingofthesepatternswillhelpyoupicktherightone,ortherightmix,dependingonyourtask,project,orstyle.
![Page 272: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/272.jpg)
Prototype chainingLet's start with the default way of implementing inheritance - inheritance chaining through theprototype.
Asyoualreadyknow,everyfunctionhasaprototypeproperty,whichpointstoanobject.Whenafunctionisinvokedusingthenewoperator,anobjectiscreatedandreturned.Thisnewobjecthasasecretlinktotheprototypeobject.Thesecretlink(called__proto__insomeenvironments)allowsmethodsandpropertiesoftheprototypeobjecttobeusedasiftheybelongedtothenewlycreatedobject.
Theprototypeobjectisjustaregularobjectand,therefore,italsohasthesecretlinktoitsprototype.Andso,achaincalledaprototypechainiscreated:
In this illustration, an object A contains a number of properties. One of the properties is thehidden__proto__property,whichpointstoanotherobject,B.B's__proto__propertypointstoC.ThischainendswiththeObject.prototypeobject,thegrandparent,andeveryobjectinheritsfromit.
Thisisallgoodtoknow,buthowdoesithelpyou?ThepracticalsideisthatwhenobjectAlacksapropertybutBhasit,Acanstillaccessthispropertyasitsown.ThesameappliesifBalsodoesn'thavetherequiredproperty,butCdoes.Thisishowinheritancetakesplace-anobjectcan
![Page 273: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/273.jpg)
accessanypropertyfoundsomewheredowntheinheritancechain.
Throughoutthischapter,you'llseedifferentexamplesthatusethefollowinghierarchy-agenericShape parent is inherited by a 2D shape, which in turn is inherited by any number of specifictwo-dimensional shapes such as a triangle, rectangle, and so on.
![Page 274: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/274.jpg)
Prototypechainingexample
Prototypechainingisthedefaultwaytoimplementinheritance.Inordertoimplementthehierarchy,let'sdefinethreeconstructorfunctions:
functionShape(){this.name='Shape';this.toString=function(){returnthis.name;
};}
functionTwoDShape(){this.name='2Dshape';}
functionTriangle(side,height){this.name='Triangle';this.side=side;this.height=height;this.getArea=function(){returnthis.side*this.height/2;};}
Thecodethatperformstheinheritancemagicisasfollows:
TwoDShape.prototype=newShape();Triangle.prototype=newTwoDShape();
What'shappeninghere?YoutaketheobjectcontainedintheprototypepropertyofTwoDShape,andinsteadofaugmentingitwithindividualproperties,youcompletelyoverwriteitwithanotherobject,createdbyinvokingtheShape()constructorwithnew.ThesameprocesscanbefollowedforTriangle-itsprototypeisreplacedbyanobjectcreatedbynewTwoDShape().It'simportanttorememberthatJavaScriptworkswithobjects,notclasses.YouneedtocreateaninstanceusingthenewShape()constructor,andafterthat,youcaninherititsproperties;youdon'tinheritfromShape()directly.Additionally,afterinheriting,youcanmodifytheShape()constructor,overwriteit,orevendeleteit,andthiswillhavenoeffectonTwoDShape,becauseallyouneededisoneinstancetoinheritfrom.
Asyouknowfromthepreviouschapter,overwritingtheprototype(asopposedtojustaddingproperties to it), has side effects on the constructor property. Therefore, it's a good idea toreset the constructor property after inheriting. Consider the following example:
TwoDShape.prototype.constructor=TwoDShape;Triangle.prototype.constructor=Triangle;
Now,let'stestwhathashappenedsofar.CreatingaTriangleobjectandcallingitsown
![Page 275: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/275.jpg)
getArea()methodworksasexpected:
>varmy=newTriangle(5,10);>my.getArea();25
Although the my object doesn't have its own toString() method, it inherited one and you can callit. Note how the inherited method toString() binds the this object to my:
>my.toString();"Triangle"
It'sfascinatingtoconsiderwhattheJavaScriptenginedoeswhenyoucall my.toString():
Itloopsthroughallofthepropertiesofmyanddoesn'tfindamethodcalledtoString().Itlooksattheobjectthatmy.__proto__pointstothisobjectistheinstancenewTwoDShape()createdduringtheinheritanceprocess.Now,theJavaScriptengineloopsthroughtheinstanceofTwoDShapeanddoesn'tfindatoString()method.Itthenchecks__proto__ofthatobject.Thistime,__proto__pointstotheinstancecreatedbynewShape().TheinstanceofnewShape()isexamined,andtoString()isfinallyfound.Thismethodisinvokedinthecontextofmy,meaningthatthispointstomy.
Ifyouaskmy,Who'syourconstructor?,itreportsitcorrectlybecauseoftheresetoftheconstructorpropertyaftertheinheritance:
>my.constructor===Triangle;true
Usingtheinstanceofoperator,youcanvalidatethatmyisaninstanceofallthreeconstructors:
>myinstanceofShape;true>myinstanceofTwoDShape;true>myinstanceofTriangle;true>myinstanceofArray;false
ThesamehappenswhenyoucallisPrototypeOf()ontheconstructorsbypassingmy:
>Shape.prototype.isPrototypeOf(my);true>TwoDShape.prototype.isPrototypeOf(my);true>Triangle.prototype.isPrototypeOf(my);true>String.prototype.isPrototypeOf(my);
![Page 276: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/276.jpg)
false
Youcanalsocreateobjectsusingtheothertwoconstructors.ObjectscreatedwithnewTwoDShape()alsogetthetoString()methodinheritedfromShape():
>vartd=newTwoDShape();>td.constructor === TwoDShape;
true>td.toString();"2Dshape">vars=newShape();>s.constructor===Shape;true
![Page 277: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/277.jpg)
Movingsharedpropertiestotheprototype
Whenyoucreateobjects usingaconstructorfunction,ownpropertiesareaddedusingthis.Thiscouldbeinefficientincaseswherepropertiesdon'tchangeacrossinstances.Inthepreviousexample,Shape()wasdefinedasfollows:
function Shape(){this.name='Shape';}
ThismeansthateverytimeyoucreateanewobjectusingnewShape(),anewnamepropertyiscreatedandstoredsomewhereinthememory.Theotheroptionistohavethenamepropertyaddedtotheprototypeandsharedamongalltheinstances:
functionShape(){}Shape.prototype.name='Shape';
Now,everytimeyoucreateanobjectusingnewShape(),thisobjectdoesn'tgetitsownpropertyname,butusestheoneaddedtotheprototype.Thisismoreefficient,butyoushouldonlyuseitforpropertiesthatdon'tchangefromoneinstancetoanother.Methodsareidealforthistypeofsharing.
Let'simprovetheprecedingexamplebyaddingallmethodsandsuitablepropertiestoprototype.InthecaseofShape()andTwoDShape(),everythingismeanttobeshared:
//constructorfunctionShape(){}
//augmentprototypeShape.prototype.name='Shape';Shape.prototype.toString=function(){returnthis.name;};
//anotherconstructorfunctionTwoDShape(){}
//takecareofinheritanceTwoDShape.prototype=newShape();TwoDShape.prototype.constructor=TwoDShape;
//augmentprototypeTwoDShape.prototype.name='2Dshape';
Asyoucansee,youhavetotakecareofinheritancefirstbeforeaugmentingtheprototype.Otherwise, anything you add to TwoDShape.prototype gets wiped out when you inherit.
TheTriangleconstructorisalittledifferent,becauseeveryobjectitcreatesisanewtriangle,
![Page 278: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/278.jpg)
whichislikelytohavedifferentdimensions.So,it'sgoodtokeepsideandheightasownpropertiesandsharetherest.ThegetArea()method,forexample,isthesame,regardlessoftheactualdimensionsofeachtriangle.Again,youdotheinheritancebitfirstandthenaugmenttheprototype:
functionTriangle(side,height){this.side=side;this.height=height;}//takecareofinheritanceTriangle.prototype=newTwoDShape();Triangle.prototype.constructor=Triangle;
//augmentprototypeTriangle.prototype.name='Triangle';Triangle.prototype.getArea=function(){returnthis.side*this.height/2;};
Alltheprecedingtestcodeworksexactlythesame.Hereisanexample:
>varmy=newTriangle(5,10);>my.getArea();25>my.toString();"Triangle"
Thereisonlyaslightbehind-the-scenesdifferencewhencallingmy.toString().ThedifferenceisthatthereisonemorelookuptobedonebeforethemethodisfoundinShape.prototype,asopposedtointhenewShape()instance,likeitwasinthepreviousexample.
YoucanalsoplaywithhasOwnProperty()toseethedifferencebetweentheownpropertyversusapropertycomingdowntheprototypechain:
>my.hasOwnProperty('side');true>my.hasOwnProperty('name');false
ThecallstoisPrototypeOf()andtheinstanceofoperatorfromthepreviousexampleworkinexactlythesameway:
>TwoDShape.prototype.isPrototypeOf(my);true>myinstanceofShape;true
![Page 279: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/279.jpg)
Inheriting the prototype onlyAs explained earlier, for reasons of efficiency, you should add the reusable properties andmethodstotheprototype.Ifyoudoso,thenit'sagoodideatoinheritonlytheprototype,becauseallthereusablecodeisthere.ThismeansthatinheritingtheShape.prototypeobjectisbetterthaninheritingtheobjectcreatedwithnewShape().Afterall,newShape()onlygivesyouownshapepropertiesthatarenotmeanttobereused(otherwise,theywouldbeintheprototype).Yougainalittlemoreefficiencyby:
NotcreatinganewobjectforthesakeofinheritancealoneHavingfewerlookupsduringruntime(whenitcomestosearchingfortoString())
For example, here's the updated code; the changes are highlighted:
functionShape(){}//augmentprototypeShape.prototype.name='Shape';Shape.prototype.toString=function(){returnthis.name;};
functionTwoDShape(){}//takecareofinheritanceTwoDShape.prototype=Shape.prototype;TwoDShape.prototype.constructor=TwoDShape;//augmentprototypeTwoDShape.prototype.name='2Dshape';
function Triangle(side, height) {this.side=side;this.height=height;}
//takecareofinheritanceTriangle.prototype=TwoDShape.prototype;Triangle.prototype.constructor=Triangle;//augmentprototypeTriangle.prototype.name='Triangle';Triangle.prototype.getArea=function(){returnthis.side*this.height/2;};
Thetestcodegivesyouthesameresult:
>varmy=newTriangle(5,10);>my.getArea();25>my.toString();"Triangle"
![Page 280: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/280.jpg)
What'sthedifferenceinthelookupswhencallingmy.toString()?First,asusual,theJavaScriptenginelooksforatoString()methodofthemyobjectitself.Theenginedoesn'tfindsuchamethod,soitinspectstheprototype.TheprototypeturnsouttobepointingtothesameobjectthattheprototypeofTwoDShapepointstoandalsothesameobjectthatShape.prototypepointsto.Rememberthatobjectsarenotcopiedbyvalue,butonlybyreference.So,thelookupisonlyatwo-stepprocessasopposedtofour(inthepreviousexample)orthree(inthefirstexample).
Simplycopyingtheprototypeismoreefficient,butithasasideeffectbecause,alltheprototypesofthechildrenandparentspointtothesameobject,whenachildmodifiestheprototype,theparentsgetthechangesandsodothesiblings.
Lookatthefollowingline:
Triangle.prototype.name = 'Triangle';
Itchangesthenameproperty,soiteffectivelychangesShape.prototype.nametoo.IfyoucreateaninstanceusingnewShape(),itsnamepropertysays"Triangle":
>vars=newShape();>s.name;"Triangle"
Thismethodismoreefficient,butmaynotsuitallyourusecases.
![Page 281: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/281.jpg)
Atemporaryconstructor-newF()
Asolutiontothepreviouslyoutlinedproblem,whereallprototypespointtothesameobjectandtheparentsgetchildren'sproperties,istouseanintermediarytobreakthechain.Theintermediaryisintheformofatemporaryconstructorfunction.CreatinganemptyfunctionF()andsettingitsprototypetotheprototypeoftheparentconstructorallowsyoutocallnewF()andcreateobjectsthathavenopropertiesoftheirown,butinheriteverythingfromtheparent'sprototype.
Let'stakealookatthemodifiedcode:
functionShape(){}//augmentprototypeShape.prototype.name='Shape';
Shape.prototype.toString = function () {returnthis.name;};
functionTwoDShape(){}//takecareofinheritancevarF=function(){};F.prototype=Shape.prototype;TwoDShape.prototype=newF();TwoDShape.prototype.constructor=TwoDShape;//augmentprototypeTwoDShape.prototype.name='2Dshape';
functionTriangle(side,height){this.side=side;this.height=height;}
//takecareofinheritancevarF=function(){};F.prototype=TwoDShape.prototype;Triangle.prototype=newF();Triangle.prototype.constructor=Triangle;//augmentprototypeTriangle.prototype.name='Triangle';
Triangle.prototype.getArea = function () {returnthis.side*this.height/2;};
Creatingmytriangleandtestingthemethods:
>varmy=newTriangle(5,10);>my.getArea();25
>my.toString();"Triangle"
![Page 282: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/282.jpg)
Usingthisapproach,theprototypechainstaysinplace:
>my.__proto__===Triangle.prototype;true>my.__proto__.constructor===Triangle;true>my.__proto__.__proto__===TwoDShape.prototype;true>my.__proto__.__proto__.__proto__.constructor===Shape;true
Also,theparents'propertiesarenotoverwrittenbythechildren:
>vars=newShape();>s.name;"Shape">"Iama"+newTwoDShape();//callingtoString()"Iama2Dshape"
Atthesametime,thisapproachsupportstheidea thatonlypropertiesandmethodsaddedtotheprototypeshouldbeinheritedandownpropertiesshouldnot.Therationalebehindthisisthatownpropertiesarelikelytobetoospecifictobereusable.
![Page 283: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/283.jpg)
Uber - access to the parent from a childobjectClassicalOOlanguagesusuallyhaveaspecialsyntaxthatgivesyouaccesstotheparentclass,alsoreferredtothesuperclass.Thiscouldbeconvenientwhenachildwantstohaveamethodthatdoeseverythingtheparent'smethoddoes,plussomethinginadditiontoit.Insuchcases,thechildcallstheparent'smethodwiththesamenameandworkswiththeresult.
InJavaScript,thereisnosuchspecialsyntax,but it'strivialtoachievethesamefunctionality.Let'srewritethelastexample,andwhiletakingcareofinheritance,alsocreateanuberpropertythatpointstotheparent'sprototypeobject:
functionShape(){}//augmentprototypeShape.prototype.name='Shape';Shape.prototype.toString=function(){varconst=this.constructor;returnconst.uber?this.const.uber.toString()+','+this.name:this.name;
};
functionTwoDShape(){}//takecareofinheritancevarF=function(){};F.prototype=Shape.prototype;TwoDShape.prototype=newF();TwoDShape.prototype.constructor=TwoDShape;TwoDShape.uber=Shape.prototype;//augmentprototypeTwoDShape.prototype.name='2Dshape';
functionTriangle(side,height){this.side=side;this.height=height;}
//takecareofinheritancevarF=function(){};F.prototype=TwoDShape.prototype;Triangle.prototype=newF();Triangle.prototype.constructor=Triangle;Triangle.uber=TwoDShape.prototype;//augmentprototypeTriangle.prototype.name='Triangle';
Triangle.prototype.getArea = function () {returnthis.side*this.height/2;};
![Page 284: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/284.jpg)
Thenewthingshereare:
Anewuberpropertypointstotheparent'sprototypeTheupdatedtoString()method
Previously,toString()onlyreturnedthis.name.Now,inadditiontothis,thereisachecktoseewhetherthis.constructor.uberexistsand,ifitdoes,callitstoString()first.Thethis.constructoristhefunctionitself,andthis.constructor.uberpointstotheparent'sprototype.TheresultisthatwhenyoucalltoString()foraTriangleinstance,alltoString()methodsuptheprototypechainarecalled:
>varmy=newTriangle(5,10);>my.toString();"Shape,2Dshape,Triangle"
Thenameoftheuberpropertycould'vebeensuperclass,butthiswouldsuggestthatJavaScripthasclasses.Ideally,itcould'vebeensuper(asinJava),butsuperisareservedwordinJavaScript.TheGermanwordubersuggestedbyDouglasCrockfordmeansmoreorlessthesameassuper,andyouhavetoadmit,itsoundsubercool.
![Page 285: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/285.jpg)
Isolating the inheritance part into a functionLet's move the code that takes care of all the inheritance details from the last example into areusableextend()function:
functionextend(Child,Parent){varF=function(){};F.prototype=Parent.prototype;Child.prototype=newF();Child.prototype.constructor=Child;Child.uber=Parent.prototype;}
Usingthisfunction(oryourowncustomversionofit)helpsyoukeepyourcodecleanwithregardtotherepetitiveinheritance-relatedtasks.Thisway,youcaninheritbysimplyusingthefollowingtwolinesofcode:
extend(TwoDShape, Shape);extend(Triangle,TwoDShape);
Let'sseeacompleteexample:
//inheritancehelperfunctionextend(Child,Parent){varF=function(){};F.prototype=Parent.prototype;Child.prototype=newF();Child.prototype.constructor=Child;Child.uber=Parent.prototype;}
//define->augmentfunctionShape(){}Shape.prototype.name='Shape';Shape.prototype.toString=function(){returnthis.constructor.uber?this.constructor.uber.toString()+','+this.name:this.name;};
//define->inherit->augmentfunctionTwoDShape(){}extend(TwoDShape,Shape);TwoDShape.prototype.name='2Dshape';
//definefunctionTriangle(side,height){this.side=side;this.height=height;}
![Page 286: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/286.jpg)
//inheritextend(Triangle,TwoDShape);//augmentTriangle.prototype.name='Triangle';Triangle.prototype.getArea=function(){returnthis.side*this.height/2;};
Letstestthefollowingcode:
>newTriangle().toString();"Shape,2Dshape,Triangle"
![Page 287: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/287.jpg)
Copying propertiesNow, let's try a slightly different approach. Since inheritance is all about reusing code, can yousimplycopythepropertiesyoulikefromoneobjecttoanother?Orfromaparenttoachild?Keepingthesameinterfaceastheprecedingextend()function,youcancreateaextend2()function,whichtakestwoconstructorfunctionsandcopiesallthepropertiesfromtheparent'sprototypetothechild'sprototype.Thiswill,ofcourse,carryovermethodstoo,asmethodsarejustpropertiesthathappentobefunctions:
functionextend2(Child,Parent){varp=Parent.prototype;varc=Child.prototype;for(variinp){c[i]=p[i];}c.uber=p;}
Asyoucansee,asimpleloopthroughthepropertiesisallittakes.Aswiththepreviousexample,youcansetanuberpropertyifyouwanttohavehandyaccesstoparent'smethodsfromthechild.Unlikethepreviousexamplethough,it'snotnecessarytoresetChild.prototype.constructorbecausehere,thechildprototypeisaugmented,notoverwrittencompletely.So,theconstructorpropertypointstotheinitialvalue.
Thismethodisalittleinefficientcomparedtothepreviousmethodbecausepropertiesofthechildprototypearebeingduplicatedinsteadofsimplybeinglookedupviatheprototypechainduringexecution.Bearinmindthatthisisonlytrueforpropertiescontainingprimitivetypes.Allobjects(includingfunctionsandarrays)arenotduplicated,becausethesearepassedbyreferenceonly.
Let'sseeanexampleofusingtwoconstructorfunctions,Shape()andTwoDShape().TheShape()function'sprototypeobjectcontainsaprimitiveproperty,name,andanon-primitiveone,thetoString()method:
varShape=function(){};var TwoDShape = function () {};
Shape.prototype.name='Shape';Shape.prototype.toString=function(){returnthis.uber?this.uber.toString()+','+this.name:this.name;};
Ifyouinheritwithextend(),neithertheobjectscreatedwithTwoDShape()noritsprototypegetanownnameproperty,buttheyhaveaccesstotheonetheyinherit:
>extend(TwoDShape,Shape);
![Page 288: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/288.jpg)
>vartd=newTwoDShape();>td.name;"Shape">TwoDShape.prototype.name;"Shape">td.__proto__.name;"Shape">td.hasOwnProperty('name');false>td.__proto__.hasOwnProperty('name');false
However,ifyouinheritwithextend2(),theprototypeofTwoDShape()getsitsowncopyofthenameproperty.ItalsogetsitsowncopyoftoString(),butit'sareferenceonly,sothefunctionwillnotberecreatedasecondtime:
>extend2(TwoDShape,Shape);>vartd=newTwoDShape();>td.__proto__.hasOwnProperty('name');true>td.__proto__.hasOwnProperty('toString');true>td.__proto__.toString===Shape.prototype.toString;true
Asyoucansee,thetwotoString()methodsarethesamefunctionobject.Thisisgoodbecauseitmeansthatnounnecessaryduplicatesofthemethodsarecreated.
So,youcansaythatextend2()islessefficientthanextend()becauseitrecreatesthepropertiesoftheprototype.However,thisisnotsobadbecauseonlytheprimitivedatatypesareduplicated.Additionally,thisisbeneficialduringtheprototypechainlookupsastherearefewerchainlinkstofollowbeforefindingtheproperty.
Takealookattheuberpropertyagain.Thistime,forachange,it'ssetontheParentobject'sprototypep,notontheParentconstructor.ThisiswhytoString()uses itasthis.uberasopposedtothis.constructor.uber.Thisisjustanillustrationthatyou canshapeyourfavoriteinheritancepatterninanywayyouseefit.Let'stestitout:
>td.toString();"Shape,Shape"
TwoDShapedidn'tredefinethenameproperty,hencetherepetition.Itcandothatatanytime,and(theprototypechainbeinglive)alltheinstancesseetheupdate:
>TwoDShape.prototype.name="2Dshape";>td.toString();"Shape,2Dshape"
![Page 289: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/289.jpg)
Heads-up when copying by referenceThe fact that objects (including functions and arrays) are copied by reference could sometimesleadtoresultsyoudon'texpect.
Let'screatetwoconstructorfunctionsandaddpropertiestotheprototypeofthefirstone:
>functionPapa(){}>functionWee(){}>Papa.prototype.name='Bear';>Papa.prototype.owns=["porridge","chair","bed"];
Now,let'shaveWeeinheritfromPapa(eitherextend()orextend2()willdo):
>extend2(Wee,Papa);
Usingextend2(),theWeefunction'sprototypeinheritedthepropertiesofPapa.prototypeasitsown:
>Wee.prototype.hasOwnProperty('name');true>Wee.prototype.hasOwnProperty('owns');
true
Thenamepropertyisprimitive,soanewcopyofitiscreated.Theownspropertyisanarrayobject,soit'scopiedbyreference:
>Wee.prototype.owns;["porridge","chair","bed"]>Wee.prototype.owns===Papa.prototype.owns;true
ChangingtheWeefunction'scopyofnamedoesn'taffectPapa:
>Wee.prototype.name+=',LittleBear';"Bear,LittleBear">Papa.prototype.name;"Bear"
ChangingtheWeefunction'sownsproperty,however,affectsPapa,becausebothpropertiespointtothesamearrayinmemory:
>Wee.prototype.owns.pop();"bed">Papa.prototype.owns;["porridge","chair"]
It'sadifferentstorywhenyoucompletelyoverwritetheWeefunction'scopyofownswithanotherobject(asopposedtomodifyingtheexistingone).Inthiscase,Papa.ownskeepspointingtothe
![Page 290: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/290.jpg)
oldobject,whileWee.ownspointstoanewone:
>Wee.prototype.owns=["emptybowl","brokenchair"];>Papa.prototype.owns.push('bed');>Papa.prototype.owns;["porridge","chair","bed"]
Thinkofanobjectassomethingthatiscreatedandstoredinaphysicallocationinmemory.Variablesandpropertiesmerelypointtothislocation,sowhenyouassignabrandnewobjecttoWee.prototype.owns,youessentiallysay-Hey,forgetaboutthisotheroldobject,moveyourpointertothisnewoneinstead.
Thefollowingdiagramillustrateswhathappensifyouimaginethememorybeingaheapofobjects(likeawallofbricks)andyoupointto(referto)someoftheseobjects:
Anewobjectiscreated,andApointstoit.AnewvariableBiscreatedandmadeequaltoA,meaningitnowpointstothesameplaceAispointingto.ApropertycolorischangedusingtheBhandle(pointer).Thebrickisnowwhite.AcheckforA.color==="white"wouldbetrue.Anewobjectiscreated,andtheBvariable/pointerisrecycledtopointtothatnewobject.AandBarenowpointingtodifferentpartsofthememorypile.Theyhavenothingincommonandchangestooneofthemdon'taffecttheother:
![Page 291: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/291.jpg)
![Page 292: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/292.jpg)
Ifyouwanttoaddresstheproblemthatobjectsarecopiedbyreference,consideradeepcopy,describedlaterinthechapter.
![Page 293: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/293.jpg)
Objects inherit from objectsAll the examples so far in this chapter assume that you create your objects with constructorfunctions,andyouwantobjectscreatedwithoneconstructortoinheritpropertiesthatcomefromanotherconstructor.However,youcanalsocreateobjectswithoutthehelpofaconstructorfunction,justusingtheobjectliteral,andthisis,infact,lesstyping.So,howaboutinheritingthose?
InJavaorPHP,youdefineclassesandhavetheminheritfromotherclasses.That'swhyyou'llseethetermclassical,becausetheOOfunctionalitycomesfromtheuseofclasses.InJavaScript,therearenoclasses,soprogrammersthatcomefromaclassicalbackgroundresorttoconstructorfunctions,becauseconstructorsaretheclosesttowhattheyareusedto.In addition,JavaScriptprovidesthenewoperator,whichcanfurthersuggestthatJavaScriptislikeJava.Thetruthisthat,intheend,itallcomesdowntoobjects.Thefirst exampleinthischapterusedthissyntax:
Child.prototype=newParent();
Here,theChildconstructor(orclass,ifyouwill)inheritsfromParent.However,thisisdonebycreatinganobjectusingnewParent()andinheritingfromit.That'swhythisisalsoreferredtoasapseudo-classicalinheritancepattern,becauseitresemblesclassicalinheritance,althoughitisn't(noclassesareinvolved).
So,whynotgetridofthemiddleman(theconstructor/class)andjusthave objectsinheritfromobjects?Inextend2(),thepropertiesoftheparentprototypeobjectwerecopiedaspropertiesofthechildprototypeobject.Thetwoprototypesare,inessence,justobjects.Forgettingaboutprototypesandconstructorfunctions,youcansimplytakeanobjectandcopyallofitspropertiesintoanotherobject.
You already know that objects can start as a blank canvas without any own properties, using varo = {};, and then get properties later. However, instead of starting fresh, you can start bycopying all of the properties of an existing object. Here's a function that does exactly this: it takesanobjectandreturnsanewcopyofit:
functionextendCopy(p){varc={};for(variinp){c[i]=p[i];}c.uber=p;returnc;}
Simplycopyingallthepropertiesisastraightforwardpattern,andit'swidelyused.Let'sseethisfunctioninaction.Youstartbyhavingabaseobject:
![Page 294: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/294.jpg)
varshape={name:'Shape',toString:function(){returnthis.name;}};
Inordertocreateanewobjectthatbuildsupontheoldone,youcancalltheextendCopy()function,whichreturnsanewobject.Then,youcanaugmentthenewobjectwithadditionalfunctionality:
vartwoDee=extendCopy(shape);twoDee.name='2Dshape';twoDee.toString=function(){returnthis.uber.toString()+','+this.name;
};
Hereisatriangleobjectthatinheritsthe2Dshapeobject:
vartriangle=extendCopy(twoDee);triangle.name='Triangle';triangle.getArea=function(){returnthis.side*this.height/2;};
Usingthetriangle,forexample:
>triangle.side=5;>triangle.height=10;>triangle.getArea();25>triangle.toString();"Shape,2Dshape,Triangle"
Apossible drawback of this method is the somewhat verbose way of initializing the newtriangleobject,where youmanuallysetvaluesforsideandheight,asopposedtopassingthemasvaluestoaconstructor.However,thisiseasilyresolvedbyhavingafunction,forexample,calledinit()(or__construct()ifyoucomefromPHP)thatactsasaconstructorandacceptsinitializationparameters.Alternatively,haveextendCopy()accepttwoparameters,anobjecttoinheritfromandanotherobjectliteralofpropertiestoaddtothe copybeforeit'sreturned.Inotherwords,justmergetwoobjects.
![Page 295: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/295.jpg)
Deep copyThe extendCopy() function discussed previously creates what is called a shallow copy of anobject, just like extend2() before that. The opposite of a shallow copy would be, naturally, adeep copy. As discussed previously (in the Heads-up when copying by reference section of thischapter),whenyoucopy objects,youonlycopypointerstothelocationinmemorywheretheobjectisstored.Thisiswhathappensinashallowcopy.Ifyoumodifyanobjectinthecopy,youalsomodifytheoriginal. Thedeepcopyavoidsthisproblem.
Thedeepcopyisimplementedinthesamewayastheshallowcopy-youloopthroughthepropertiesandcopythemonebyone.However,whenyouencounterapropertythatpointstoanobject,youcallthedeepcopyfunctionagain:
functiondeepCopy(p,c){c=c||{};for(variinp){if(p.hasOwnProperty(i)){
if (typeof p[i] === 'object') {c[i]=Array.isArray(p[i])?[]:{};deepCopy(p[i],c[i]);}else{c[i]=p[i];}}}returnc;}
Let'screateanobjectthathasarraysandasubobjectasproperties:
var parent = {numbers:[1,2,3],letters:['a','b','c'],obj:{prop:1},bool:true};
Let'stestthisbycreatingadeepcopyandashallowcopy.Unliketheshallowcopy,whenyouupdatethenumberspropertyofadeepcopy,theoriginalisnotaffected:
>varmydeep=deepCopy(parent);>varmyshallow=extendCopy(parent);
>mydeep.numbers.push(4,5,6);6>mydeep.numbers;[1,2,3,4,5,6]>parent.numbers;
![Page 296: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/296.jpg)
[1,2,3]>myshallow.numbers.push(10);4>myshallow.numbers;[1,2,3,10]>parent.numbers;[1,2,3,10]>mydeep.numbers;[1,2,3,4,5,6]
TwosidenotesaboutthedeepCopy()function:
Filteringoutnon-ownpropertieswithhasOwnProperty()isalwaysagoodideatomakesureyoudon'tcarryoversomeone'sadditionstothecoreprototypes.Array.isArray()existssinceES5becauseit'ssurprisinglyhardotherwisetotellrealarraysfromobjects.Thebestcross-browsersolution(ifyouneedtodefineisArray()inES3browsers)looksalittlehacky,butitworks:
if(Array.isArray!=="function"){Array.isArray=function(candidate){returnObject.prototype.toString.call(candidate)==='[objectArray]';};}
![Page 297: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/297.jpg)
Using object() methodBased on the idea that objects inherit from objects, Douglas Crockford advocates the use of anobject()functionthatacceptsanobjectandreturnsanewonethathastheparentasaprototype:
functionobject(o){functionF(){}F.prototype=o;returnnewF();}
Ifyouneedaccesstoanuberproperty,youcanmodifytheobject()functionasfollows:
functionobject(o){varn;functionF(){}F.prototype=o;n=newF();n.uber=o;returnn;}
UsingthisfunctionisthesameasusingextendCopy(),youtakeanobjectsuchastwoDee,createanewobjectfromit,andthenproceedtoaugmentingthenewobject:
vartriangle=object(twoDee);triangle.name='Triangle';triangle.getArea=function(){returnthis.side*this.height/2;};
Thenewtrianglestillbehavesthesameway:
>triangle.toString();"Shape,2Dshape,Triangle"
Thispatternisalsoreferredtoasprototypalinheritance,becauseyouuseaparentobjectastheprototypeofachildobject.It'salsoadoptedandbuiltuponinES5andcalledObject.create().Hereisanexample:
>varsquare=Object.create(triangle);
![Page 298: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/298.jpg)
Using a mix of prototypal inheritance andcopyingpropertiesWhenyouuseinheritance,youwillmostlikelywanttotakeanalreadyexistingfunctionalityandthenbuilduponit.Thismeanscreatinganewobjectbyinheritingfroman existingobjectandthenaddingadditionalmethodsandproperties.Youcandothiswithonefunctioncallusingacombinationofthelasttwoapproachesjustdiscussed.
Youcan:
Useprototypalinheritancetouseanexistingobjectasaprototypeof anewoneCopyallthepropertiesofanotherobjectintothenewlycreatedone:
functionobjectPlus(o,stuff){var n;
functionF(){}F.prototype=o;n=newF();n.uber=o;for(variinstuff){n[i]=stuff[i];}returnn;}
Thisfunctiontakesanobjectotoinheritfromandanotherobjectstuffthathastheadditionalmethodsandpropertiesthataretobecopied.Let'sseethisinaction.
Startwiththebaseshapeobject:
varshape={name:'Shape',toString:function(){returnthis.name;}};
Createa2Dobjectbyinheritingshapeandaddingmoreproperties.Theadditionalpropertiesaresimplycreatedwithanobjectliteral:
vartwoDee=objectPlus(shape,{name:'2Dshape',
toString: function () {returnthis.uber.toString()+','+this.name;}});
![Page 299: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/299.jpg)
Now,let'screateatriangleobjectthatinheritsfrom2Dandaddsmoreproperties:
vartriangle=objectPlus(twoDee,{name:'Triangle',getArea:function(){returnthis.side*this.height/2;},side:0,height:0});
Youcantesthowitallworksbycreatingaconcretetrianglemywithdefinedsideandheight:
varmy=objectPlus(triangle,{side:4,height:4});>my.getArea();8>my.toString();
"Shape, 2D shape, Triangle, Triangle"
Thedifferencehere,whenexecutingtoString(),isthattheTrianglenameisrepeatedtwice.That'sbecausetheconcreteinstancewascreatedbyinheritingtriangle,sotherewasonemorelevelofinheritance.Youcouldgivethenewinstanceaname:
>objectPlus(triangle,{side:4,height:4,name:'My4x4'}).toString();"Shape,2Dshape,Triangle,My4x4"
ThisobjectPlus()isevenclosertoES5'sObject.create();onlytheES5onetakestheadditionalproperties(thesecondargument)usingsomethingcalledpropertydescriptors(discussedinAppendixC,Built-InObjects).
![Page 300: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/300.jpg)
Multiple inheritanceMultiple inheritance is where a child inherits frommore than one parent. Some OO languagessupportmultipleinheritanceoutoftheboxandsomedon't.Youcanarguebothways,thatmultipleinheritanceisconvenientorthatit'sunnecessary,complicatesapplicationdesign,andit'sbettertouseaninheritancechaininstead.Leavingthediscussionofmultipleinheritance'sprosandconsforthelong,coldwinternights,let'sseehowyoucandoitinpracticeinJavaScript.
Theimplementationcanbeassimpleastakingtheideaofinheritancebycopyingpropertiesandexpandingitsothatittakesanunlimitednumberofinputobjectstoinheritfrom.
Let'screateamulti()functionthatacceptsanynumberofinputobjects.Youcanwraptheloopthatcopiespropertiesinanotherloopthatgoesthroughalltheobjectspassedasargumentstothefunction:
functionmulti(){varn={},stuff,j=0,len=arguments.length;for(j=0;j<len;j++){stuff=arguments[j];for(variinstuff){if(stuff.hasOwnProperty(i)){n[i]=stuff[i];
}}}returnn;}
Let'stestthisbycreatingthreeobjects-shape,twoDee,andathird,unnamedobject.Then,creatingatriangleobjectmeanscallingmulti()andpassingallthreeobjects:
varshape={name: 'Shape',
toString:function(){returnthis.name;}};
vartwoDee={name:'2Dshape',dimensions:2};
vartriangle=multi(shape,twoDee,{name:'Triangle',getArea:function(){returnthis.side*this.height/2;},side:5,
![Page 301: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/301.jpg)
height:10});
Doesthiswork?Let'ssee.ThegetArea()methodshouldbeanownproperty,dimensionsshouldcomefromtwoDee,andtoString()shouldcomefromshape:
>triangle.getArea();25>triangle.dimensions;2>triangle.toString();"Triangle"
Bearinmindthatmulti()loopsthroughtheinputobjectsintheordertheyappearandifithappensthattwoofthemhavethesameproperty, thelastonewins.
![Page 302: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/302.jpg)
Mixins
Youmightcomeacrossthetermmixin.Thinkofamixinasanobjectthatprovidessomeusefulfunctionalitybutisnotmeanttobeinheritedandextendedbysubobjects.Theapproachtomultipleinheritanceoutlinedpreviouslycanbeconsideredanimplementationofthemixinsidea.Whenyoucreateanewobject,youcanpickandchooseanyotherobjectstomixintoyournewobject.Bypassingthemalltomulti(),yougetalltheirfunctionalitywithoutmakingthempartoftheinheritancetree.
![Page 303: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/303.jpg)
Parasitic inheritanceIf you like the fact that you can have all kinds of different ways to implement inheritance inJavaScriptandyou'rehungryformore,here'sanotherone.Thispattern,courtesyofDouglasCrockford,iscalledparasiticinheritance.It'saboutafunctionthatcreatesobjectsbytakingallthefunctionalityfromanotherobjectintoanewone,augmentingthenewobject,andreturningit,pretendingthatithasdoneallthework.
Here'sanordinaryobject,definedwithanobject literal,andunawareofthefactthatit'ssoongoingtofallvictimtoparasitism:
vartwoD={name:'2Dshape',dimensions:2};
A function that creates triangle objects could:
UsethetwoDobjectasaprototypeofanobjectcalledthat(similartothisforconvenience).Thiscanbedoneinanywayyousawpreviously,forexample,usingtheobject()functionorcopyingalltheproperties.Augmentthatwithmoreproperties.Returnthat:
functiontriangle(s,h){varthat=object(twoD);that.name='Triangle';
that.getArea = function () {returnthis.side*this.height/2;};that.side=s;that.height=h;returnthat;}
Becausetriangle()isanormalfunction,notaconstructor,itdoesn'trequirethenewoperator.However,becauseitreturnsanobject,callingitwithnewbymistakeworkstoo:
>vart=triangle(5,10);>t.dimensions;2>vart2=newtriangle(5,5);>t2.getArea();12.5
Notethatthatisjustaname,itdoesn'thaveaspecialmeaning,thewaythisdoes.
![Page 304: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/304.jpg)
Borrowing a constructorOne more way of implementing inheritance (the last one in the chapter, I promise) has to do againwithconstructorfunctionsandnottheobjectsdirectly.Inthispattern,theconstructorofthechildcallstheconstructoroftheparentusingeitherthe call()orapply()method.Thiscanbecalledstealingaconstructororinheritancebyborrowingaconstructorifyouwanttobemoresubtleaboutit.
Thecall()andapply()methodswerediscussedinChapter4,Objects, buthere'sarefresher;theyallowyoutocallafunctionandpassanobjectthatthefunctionshouldbindtoitsthisvalue.Soforinheritancepurposes,thechildconstructorcallstheparent'sconstructorandbindsthechild'snewlycreatedthisobjectastheparent'sthis.
Let'shavethisparentconstructorShape():
functionShape(id){this.id=id;}Shape.prototype.name='Shape';Shape.prototype.toString=function(){returnthis.name;};
Now,let'sdefineTriangle(),whichusesapply()tocalltheShape()constructor,passingthis(aninstancecreatedwithnewTriangle())andanyadditionalarguments:
functionTriangle(){Shape.apply(this,arguments);}Triangle.prototype.name='Triangle';
NotethatbothTriangle()andShape()haveaddedsomeextrapropertiestotheirprototypes.
Now,let'stestthisbycreatinganewtriangleobject:
>vart=newTriangle(101);>t.name;"Triangle"
Thenewtriangleobjectinheritstheidpropertyfromtheparent,butitdoesn'tinheritanythingaddedtotheparent'sprototype:
>t.id;101>t.toString();"[objectObject]"
![Page 305: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/305.jpg)
ThetrianglefailedtogettheShapefunction'sprototypepropertiesbecausetherewasneveranewShape()instancecreated,sotheprototypewasneverused.However,yousawhowtodothisatthebeginningofthischapter.YoucanredefineTriangleasfollows:
functionTriangle(){Shape.apply(this,arguments);}Triangle.prototype=newShape();Triangle.prototype.name='Triangle';
Inthisinheritancepattern,theparent'sownpropertiesarerecreatedasthechild'sownproperties.Ifachildinheritsanarrayorotherobject,it'sacompletelynewvalue(notareference),andmodifyingitwon'taffecttheparent.
Thedrawbackisthatthe parent'sconstructorgetscalledtwice-oncewithapply()toinheritownpropertiesandoncewithnewtoinherittheprototype.Infact,theownpropertiesoftheparentareinheritedtwice.Let'stakethissimplifiedscenario:
functionShape(id){this.id=id;}functionTriangle(){Shape.apply(this,arguments);}Triangle.prototype=newShape(101);
Here,wewillcreateanewinstance:
>vart=newTriangle(202);>t.id;202
There'sanownpropertyid,butthere'salsoonethatcomesdowntheprototypechain,readytoshinethrough:
>t.__proto__.id;101>deletet.id;true
>t.id;101
![Page 306: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/306.jpg)
Borrowingaconstructorandcopyingitsprototype
Theproblemofthedoubleworkperformedbycallingtheconstructortwicecaneasilybecorrected.Youcancallapply()ontheparentconstructortogetallownpropertiesandthencopytheprototype'spropertiesusingasimpleiteration(orextend2()asdiscussedpreviously):
function Shape(id) {this.id=id;}Shape.prototype.name='Shape';Shape.prototype.toString=function(){returnthis.name;};
functionTriangle(){Shape.apply(this,arguments);}extend2(Triangle,Shape);Triangle.prototype.name='Triangle';
Letstestthefollowingcode:
>vart=newTriangle(101);>t.toString();"Triangle">t.id;101
Nodoubleinheritance:
>typeoft.__proto__.id;"undefined"
Theextend2()methodalsogivesaccesstouberifneeded:
>t.uber.name;"Shape"
![Page 307: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/307.jpg)
Case study - drawing shapesLet's finish off this chapter with a more practical example of using inheritance. The task is to beabletocalculatetheareaandtheperimeterofdifferentshapes,aswellastodrawthem,whilereusingasmuchcodeaspossible.
![Page 308: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/308.jpg)
Analysis
Let'shaveoneShapeconstructorthatcontainsallthecommonparts.Fromthere,let'shaveTriangle,Rectangle,andSquareconstructors,allinheritingfromShape.Asquareisreallyarectanglewiththesamelengthsides,solet'sreuseRectanglewhenbuildingSquare.
Inordertodefineashape,you'llneedpointswithxandycoordinates.Agenericshapecanhaveanynumberofpoints.Atriangleisdefinedwiththreepoints,arectangle(tokeepitsimpler)withonepointandthelengthsofthesides.Theperimeterofanyshapeisthesumofitsside'slengths.Calculatingtheareaisshapespecificandwillbeimplementedbyeachshape.
ThecommonfunctionalityinShapewouldbe:
Adraw()methodthatcandrawanyshapegiventhepointsAgetParameter()methodApropertythatcontainsanarrayofpointsOthermethodsandpropertiesasneeded
Forthedrawingpart,let'susea<canvas>tag.It'snotsupportedinearlyIEs,buthey,thisisjustanexercise.
Let'shavetwootherhelperconstructors-PointandLine.Pointwillhelpwhendefiningshapes.Linewillmakecalculationseasier,asitcangivethelengthofthelineconnectinganytwogivenpoints.
Youcanplaywithaworkingexampleathttp://www.phpied.com/files/canvas/.Justopenyourconsoleandstartcreatingnewshapesasyou'llseeinamoment.
![Page 309: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/309.jpg)
Implementation
Let'sstartbyaddingacanvastagtoablankHTMLpage:
<canvasheight="600"width="800"id="canvas"/>
Then,puttheJavaScriptcodeinside<script>tags:
<script>// ... code goes here
</script>
Now,let'stakealookatwhat'sintheJavaScriptpart.FirstisthehelperPointconstructor.Itjustcan'tgetanysimplerthanthefollowing:
functionPoint(x,y){this.x=x;this.y=y;}
Bear in mind that the coordinates of the points on the canvas start from x=0, y=0, which is the topleft. The bottom right will be x = 800, y = 600:
NextcomestheLineconstructor.Ittakestwopointsandcalculatesthelengthofthelinebetween
them,usingthePythagoreantheorema2+b2=c2(imaginearight-angledtrianglewherethehypotenuseconnectsthetwogivenpoints):
function Line(p1, p2) {
![Page 310: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/310.jpg)
this.p1=p1;this.p2=p2;this.length=Math.sqrt(Math.pow(p1.x-p2.x,2)+Math.pow(p1.y-p2.y,2));}
NextcomestheShapeconstructor.Theshapeswillhavetheirpoints(and thelinesthatconnectthem)asownproperties.Theconstructoralsoinvokesaninitializationmethod,init(),thatwillbedefinedintheprototype:
functionShape(){this.points=[];this.lines=[];this.init();}
Now,thebigpart-themethodsofShape.prototype.Let'sdefineallthesemethodsusingtheobjectliteralnotation.Refertothecommentsforguidelinesastowhateachmethoddoes:
Shape.prototype={//resetpointertoconstructorconstructor:Shape,
// initialization, sets this.context to point//tothecontextifthecanvasobjectinit:function(){if(this.context===undefined){varcanvas=document.getElementById('canvas');Shape.prototype.context=canvas.getContext('2d');}},
//methodthatdrawsashapebyloopingthroughthis.pointsdraw:function(){vari,ctx=this.context;ctx.strokeStyle=this.getColor();ctx.beginPath();ctx.moveTo(this.points[0].x,this.points[0].y);for(i=1;i<this.points.length;i++){ctx.lineTo(this.points[i].x,this.points[i].y);}ctx.closePath();ctx.stroke();},
//methodthatgeneratesarandomcolorgetColor:function(){vari,rgb=[];
for (i = 0; i< 3; i++) {rgb[i]=Math.round(255*Math.random());
![Page 311: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/311.jpg)
}return'rgb('+rgb.join(',')+')';},
//methodthatloopsthroughthepointsarray,//createsLineinstancesandaddsthemtothis.linesgetLines:function(){if(this.lines.length>0){returnthis.lines;}vari,lines=[];for(i=0;i<this.points.length;i++){lines[i]=newLine(this.points[i],this.points[i+1]||this.points[0]);}this.lines=lines;returnlines;},
//shellmethod,tobeimplementedbychildrengetArea:function(){},
//sumsthelengthsofalllinesgetPerimeter:function(){vari,perim=0,lines=this.getLines();for(i=0;i<lines.length;i++){perim+=lines[i].length;}returnperim;}};
Now,thechildrenconstructorfunctions.Trianglecomesfirst:
functionTriangle(a,b,c){this.points=[a,b,c];this.getArea=function(){varp=this.getPerimeter(),s=p/2;returnMath.sqrt(s*(s-this.lines[0].length)*(s-this.lines[1].length)*(s-this.lines[2].length));};}
TheTriangleconstructortakesthreepointobjectsandassignsthemtothis.points(itsowncollectionofpoints).Then,itimplementsthegetArea()method,usingHeron'sformula:
Area=s(s-a)(s-b)(s-c)
sisthesemi-perimeter(perimeterdividedbytwo).
![Page 312: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/312.jpg)
NextcomestheRectangleconstructor.Itreceivesonepoint(theupper-leftpoint)andthelengthsofthetwosides.Then,itpopulatesitspointsarraystartingfromthatonepoint:
functionRectangle(p,side_a,side_b){this.points=[p,newPoint(p.x+side_a,p.y),//toprightnewPoint(p.x+side_a,p.y+side_b),//bottomrightnewPoint(p.x,p.y+side_b)//bottomleft];
this.getArea = function () {returnside_a*side_b;};}
ThelastchildconstructorisSquare.Asquareisaspecialcaseofarectangle,soitmakessensetoreuseRectangle.Theeasiestthingtodohereistoborrowtheconstructor:
functionSquare(p,side){Rectangle.call(this,p,side,side);
}
Nowthatallconstructorsaredone,let'stakecareofinheritance.Anypseudo-classicalpattern(onethatworkswithconstructorsasopposedtoobjects)willdo.Let'stryusingamodifiedandsimplifiedversionoftheprototype-chainingpattern(thefirstmethoddescribedinthischapter).Thispatterncallsforcreatinganewinstanceoftheparentandsettingitasthechild'sprototype.Inthiscase,it'snotnecessarytohaveanewinstanceforeachchild-theycanallshareit:
(function () {vars=newShape();Triangle.prototype=s;Rectangle.prototype=s;Square.prototype=s;})();
![Page 313: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/313.jpg)
Testing
Let'stestthisbydrawingshapes.First,definethreepointsforatriangle:
>var p1 = new Point(100, 100);>varp2=newPoint(300,100);>varp3=newPoint(200,0);
NowyoucancreateatrianglebypassingthethreepointstotheTriangleconstructor:
>vart=newTriangle(p1,p2,p3);
Youcancallthemethodstodrawthetriangleonthecanvasandgetitsareaandperimeter:
>t.draw();>t.getPerimeter();482.842712474619>t.getArea();10000.000000000002
Nowlet'splaywitharectangleinstance:
>varr=newRectangle(newPoint(200,200),50,100);>r.draw();>r.getArea();5000>r.getPerimeter();300
Andfinally,let'splaywithasquare:
>vars=newSquare(newPoint(130,130),50);>s.draw();>s.getArea();2500>s.getPerimeter();200
It'sfuntodrawtheseshapes.Youcanalsobeaslazyasthefollowingexample,whichdrawsanothersquare,reusingatriangle'spoint:
> new Square(p1, 200).draw();
Theresultofthetestswillbesomethinglikethefollowing:
![Page 314: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/314.jpg)
![Page 315: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/315.jpg)
ExercisesLets do the following exercise:
1. Implementmultipleinheritancebutwithaprototypalinheritancepattern,notpropertycopying.Hereisan example:
varmy=objectMulti(obj,another_obj,a_third,{additional:"properties"});
The additional property should be an own property; all the rest should be mixed into theprototype.
2. Usethecanvasexampletopractice.Tryoutdifferentthings.Herearesomeexamples:Drawafewtriangles,squares,andrectangles.Addconstructorsformoreshapes,suchasTrapezoid,Rhombus,Kite,andPentagon.Ifyouwanttolearnmoreaboutthecanvastag,createaCircleconstructortoo.Itwillneedtooverwritethedraw()methodoftheparent.Canyouthinkofanotherwaytoapproachtheproblemanduseanothertypeofinheritance?Pickoneofthemethodsthatusesuberasawayforachildtoaccessitsparent.Addfunctionalitywheretheparentscankeeptrackofwhotheirchildrenare,perhapsusingapropertythatcontainsachildrenarray?
![Page 316: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/316.jpg)
SummaryIn this chapter, you learned quite a few ways (patterns) of implementing inheritance, and thefollowingtablesummarizesthem.Thedifferenttypescanroughlybedividedintothefollowing:
PatternsthatworkwithconstructorsPatternsthatworkwithobjects
Youcanalsoclassifythepatternsbasedonwhetherthey:
UsetheprototypeCopypropertiesDoboth(copypropertiesoftheprototype):
# Name Example Classification Notes
1
Prototypechaining
(pseudo-classical)
Child.prototype=newParent();
WorkswithconstructorsUsestheprototypechain
ThedefaultmechanismTip-moveallproperties/methodsthataremeanttobereusedtotheprototype,andaddthenon-reusableas own properties
2Inheritonlytheprototype
Child.prototype=Parent.prototype;
WorkswithconstructorsCopiestheprototype(noprototypechain,asallsharethesameprototypeobject)
Moreefficient;nonewinstancesarecreatedjustforthesakeofinheritancePrototypechainlookupduringruntime;itisfast,sincethere'snochainDrawback:childrencanmodifyparents'functionality
3Temporaryconstructor
functionextend(Child,Parent){varF=function(){};F.prototype=Parent.prototype;Child.prototype = new F();Child.prototype.constructor=Child;Child.uber=Parent.prototype;}
Works withconstructorsUsestheprototypechain
Unlike#1,itonlyinheritspropertiesofthe prototype; own properties(createdwiththisinsidetheconstructor)arenotinherited.Providesconvenientaccesstotheparent(throughuber)
4Copyingtheprototype
properties
functionextend2(Child,Parent){varp=Parent.prototype;varc=Child.prototype;for(variinp){c[i]=p[i];}c.uber=p;}
WorkswithconstructorsCopiespropertiesUsestheprototypechain
AllpropertiesoftheparentprototypebecomepropertiesofthechildprototypeNoneedtocreateanewobjectonlyforinheritancepurposesShorterprototypechains
![Page 317: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/317.jpg)
5
Copyallproperties
(shallowcopy)
functionextendCopy(p){varc={};for(variinp){c[i]=p[i];}c.uber=p;returnc;}
Works with objectsCopiesproperties
SimpleDoesn'tuseprototypes
6 DeepcopySameasthepreviousone,butrecurseintoobjects
WorkswithobjectsCopiesproperties
Sameas#5,butclonesobjectsandarrays
7Prototypalinheritance
functionobject(o){functionF(){}F.prototype=o;returnnewF();}
WorkswithobjectsUsestheprototypechain
Nopseudo-classes,objectsinheritfrom objectsLeveragesthebenefitsoftheprototype
8Extendandaugment
functionobjectPlus(o,stuff) {varn;functionF(){}F.prototype=o;n=newF();n.uber=o;for(variinstuff){n[i]=stuff[i];}returnn;}
WorkswithobjectsUsestheprototypechainCopiesproperties
Mixofprototypalinheritance(#7)andcopyingproperties(#5)Onefunctioncalltoinheritandextendatthesametime
9Multipleinheritance
functionmulti(){varn={},stuff,j=0,len=arguments.length;for(j=0;j<len;j++){stuff=arguments[j];for(variinstuff){n[i]=stuff[i];}}returnn;}
WorkswithobjectsCopiesproperties
Amixin-styleimplementationCopiesallthepropertiesofalltheparentobjectsintheorderofappearance
10Parasiticinheritance
functionparasite(victim){varthat=object(victim);that.more=1;returnthat;}
WorkswithobjectsUsestheprototypechain
Constructor-likefunctioncreatesobjectsCopiesanobject,andaugmentsandreturnsthecopy
11Borrowingconstructors
functionChild(){Parent.apply(this,arguments);}
Workswithconstructors
InheritsonlyownpropertiesCanbecombinedwith#1toinherittheprototypetooConvenientwaytodealwiththeissues whenachildinheritsapropertythatis anobject(andtherefore,passed by reference)
functionChild(){ Workswith Combinationof#11and#4
![Page 318: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/318.jpg)
12Borrowaconstructorandcopytheprototype
Parent.apply(this,arguments);}extend2(Child,Parent);
constructorsUsestheprototypechainCopiesproperties
Allowsyoutoinheritbothownpropertiesandprototypepropertieswithoutcallingtheparentconstructortwice
Givensomanyoptions,youmustbewonderingwhichistherightone.Thatdependsonyourstyleand preferences, your project, task, and team. Are you more comfortable thinking in terms ofclasses?Thenpickoneofthemethodsthatworkwithconstructors.Areyougoingtoneedjustoneorafewinstancesofyourclass?Thenchooseanobject-basedpattern.
Arethesetheonlywaysofimplementinginheritance?No.Youcanchooseapatternfromtheprecedingtable,youcanmixthem,oryoucanthinkofyourown.Theimportantthingistounderstandandbecomfortablewithobjects,prototypes,andconstructors;therestisjustpurejoy.
![Page 319: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/319.jpg)
Chapter 8. Classes and ModulesIn this chapter, we will explore some of the most interesting features introduced in ES6.JavaScriptisaprototype-basedlanguageandsupportsprototypicalinheritance.Inthepreviouschapter,wediscussedtheprototypepropertyofanobjectandhowprototypicalinheritanceworksinJavaScript.ES6bringsinclasses.Ifyouarecomingfromtraditionalobject-orientedlanguagessuchasJava,youwillimmediatelyrelatetothewell-knownconceptsofclasses.However,theyarenotthesameinJavaScript.ClassesinJavaScriptareasyntacticsugarovertheprototypicalinheritancewediscussedinthelastchapter.
Inthischapter,wewilltakeadetailedlookatES6classesandmodules-thesearewelcomechangestothiseditionofJavaScriptandmakeObjectOrientedProgramming(OOP)andinheritancesignificantlyeasier.
Ifyouarecomingfroma traditionalobject-orientedlanguage,prototypicalinheritancemayfeelabitoutofplaceforyou.ES6classesofferamoretraditionalsyntaxforyoutogetfamiliarizedwithprototypicalinheritanceinJavaScript.
Beforewetryanddelvedeeperintoclasses,letmeshowyouwhyyoushouldusetheES6classessyntaxovertheprototypicalinheritancesyntaxof ES5.
Inthissnippet,IamcreatingaclasshierarchyofPerson,Employee,andEngineer,prettystraightforward.First,wewillseetheES5prototypicalinheritance,whichiswrittenasfollows:
varPerson=function(firstname){if(!(thisinstanceofPerson)){thrownewError("Personisaconstructor");}
this.firstname = firstname;};
Person.prototype.giveBirth=function(){//...wegivebirthtotheperson};
varEmployee=function(firstname,lastname,job){if(!(thisinstanceofEmployee)){thrownewError("Employeeisaconstructor");}Person.call(this,firstname);this.job=job;};Employee.prototype=Object.create(Person.prototype);Employee.prototype.constructor=Employee;Employee.prototype.startJob=function(){//...Employeestartsjob};
![Page 320: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/320.jpg)
varEngineer=function(firstname,lastname,job,department){if(!(thisinstanceofEngineer)){thrownewError("Engineerisaconstructor");}Employee.call(this,firstname,lastname,job);this.department=department;};Engineer.prototype=Object.create(Employee.prototype);Engineer.prototype.constructor=Engineer;Engineer.prototype.startWorking=function(){//...Engineerstartsworking};
Nowlet'slookattheequivalentcodeusingtheES6classessyntax:
classPerson{constructor(firstname){this.firsnamet=firstname;}giveBirth(){//...apersonisborn}}
classEmployeeextendsPerson{constructor(firstname,lastname,job){super(firstname);this.lastname=lastname;this.position=position;}
startJob(){//...Employeestartsjob
}}
classEngineerextendsEmployee{constructor(firstname,lastname,job,department){super(firstname,lastname,job);this.department=department;}
startWorking(){//...Engineerstartsworking}}
Ifyouobservethetwoprecedingcodesnippets,itwillbeobvioustoyouthatthesecondexampleisprettyneat.IfyoualreadyknowJavaorC#,youwillfeelrightathome.However,oneimportantthingtorememberisthatclassesdonotintroduceanynewobject-orientedinheritancemodeltothelanguage,butbringinamuchnicerwaytocreateobjectsandhandleinheritance.
![Page 321: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/321.jpg)
Defining classesUnder the hood, classes are special functions. Just like you can define functions using functionexpressionsanddeclarations,youcandefineclassesaswell.Onewaytodefineclassesisusingclassdeclaration.
Youcanusetheclasskeywordandthenameoftheclass.ThissyntaxisverysimilartothatofJavaorC#:
classCar{constructor(model,year){this.model=model;this.year=year;}}console.log(typeofCar);//"function"
Toestablishthefactthatclassesareaspecialfunction,ifwegetthetypeoftheCarclass,wewillgetafunction.
Thereisanimportantdistinctionbetweenclassesandnormalfunctions.Whilenormalfunctionsarehoisted,classesarenot.Anormalfunctionisavailableimmediatelywhenyouenterascopeinwhichitisdeclared;thisiscalledhoisting,whichmeansthatanormalfunctioncanbedeclaredanywhereinthescope,anditwillbeavailable.However,classesarenothoisted;theyare available only after they are declared. For a normal function, you can say:
normalFunction();//usefirstfunctionnormalFunction(){}//declarelater
However,youcannotusetheclassbeforedeclaringit,forexample:
varford=newCar();//ReferenceErrorclassCar{}
Theotherwaytodefineaclassistouseaclassexpression.Aclassexpression,likeafunctionexpression,mayormaynothaveaname.
Thefollowingexampleshowsananonymousclassexpression:
constCar=class{constructor(model,year){this.model=model;this.year=year;}}
Ifyounametheclassexpression,thenameislocaltotheclass'sbodyand notavailableoutside:
![Page 322: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/322.jpg)
constNamedCar=classCar{constructor(model,year){this.model=model;this.year=year;}getName(){returnCar.name;}}constford=newNamedCar();console.log(ford.getName());//Carconsole.log(ford.name);//ReferenceError:nameisnotdefined
Asyoucansee,here,wewillgiveanametotheCarclass.Thisnameisavailablewithinthebodyoftheclass,butwhenwetrytoaccessitoutsidetheclass,wegetareferenceerror.
Youcannotusecommaswhileseparatingmembersofaclass.Semicolonsarevalidthough.ThisisfunnyasES6ignoressemicolonsandthereisaragingdebateaboutusingsemicolonsinES6.Considerthefollowingcodesnippetasanexample:
classNoCommas{method1(){}
member1;//Thisisignoredandcanbeusedtoseparateclassmembersmember2,//Thisisanerrormethod2(){}}
Oncedefined,wecanuseclassesviaanewkeywordandnotafunctioncall;here'stheexample:
class Car {constructor(model,year){this.model=model;this.year=year;}}constfiesta=newCar('Fiesta','2010');
![Page 323: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/323.jpg)
Constructor
Wehaveusedtheconstructorfunctionintheexamplessofar.Aconstructorisaspecialmethodusedtocreateandinitializeanobjectcreatedwiththeclass.Youcanhaveonlyoneconstructorinaclass.Constructorsareabitdifferentfromthenormalconstructorfunctions.Unlikenormalconstructors,aclassconstructorcancallitsparentclassconstructorviasuper().Wewilldiscussthisindetailwhenwelookatinheritance.
![Page 324: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/324.jpg)
Prototypemethods
Prototypemethodsareprototypepropertiesoftheclass,andtheyareinheritedbyinstancesoftheclass.
Prototypemethodscanalsohavegetterandsettermethods.ThesyntaxofgettersandsettersisthesameasES5:
classCar{constructor(model,year){this.model=model;
this.year = year;}getmodel(){returnthis.model}calculateCurrentValue(){return"7000"}}constfiesta=newCar('Fiesta','2010')console.log(fiesta.model)
Similarly,computedpropertiesarealsosupported.Youcandefinethenameofthemethodusingtheexpression.Theexpressionneedstobeputinsidesquarebrackets.Wediscussedthisshorthandsyntaxinearlierchapters.Thefollowingareallequivalent:
classCarOne{driveCar(){}}classCarTwo{['drive'+'Car'](){}}
const methodName = 'driveCar';classCarThree{[methodName](){}}
![Page 325: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/325.jpg)
Staticmethods
Staticmethodsareassociatedwiththeclassandnotwithaninstanceofthatclass(object).Inotherwords,youcanonlyreachastaticmethodusingthenameoftheclass.Staticmethodsareinvokedwithoutinstantiatingtheclassandtheycannotbecalledonaninstanceofaclass.Staticmethodsarepopularincreatingutilityorhelpermethods.Considerthefollowingpieceofcode:
classLogger{staticlog(level,message){console.log(`${level}:${message}`)}}//InvokestaticmethodsontheClassLogger.log("ERROR","Theendisnear")//"ERROR:Theendisnear"
//Notoninstanceconstlogger=newLogger("ERROR")logger.log("Theendisnear")//logger.logisnotafunction
![Page 326: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/326.jpg)
Staticproperties
Youmayask-well,wehavestaticmethods,whataboutstaticproperties?InthehurryofgettingES6ready,theydidnotaddstaticproperties.Theywillbeaddedinfutureiterationsofthelanguage.
![Page 327: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/327.jpg)
Generatormethods
Wediscussedhugelyusefulgeneratorfunctionsafewchaptersback.Youcanaddgeneratorfunctionsaspartofclass,andtheyarecalledgeneratormethods.AgeneratormethodisusefulbecauseyoucandefinetheirkeyasSymbol.iterator.Thefollowingexampleshowshowgeneratormethodscanbedefinedinsideaclass:
classiterableArg{constructor(...args){this.args=args;}*[Symbol.iterator](){for(constargofthis.args){yieldarg;}
}}
for(constxofnewiterableArg('ES6','wins')){console.log(x);}
//ES6//wins
![Page 328: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/328.jpg)
SubclassingSo far, we discussed how to declare classes and the types of members classes can support. Amajoruseofaclassistoserveasatemplatetocreateothersubclasses.Whenyoucreateachildclassfromaclass,youderivepropertiesoftheparentclassandextendtheparentclassbyaddingmorefeaturesofitsown.
Let'slookatthefollowingdefactoexampleofinheritance:
class Animal {constructor(name){this.name=name;}speak(){console.log(this.name+'genericnoise');}}classCatextendsAnimal{speak(){console.log(this.name+'saysMeow.');}}varc=newCat('Grace');c.speak();//"GracesaysMeow."
Here,AnimalisthebaseclassandtheCatclassisderivedfromtheclassAnimal.Theextendclauseallowsyoutocreateasubclassofanexistingclass.Thisexampledemonstratesthesyntaxofsubclassing.Let'senhancethisexampleabitmorebywritingthefollowingcode:
classAnimal{constructor(name){this.name=name;}speak(){console.log(this.name+'genericnoise');}}classCatextendsAnimal{speak(){console.log(this.name+'saysMeow.');}}classLionextendsCat{speak(){super.speak();console.log(this.name+'Roars....');}}varl=newLion('Lenny');l.speak();
![Page 329: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/329.jpg)
//"LennysaysMeow."//"LennyRoar...."
Here,weareusingthesuperkeywordtocallfunctionsfromtheparentclass.Thefollowingarethethreewaysinwhichthesuperkeywordcanbeused:
You can use super (<params>) as a function call to invoke the constructor of the parentclassYoucanusesuper.<parentClassMethod>toaccesstheparentclassmethodsYoucanusesuper.<parentClassProp>toaccesstheparentclassproperties
Inthederiveclassconstructor,youmustcallthesuper()methodbeforeyoucanuse,thiskeyword;forexample,thefollowingpieceofcodewillfail:
classBase{}classDeriveextendsBase{constructor(name){this.name=name;//'this'isnotallowedbeforesuper()}}
Youcan'timplicitlyleaveaderivedconstructorwithasuper()methodasanerror:
classBase{}classDeriveextendsBase{constructor(){//missingsuper()callinconstructor}}
Ifyoudon'tprovideaconstructorforthebaseclass,thefollowingconstructorisused:
constructor(){}
Forthederivedclasses,thedefaultconstructorisasfollows:
constructor(...args){super(...args);
}
![Page 330: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/330.jpg)
Mixins
JavaScriptsupportsonlysingleinheritance.Atmost,aclasscanhaveonesuperclass.Thisislimitingwhenyouwanttocreateclasshierarchiesbutalsowanttoinherittoolmethodsfromdifferentsources.
Let'ssaywehaveascenariowherewehaveaPersonclass,andwecreateasubclass,Employee:
classPerson{}classEmployeeextendsPerson{}
Wealsowanttoinheritfunctionsfromtwoutility classes,BackgroundCheck-thisclassdoesemployeebackgroundchecks-andOnboard-thisclasshandlesemployeeonboardingprocesses,suchasprintingbadgesandsoon:
classBackgroundCheck{check(){}}classOnboard{printBadge(){}}
BothBackgroundCheckandOnboardclassesaretemplates,andtheirfunctionalitywillbeusedmultipletimes.Suchtemplates(abstractsubclasses)arecalledmixins.
As multiple inheritance is not possible in JavaScript, we will employ a different technique toachievethis.ApopularwayofimplementingmixinsinES6istowriteafunctionwithasuperclassasaninputandasubclassextendingthatsuperclassastheoutput,forexample:
classPerson{}constBackgroundCheck=Tools=>classextendsTools{check(){}};constOnboard=Tools=>classextendsTools{printBadge(){}};classEmployeeextendsBackgroundCheck(Onboard(Person)){}
ThisessentiallymeansthatEmployeeisasubclassofBackgroundCheck,whichinturnisasubclassofOnboard,whichinturnisasubclassofPerson.
![Page 331: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/331.jpg)
ModulesJavaScript modules are not new. In fact, there were have been libraries that support modules forsometimenow.ES6,however,offersbuilt-inmodules.Traditionally,JavaScript'smajorusewasonbrowsers,wheremostoftheJavaScriptcodewaseitherembeddedorsmallenoughtomanagewithoutmuchtrouble.Thingshavechanged.JavaScriptprojectsarenowonamassivescale.Withoutanefficientsystemofspreadingthecode intofilesanddirectories,managingcodebecomesanightmare.
ES6modulesarefiles.Onemoduleperfileandonefilepermodule.Thereisnomodulekeyword.Whatevercodeyouwriteinthemodulefileislocaltothemoduleunlessyouexportit.Youmayhaveabunchoffunctionsinamodule,andyouwanttoexportonlyafewofthem.Youcanexportmodulefunctionalityinacoupleofways.
Thefirstwayistousetheexportkeyword.Youcanexportanytop-level function,class,var,let,orconst.
The following example shows a module inside server.js where we export a function, aclass, and a const. We don't export the processConfig() function, and any file importing thismodule won't be able to access the unexported function:
//----------------server.js---------------------exportconstport=8080;exportfunctionstartServer(){//...startserver}exportclassConfig{//...}functionprocessConfig(){//...}
Anycodethathasaccesstoserver.jscanimporttheexportedfunctionality:
//--------------app.js----------------------------import{Config,startServer}from'server'startServer(port);
Inthiscase,anotherJavaScriptfileisimportingConfigandstartServerfromtheservermodule(withthecorrespondingJavaScriptfileserver.js,wedropthefileextension).
Youcanalsoimporteverythingthatwasexportedfromthemodule:
import*from'server'
![Page 332: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/332.jpg)
Ifyouhaveonlyonethingtoexport,youcanusethedefaultexportsyntax. Considerthefollowingpieceofcodeasanexample:
//----------------server.js---------------------exportdefaultclass{//...}//--------------app.js----------------------------importServerfrom'server';consts=newServer();
Inthisexample,wewillkeeptheclassanonymousaswecanusethemodulenameitselfasthereferenceoutside.
BeforeES6modules,externallibrariessupportedseveralapproachestomodules.Theyestablishedfairlygoodguidelines/stylesforES6tofollow.ThefollowingstyleisfollowedbyES6:
Modulesaresingletons.Amoduleisimportedonlyonce,evenifyoutrytoimportitseveraltimesinyourcode.Variable,functions, andothertypeofdeclarationsarelocaltothemodule.Onlydeclarationsmarkedwithexportareavailableoutsidethemoduleforimport.Modulescanimportfromothermodules.Thefollowingarethethreeoptionsforreferringtoothermodules:
Youcanuserelativepaths("../lib/server");thesepathsareresolvedrelativelytothefileimportingthemodule.Forexample,ifyouareimportingthemodulefrom<project_path>/src/app.js,andthemodulefileislocatedat<project_path>/lib/server.js,youwillneedtoprovidea pathrelativetotheapp.js-../lib/serverinthiscase.Absolutepathscanalsopointtothemodulefiledirectly.Youcandropthefile.jsextensionwhileimportingthemodule.
BeforewegointomoredetailsoftheES6modulesystem,weneedtounderstandhowES5supportedthemviaexternallibraries.ES5hastwonon-compatiblemodulesystems,whichareasfollows:
CommonJS:ThisisthedominantstandardasNode.jsadopteditAMD(AsynchronousModuleDefinition):ThisisslightlymorecomplicatedthanCommonJSanddesignedforasynchronousmoduleloading,andtargetedtowardbrowsers
ES6moduleswereaimedtobeeasytouseforengineerscomingfromanyofthesesystems.
![Page 333: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/333.jpg)
Exportlists
Insteadoftaggingeachexportedfunctionorclassfromyourmodulewiththeexportkeyword,youcanwriteasinglelistofallthethingsyouwanttoexportfromthemodule,whichareasfollows:
export{port,startServer,Config};constport=8080;functionstartServer(){//...startserver
}classConfig{//...}functionprocessConfig(){//...}
Thefirstlineofthemoduleisthelistofexports.Youcanhavemultipleexportlistsinthemodulefileandthelistcanappearanywhereinthefile.Youcanalsohaveamixofexportlistandexportdeclarationsinthesamemodulefile,butyoucanexportonenameonlyonce.
Inalargeproject,therearecaseswhenyouencounternameconflicts.Supposeyouimporttwomodules,andbothofthemexportafunctionwiththesamename.Insuchcases,youcanrenametheimportsasfollows:
import{truncasStringLib}from"../lib/string.js"import{truncasMathLib}from"../lib/math.js"
Here, both the imported modules exported a name, trunc, and hence created a conflict of names.We can alias them to resolve this conflict.
Youcandotherenaming whileexportingaswell,whichisasfollows:
functionv(){}functionv2(){}export{vasfunctionV(),v2asfunctionV2(),v2asfunctionLatest()}
IfyouarealreadyusingES5modulesystems,ES6modulesmaylookredundant.However,itwasveryimportantforthelanguagetohavesupportforsuchanimportantfeature.ES6modulesyntaxisalsostandardizedandmorecompactthantheotheralternatives.
![Page 334: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/334.jpg)
SummaryIn this chapter, we focused on understanding ES6 classes. ES6 classes give formal support to thecommonJavaScriptpatternofsimulatingclass-likeinheritancehierarchiesusingfunctionsandprototypes.Theyaresyntacticsugaringoverprototype-basedOO,offeringaconvenientdeclarativeformforclasspatternswhichencourageinteroperability.ES6 classesofferamuchnicer,cleaner,andclearersyntaxforcreatingtheseobjectsanddealingwithinheritance.ES6classesprovidesupportforconstructors,instanceandstaticmethods,(prototype-based)inheritance,andsupercalls.
Sofar,JavaScriptlackedoneofthemostbasicfeatures-modules.BeforeES6,wewrotemodulesusingeitherCommonJSorAMD.ES6bringsmodulesintoJavaScriptofficially.Inthischapter,wetookadetailedlookathowmodulesareusedinES6.
ThenextchapterfocusesonanotherinterestingadditiontoES6-proxiesandpromises.
![Page 335: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/335.jpg)
Chapter 9. Promises and ProxiesThis chapter introduces the important concept of asynchronous programming and howJavaScriptisanideallanguagetoutilizeit.Theothertopicthatwewillcoverinthischapterismetaprogrammingwithproxies.ThesetwoconceptsareintroducedinES6.
Inthischapter,ourprimaryfocusistounderstandasynchronousprogramming,beforewejumpintothelanguage-specificconstructs,let'sspendtimeinunderstandingtheconceptfirst.
Thefirstmodel-thesynchronousmodel-iswhereitallbegan.Thisisthesimplestmodelofprogramming.Eachtaskisexecutedoneatatime,andonlyafterthefirsttaskcompletesexecutioncan,thenexttaskstart.Whenyouprograminthismodel,weexpectthatalltasksbeforethecurrenttaskarecompleteandthereisnoerror.Takealookatthefollowingfigure:
![Page 336: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/336.jpg)
Thesinglethreadedasynchronousmodelisafamiliarmodelweallknow.However,thismodelcanbewastefulandoptimized.Foranynontrivialprogramscomposedofseveraldifferenttasks,thismodelcanbeslow.Considerthefollowinghypotheticalscenarioasanexample:
varresult=database.query("SELECT*FROMtable");console.log("Afterreadingfromthedatabase");
Withthesynchronousmodelinmind,twotasksareexecutedoneaftertheother.Thismeansthatthesecondstatementwillonlybeexecutedoncethefirsthascompletedexecution.Assumingthe
![Page 337: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/337.jpg)
firststatementisacostlyoneandtakes10seconds(itisnormaltotakeevenmoretimetoreadfromaremotedatabase),thesecondstatementwillbeblocked.
This is a serious problemwhen you need to write high - performance and scalable systems. Thereisanotherproblemthatmanifestswhenyouarewritingprogramswhereyouneedtowriteinterfacesforhumaninteractionslikewedoonwebsitesthatrunonabrowser.Whileyouareperformingataskthatmaytakesometime,youcannotblocktheuser.Theymaybeenteringsomethinginaninputfieldwhilethecostlytaskisrunning;itwouldbeaterribleexperienceifweblockuserinputwhilewearebusydoingacostlyoperation.Insuchscenarios,thecostlytasksneedtoberuninthebackgroundwhilewecanhappilytakeinputfromtheuser.
Tosolvethis,onesolutionistospliteachtaskintoitsownthreadofcontrol.Thisiscalledthemulti-threadedorthreadedmodel.Considerthefollowingfigure:
Thedifferenceishowthetasksaresplit.Inthethreadedmodel,eachtaskisperformedinitsownthreadofcontrol.Usually,threadsaremanagedbytheoperatingsystemandcanberuninparallelon different CPU cores or on a single core with appropriate thread scheduling done by the CPU.WithmodernCPUs,thethreadedmodelcanbeextremelyoptimalinperformance.Severallanguagessupportthispopularmodel.Althoughapopularmodel,thethreadedmodelcanbecomplextoimplementinpractice.Thethreadsneedtocommunicateandcoordinatewitheachother.Inter-threadcommunicationcangettrickyveryquickly.Therearevariationsofthethreadedmodelwherethestateisimmutable.Insuchcases,themodelbecomessimpleraseachthreadisresponsibleforimmutablestateandthereisnoneedtomanagestatebetweenthreads.
![Page 338: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/338.jpg)
Asynchronous programming modelThe third model is what interests us the most. In this model, tasks are interleaved in a singlethreadofcontrol.Considerthefollowingfigure:
Theasynchronousmodelissimplerbecauseyouhaveonlyonethread.Whenyouareexecutingonetask,youaresurethatonlythattaskisbeingexecuted.Thismodeldoesn'trequirecomplexmechanismforinter-threadcoordinationand,hence,ismorepredictable.Thereisonemoredifferencebetweenthethreadedandtheasynchronousmodels;inthethreadedmodel,youdon'thaveawaytocontrolthethreadexecutionasthethreadschedulingismostlydonebytheoperatingsystem.However,intheasynchronousmodel,thereisnosuchchallenge.
In which scenarios can the asynchronous model outperform the synchronous model? If we aresimplysplittingtasksintosmallerchunks,intuitively,eventhesmallerchunkswilltakequiteanamountoftimewhenyouaddthemupintheend.
![Page 339: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/339.jpg)
Thereisasignificantfactorwehavenotyetconsidered.Whenyouexecuteatask,youwillendupwaitingonsomething-adiskread,adatabasequery,oranetworkcall;theseareblockingoperations.Whenyouenterablockedmode,yourtasksimplywaitsinthesynchronousmodel.Takealookatthefollowingfigure:
Intheprecedingdiagram,theblackblocksarewhereataskiswaitingonsomething.Whatarethetypicaloperationsthatcancausesuchablock?A taskisperformedinaCPUandRAM.AtypicalCPUandRAMcanhandledatatransferordersofmagnitudefasterthanatypicaldiscreadoranetworkcall.
![Page 340: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/340.jpg)
Tip
Pleaserefertoacomparison(https://gist.github.com/jboner/2841832)oflatenciesbetweenCPU,internalmemory,anddiscs.
Whenyourtaskswaiton anI/O(Input/Output)fromsuchsources,thelatencyisunpredictable.ForasynchronousprogramthatdoesalotofI/O,thisisarecipeforbadperformance.
The most important difference between the synchronous and asynchronous models is the way theyhandleblockingoperations.Intheasynchronousmodel,aprogram,whenfacedwithataskthatencountersablock,executesanothertaskwithoutwaitingfortheblockingoperationtofinish.Inaprogramwheretherearepotentialblocks,anasynchronousprogramoutperformsanequivalentsynchronousprogrambecauselesstimeisspentonwaiting.Aslightlyinaccuratevisualizationofsuchamodelwouldbeasseeninthefollowingfigure:
Withthisconceptualbackgroundoftheasynchronousmodelwithus,wecanlookatlanguage-specificconstructstosupportthismodel.
![Page 341: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/341.jpg)
JavaScript call stackIn JavaScript, function calls form a stack of frames. Consider the following example:
functionc(z2){console.log(newError().stack);}functionb(z1){c(z1+1);}functiona(z){b(z+1);}a(1);
//atc(evalat<anonymous>)//atb(evalat<anonymous>)//ata(evalat<anonymous>)
Whenwecallfunctiona(),thefirstframeinthestackiscreatedwithargumentstothefunctionandalllocalvariablesinthea()function.Whenfunctiona()callsfunctionb(),asecondframeiscreatedandpushedtothetopofthestack.Thisgoesonforallfunctioncalls.Whenthec()function returns, the top frame from the stack is popped out, leaving functions b() and a();this goes on until the entire stack is empty. This is necessary to maintain because once the functionfinishesexecution,JavaScriptwillneedtoknowwheretoreturn.
![Page 342: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/342.jpg)
Messagequeue
TheJavaScriptruntimecontainsamessagequeue.Thisqueuecontainsthelistofmessagestobeprocessed.ThesemessagesarequeuedinresponsetoeventssuchasclickoranHTTPresponsereceived.Eachmessageisassociatedwithacallbackfunction.
![Page 343: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/343.jpg)
Eventloop
Abrowsertabrunsinasinglethread-aneventloop.Thisloopcontinuouslypicksmessagesfromthemessagequeueandexecutesthecallbacksassociatedwiththem.Theeventloopsimplykeepspickingtasksfromthemessagequeueswhileotherprocessesaddtaskstothemessagequeue.Otherprocessessuchastimersandeventhandlersruninparallelandkeepaddingtaskstothequeue.
![Page 344: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/344.jpg)
Timers
ThesetTimeout()methodcreatesatimerandwaitsuntilitfires.Whenthetimerisexecuted,ataskisaddedtothemessagequeue.ThesetTimeOut()methodtakestwoarguments:acallback,andthedurationinmilliseconds.Aftertheduration,thecallbackisaddedtothemessagequeue.Oncethecallbackisaddedtothemessagequeue,theeventloopwilleventuallypickitupandexecuteit.Thereis,however,noguaranteewhenthecallbackwillbepickedupbytheeventloop.
Runtocompletion
Whentheeventlooppicksupamessagefromthequeue,theassociatedcallbackisruntocompletion.Thismeansthatamessageisprocessedcompletelybeforethenextmessagefromthequeueisprocessed.Thispropertygivestheasynchronousmodelasenseofpredictability.Asthereisnointerventiontopreemptanyofthemessagesinbetweenexecution,thismodelismuchsimplerthanothermodels,whereanyunitofexecutioncanbehaltedinbetween.However,oncethemessageispickedup,eveniftheexecutiontakestoolong,anyotherinteractiononthebrowserisblocked.
Events
Youcanregistereventhandlersforanobjectandreceiveresultsofamethodasynchronously.ThefollowingexampleshowshowwecansetupeventhandlersfortheXMLHttpRequestAPI:
varxhr=newXMLHttpRequest();xhr.open('GET','http://babeljs.io',true);xhr.onload=function(e){if(this.status==200){console.log("Works");}};xhr.send();
Intheprecedingsnippet, wearecreatingtheobjectoftheXMLHttpRequestclass.Oncetherequestobjectiscreated,wewillregistereventhandlersforit.Eventhandlers,suchasonload(),aretriggeredasynchronouslywhentheresponseisreceivedfromtheopen()method.
The send() method doesn't actually initiate the request, it adds the request to the message queuefor the event loop to pick it up and execute necessary callbacks associated with it.
Callbacks
TheNode.jsapplicationpopularizedthisstyleof receivingasynchronousdata.Acallbackisafunctionpassedasthelastargumenttotheasynchronousfunctioncall.
Toillustratetheusage,let'susethefollowingexampleofreadingafileinNode.js:
![Page 345: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/345.jpg)
fs.readFile('/etc/passwd',(err,data)=>{if(err)throwerr;console.log(data);});
Don'tworryaboutafewdetailshere.Weareusingthefilesystemmoduleasanfsalias.ThismodulehasareadFilemethodtoreadafileasynchronously.Wewillpassthefilepathandfilenameasthefirstargumentandacallbackfunctionasthelastargumentofthefunction.Weareusingananonymousfunctionasthecallbackintheexample.
Thecallbackfunctionhastwoarguments-erroranddata.WhenthereadFile()methodissuccessful,thecallbackfunctionreceivesdata,andifitfails,theerrorargumentwillhavetheerrordetails.
Wecanalsouseaslightlyfunctionalstyletowritethesamecallback.Considerthefollowingexample:
fs.readFile('/etc/passwd',//successfunction(data){console.log(data)},//errorfunction(error){console.log(error)
});
Thisstyleofpassingcallbacksisalsocalledcontinuous-passingstyle(CPS);thenextstepofexecutionorcontinuationispassedasaparameter.ThefollowingexamplefurtherillustratestheCPSstyleofcallbacks:
console.log("1");cps("2",functioncps_step2(val2){console.log(val2);cps("3",functioncos_step3(val3){console.log(val3);})console.log("4");});console.log("5");//15243
functioncps(val,callback){setTimeout(function(){callback(val);},0);}
Wewillprovidethecontinuation(thenextcallback)toeachstep.Thisnestedcallbackstylealso
![Page 346: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/346.jpg)
causesaproblemsometimesreferredtoascallbackhell.
CallbacksandtheCPSintroducearadicallydifferentstyleofprogramming.Althoughitiseasierto understand callbacks compared to other constructs, callbacks can create slightly difficult tounderstandcode.
![Page 347: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/347.jpg)
PromisesES6 introduces promises as an alternate to callbacks. Like callbacks, promises are used toretrievetheresultsofanasynchronousfunctioncall.Usingpromisesiseasierthancallbacksandproducesmorereadablecode.However,toimplementpromisesforyourasynchronousfunctionsrequiresmorework.
Apromiseobjectrepresentsavaluethatmaybeavailablenoworinthefuture,orpossiblynever.Asthenamesuggests,apromisemaybefulfilledorrejected.Apromiseactsasaplaceholderfortheeventualresult.
Apromisehasthreemutuallyexclusivestates,whichareasfollows:
1. Apromiseispendingbeforetheresultisready;thisistheinitialstate.2. Apromiseisfulfilledwhentheresultisready.3. Onanerror,apromiseisrejected.
Whenapendingpromiseiseitherfulfilledorrejected,associatedcallbacks/handlersthatarequeuedupbythethen()methodofthepromiseareexecuted.
ThepurposeofpromisesistoprovideabettersyntaxfortheCPScallbacks.ThetypicalCPSstyleasynchronousfunctionslikethefollowingone:
asyncFunction(arg,result=>{//...})
Theprecedingcodecanbewrittenabitdifferentlywithpromises,asshowninthefollowinglinesofcode:
asyncFunction(arg).then(result=>{//...});
Theasynchronousfunctionnowreturnsapromise,whichistheplaceholderforaneventualresult.Callbacksregisteredwiththethen()methodarenotifiedwhentheresultisready.
Youcanchainthethen()method.Whenthethen()methodseesthatthecallbacktriggeredanotherasynchronousactionthatreturnsapromise,itreturnsthatpromise.Takealookatthefollowingexample:
asyncFunction(arg).then(resultA=>{//...returnasyncFunctionB(argB);
![Page 348: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/348.jpg)
}).then(resultB=>{//...})
Let'sseearealexampleofhowwecanusepromises.WesawatypicalexampleofasynchronousfilereadsinNode.js;nowlet'sseewhatthatexamplewilllooklikewhenusedwithpromises.Tojogourmemories,wewrotesomethinglikethefollowing:
fs.readFile('text.json',function(error,text){if(error){console.error('Errorwhilereadingtextfile');}else{try{//...}catch(e){console.error('Invalidcontent');}
}});
Weseecallbacksascontinuationhere;nowlet'sseehowthesamefunctioncanbewrittenusingpromises:
readFileWithPromises('text.json').then(text=>{//...processtext}).catch(error=>{console.error('Errorwhilereadingtextfile');})
Nowthecallbacksareinvokedviatheresultandmethodsthen()andcatch().Theerrorhandlingismuchcleanerbecausewearenotwritingtheif...elseandtry...catchconstructsanymore.
![Page 349: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/349.jpg)
Creatingpromises
Wesawhowwecanconsumepromises.Now,let'slookathowwecanproducethem.
Asaproducer,youcancreateaPromiseobjectandsendaresultviathePromise.Theconstructlookslikethefollowingcodesnippet:
constp=newPromise(function(resolve,reject){//(1)if(){resolve(value);//success}else{reject(reason);//failure}});
TheparametertoPromiseisanexecutorfunction.Theexecutorhandlestwostatesofthepromise,whichareasfollows:
Resolving: If the result was generated successfully, the executor sends the results back viatheresolve()method.ThismethodusuallyfulfillsthePromiseobject.Rejecting:Ifanerrorhappened,theexecutornotifiestheconsumerviathereject()method.Ifanexceptionoccurs,itisnotified viathereject()methodaswell.
Asaconsumer,youarenotifiedofeitherfulfillmentofpromiseorrejectionofpromiseviathethen()andcatch()methods.Considerthefollowingpieceofcodeasanexample:
promise.then(result=>{/*promisefulfilled*/}).catch(error=>{/*promiserejected*/});
Nowthatwehavesomebackgroundonhowtoproducepromises,let'srewriteourearlierexampleoftheasynchronousfile'sreadmethodtoproducepromises.WewilluseNode.js'sfilesystemmoduleandthereadFile()methodaswedidlasttime.Ifyoudon'tunderstandanyNode.jsspecificconstructinthefollowingsnippet,pleasedon'tworry.Considerthefollowingcode:
import{readFile}from'fs';functionreadFileWithPromises(filename){returnnewPromise(
function (resolve, reject) {readFile(filename,(error,data)=>{if(error){reject(error);}else{resolve(data);
![Page 350: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/350.jpg)
}});});}
Intheprecedingsnippet, wearecreatinganewPromiseobjectandreturningittotheconsumer.Aswesawearlier,theparametertothePromiseobjectistheexecutorfunctionandtheexecutorfunctiontakescareoftwostatesofPromise-fulfilledandrejected.Theexecutorfunctiontakesintwoarguments,resolveandreject.ThesearethefunctionsthatnotifythestateofthePromiseobjecttotheconsumer.
Insidetheexecutorfunction,wewillcalltheactualfunction-thereadFile()method;ifthisfunctionissuccessful,wewillreturntheresultusingtheresolve()methodandifthereisanerror,wewillnotifytheconsumerusingthereject()method.
Ifanerrorhappensinoneofthethen()reactions,theyarecaughtinthesubsequentcatch()block.Takealookatthe followingcode:
readFileWithPromises('file.txt').then(result=>{'somethingcausesanexception'}).catch(error=>{'Somethingwentwrong'});
Inthiscase,thethen()reactioncausesanexceptionorerror,andthesubsequentcatch()blockcanhandlethis.
Similarly,anexceptionthrowninsideathen()orcatch()handlerispassedtothenexterrorhandler.Considerthefollowingcodesnippet:
readFileWithPromises('file.txt').then(thrownewError())
.catch(error=> {'Something went wrong'});
Promise.all()
Oneinterestingusecaseistocreateaniterableoverpromises.Let'sassumethatyouhavealistofURLsyouwanttovisitandparsetheresults.YoucancreatepromisesforeachofthefetchURLcallsandusethemindividually,oryoucancreateaniteratorwithalltheURLsandusethepromiseinonego.ThePromise.all()methodtakestheiterableofpromisesasanargument.Whenallofthepromisesarefulfilled,anarrayisfilledwiththeirresults.Considerthefollowingcodeasanexample:
Promise.all([f1(),
f2()]).then(([r1,r2])=>{//})
![Page 351: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/351.jpg)
.catch(err=>{//..});
![Page 352: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/352.jpg)
Metaprogrammingandproxies
Metaprogrammingreferstoamethodofprogrammingwheretheprogramisawareofitsstructureandcanmanipulateitself.Manylanguageshavesupportformetaprogrammingintheformofmacros.MacrosareimportantconstructsinfunctionallanguagessuchasLISP(Locator/IDSeparationProtocol).InlanguagessuchasJavaandC#,reflectionisaformofmetaprogrammingbecauseaprogramcanexamineinformationaboutitselfusingreflection.
InJavaScript,youcansaythatmethodsofobjectallowyoutoexaminethestructureandhence,theyoffermetaprogramming.Therearethreetypesofmetaprogrammingparadigms(TheArtoftheMetaobjectProtocol,Kiczalesetal,https://mitpress.mit.edu/books/art-metaobject-protocol):
Introspection:Thisgivesaread-onlyaccesstotheinternalsofaprogramSelf-modification:ThismakesstructuralchangespossibletotheprogramIntercession:Thischangeslanguagesemantics
TheObject.keys()methodisanexampleofintrospection.Inthefollowingexample,theprogramisexaminingitsownstructure:
constintrospection={intro(){console.log("IthinkthereforeIam");}}for(constkeyofObject.keys(introspection)){console.log(key);//intro}
Self-modificationisalsopossibleinJavaScriptbymutatingthepropertiesofanobject.
However,intercession,ortheabilitytochangelanguagesemantics,issomethingnotavailableinJavaScripttillES6.Proxiesareintroducedtoopenupthispossibility.
![Page 353: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/353.jpg)
Proxy
Youcanuseaproxytodeterminethebehaviorofanobject,whichiscalledthetarget,wheneveritspropertiesareaccessed.Aproxyisusedtodefinecustombehaviorforbasicoperationsonanobject,suchaslookingupaproperty,functioninvocation,andassignment.
Aproxyneedstwoparameters,whichareasfollows:
Handler:Foreachoperationyouwanttocustomize,youneedahandlermethod.Thismethodinterceptstheoperationsandissometimescalledatrap.Target:Whenthehandlerdoesnotintercepttheoperation,thetargetisusedasafallback.
Let'stakealookatthefollowingexampletounderstandthisconceptbetter:
varhandler={get:function(target,name){returnnameintarget?target[name]:42;}}varp=newProxy({},handler);p.a=100;p.b=undefined;console.log(p.a,p.b);//100,undefinedconsole.log('c'inp,p.c);//false,42
Inthisexample,wearetrappingtheoperationofgettingapropertyfromtheobject.Wereturn42asadefaultpropertyvalueifthepropertydoesnotexist.Weareusingthe gethandlertotrapthisoperation.
Youcanuseproxiestovalidatevaluesbeforesettingthemonanobject.Forthis,wecantrapthesethandlerasfollows:
letageValidator={set:function(obj,prop,value){if(prop==='age'){if(!Number.isInteger(value)){thrownewTypeError('Theageisnotannumber');}if(value>100){thrownewRangeError('Youcantbeolderthan100');}}//Ifnoerror-juststorethevalueinthepropertyobj[prop]=value;}};letp=newProxy({},ageValidator);p.age=100;
![Page 354: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/354.jpg)
console.log(p.age);//100p.age='Two';//Exceptionp.age=300;//Exception
Intheprecedingexample,wearetrappingthesethandler.Whenwesetapropertyoftheobject,wearetrappingthatoperationandintroducingvalidationofvalues.Ifthevalueisvalid,wewillsettheproperty.
![Page 355: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/355.jpg)
Functiontraps
Therearetwooperationsthatcanbetrappedifthetargetisafunction:applyandconstruct.
Tointerceptfunctioncalls,youwillneedtotrapthegetandapplyoperations.Firstgetthefunctionandthenapplytocallthefunction.So,yougetthefunctionandreturnthefunction.
Let'sconsiderthefollowingexampletounderstandhowmethodinterceptionworks:
varcar={name:"Ford",method_1:function(text){console.log("Method_1calledwith"+text);}}varmethodInterceptorProxy=newProxy(car,{//targetistheobjectbeingproxied,receiveristheproxyget:function(target,propKey,receiver){//Ionlywanttointerceptmethodcalls,notpropertyaccessvarpropValue=target[propKey];if(typeofpropValue!="function"){returnpropValue;}else{
return function(){console.log("interceptingcallto"+propKey+"incar"+target.name);//targetistheobjectbeingproxiedreturnpropValue.apply(target,arguments);}}}});methodInterceptorProxy.method_1("Mercedes");//"interceptingcalltomethod_1incarFord"//"Method_1calledwithMercedes"
Intheprecedingexample,wearetrappingthegetoperation.Ifthetypeofthepropertybeinggetisafunction,wewilluseapplytoinvokethatfunction.Ifyouseetheoutput,wearegettingtwoconsole.logs;thefirstisfromtheproxywherewetrappedthegetoperationandthesecondisfromtheactualmethodcall.
Metaprogrammingisaninterestingconstructtouse.However,anykindofintrospectionorreflectioncomesatthecostofperformance.Careshouldbetakenwhileusingproxiesastheycanbeslow.
![Page 356: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/356.jpg)
SummaryIn this chapter, we looked at two important concepts. ES6 proxies are useful meta programmingconstructsusedtodefinecustombehaviorforfundamentaloperations(forexample,propertylookup,assignment,enumeration,functioninvocation,andsoon).Welookedathowtousehandlers,traps,andproxytargetstointerceptandmodifythedefaultbehaviorofoperations.ThisgivesusverypowerfulmetaprogrammingcapabilitiesearlierlackinginJavaScript.
TheotherimportantconstructwediscussedinthischapterwasES6promises.Promisesareimportantbecausetheymakeasynchronousprogrammingconstructseasiertoworkwith.Apromiseactsasaproxyforavaluenotnecessarilyknownwhenthepromiseiscreated.Thisletsasynchronousmethodsreturnvalueslikesynchronousmethods-insteadofthefinalvalue,theasynchronousmethodreturnsapromiseforthevalueatsomepointinthefuture.
ThesearetwoverypowerfulconstructsinES6thatgreatlyenhancethelanguage'scorecapabilities.
Inthenextchapter,wewilllookatthefascinatingpossibilitiesaroundbrowsersandDOMmanipulationusingJavaScript.
![Page 357: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/357.jpg)
Chapter 10. The Browser EnvironmentYou know that JavaScript programs need a host environment. Most of what you learned so far inthisbookwasrelatedtocoreECMAScript/JavaScriptandcanbeusedinmanydifferenthostenvironments.Now,let'sshiftthefocustothebrowserasthisisthemostpopularandnaturalhostenvironmentforJavaScriptprograms.Inthischapter,youwilllearnthefollowingtopics:
TheBrowserObjectModel(BOM)TheDocumentObjectModel(DOM)BrowsereventsTheXMLHttpRequestobject
![Page 358: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/358.jpg)
Including JavaScript in an HTML pageTo include JavaScript in an HTMLpage, you will need to use the <script> tag as follows:
<!DOCTYPE><html><head><title>JStest</title><scriptsrc="somefile.js"></script></head><body><script>vara=1;a++;
</script></body></html>
Inthisexample,thefirst<script>tagincludesanexternalfile,somefile.js,whichcontainsJavaScriptcode.Thesecond<script>tagincludestheJavaScriptcodedirectlyintheHTMLcodeofthepage.ThebrowserexecutestheJavaScriptcodeinthesequenceitfindsitonthepageandallthecodeinalltagssharethesameglobalnamespace.Thismeansthatwhenyoudefineavariableinsomefile.js,italsoexistsinthesecond<script>block.
![Page 359: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/359.jpg)
BOM and DOM - an overviewThe JavaScript code in a page has access to a number of objects. These objects can be dividedintothefollowingtypes:
CoreECMAScriptobjects:ThisconsistsofalltheobjectsmentionedinthepreviouschaptersDOM:Thisconsistsofobjectsthathavetodowiththecurrentlyloadedpage,whichisalsocalledthedocumentBOM:Thisconsistsofobjectsthatdealwitheverythingoutsidethepage-thebrowserwindowandthedesktopscreen
DOMstandsforDocumentObjectModelandBOMforBrowserObjectModel.
TheDOMisastandardgovernedbytheWorldWideWebConsortium(W3C)andhasdifferentversions,calledlevels,suchasDOMLevel1,DOMLevel2,andsoon.Browsersinusetodayhavedifferentdegreesofcompliancewiththestandard,butingeneral,theyalmostallcompletelyimplementDOMLevel1.TheDOMwasstandardizedpostfactumafterthebrowservendorshadeachimplementedtheirownwaystoaccessthedocument.ThelegacypartfrombeforetheW3CtookoverisstillaroundandisreferredtoasDOM0,although,norealDOMLevel0standardexists.SomepartsofDOM0havebecomedefactostandardsasallmajorbrowserssupportthem;someofthesewereaddedtotheDOMLevel1standard.TherestofDOM0thatdidn'tfinditswaytoDOM1istoobrowserspecificandwon'tbediscussedhere.
Historically,BOMwasnotapartofanystandard.SimilartoDOM0,ithasasubsetofobjectsthatissupportedbyallmajorbrowsers,andanothersubsetthatisbrowser-specific.TheHTML5standard codifies common behavior among browsers, and it includes common BOM objects.Additionally,mobiledevicescomewiththeirspecificobjects(andHTML5aimstostandardizethoseaswell),whichtraditionallywerenotnecessaryfordesktopcomputers,butmakesenseinamobileworld,forexample,geolocation,cameraaccess,vibration,touchevents,telephony,andSMS.
Thischapterdiscussesonlycross-browsersubsetsofBOMandDOMLevel1,unlessnotedotherwiseinthetext.Eventhesesafesubsetsconstitutealargetopic,andafullreferenceisbeyondthescopeofthisbook.Youcanalsoconsultthefollowingreferences:
MozillaDOMreference(http://developer.mozilla.org/en/docs/Gecko_DOM_Reference)Mozilla'sHTML5wiki(https://developer.mozilla.org/en-US/docs/HTML/HTML5)Microsoft'sdocumentationforInternetExplorer(http://msdn2.microsoft.com/en-us/library/ms533050(vs.85).aspx)W3C'sDOMspecifications(http://www.w3.org/DOM/DOMTR)
![Page 360: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/360.jpg)
BOMThe BOM is a collection of objects that give you access to the browser and the computer screen.Theseobjectsareaccessiblethroughtheglobalobjectwindow.
![Page 361: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/361.jpg)
Thewindowobjectrevisited
Asyoualreadyknow,inJavaScript,there'saglobalobjectprovidedbythehostenvironment.Inthebrowserenvironment,thisglobalobjectisaccessibleusingwindow.Allglobalvariablesarealsoaccessibleaspropertiesofthewindowobject.Forexample,takealookatthefollowingcode:
>window.somevar=1;1>somevar;1
Additionally,allthecoreJavaScriptfunctions,discussedinChapter2,PrimitiveDataTypes,Arrays, Loops, and Conditions, are methods of the global object. Consider the following piece ofcode:
>parseInt('123a456');123>window.parseInt('123a456');123
Inadditiontobeingareferencetotheglobalobject,thewindowobjectalsoservesasecondpurpose-providinginformationaboutthebrowserenvironment.There'sawindowobjectforeveryframe,iframe,popup,orbrowsertab.
Let'sseesomeofthebrowser-relatedpropertiesofthewindowobject.Again,thesecanvaryfromonebrowsertoanother,solet'sonlyconsiderthe propertiesthatareimplementedconsistentlyandreliablyacrossallmajorbrowsers.
![Page 362: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/362.jpg)
Usingwindow.navigatorproperty
Thenavigatorisanobjectthathassomeinformationaboutthebrowseranditscapabilities.Onepropertyisnavigator.userAgent,whichisalongstringofbrowseridentification.InFirefox,you'llgetthefollowingoutput:
> window.navigator.userAgent;"Mozilla/5.0(Macintosh;IntelMacOSX10_8_3)AppleWebKit/536.28.10(KHTML,likeGecko)Version/6.0.3Safari/536.28.10"
TheuserAgentstringinMicrosoftInternetExplorerissomethingasfollows:
"Mozilla/5.0(compatible;MSIE10.0;WindowsNT6.1;Trident/6.0)"
Asthebrowsershavedifferentcapabilities,developersareusingtheuserAgentstringtoidentifythebrowserandprovidedifferentversionsofthecode.Forexample,thefollowingcodesnippetsearchesforthepresenceoftheMSIEstringtoidentifyInternetExplorer:
if(navigator.userAgent.indexOf('MSIE')!==-1){//thisisIE}else{//notIE}
It'sbetternottorelyontheuserAgentstring,buttousefeaturesniffing(alsocalledcapabilitydetection)instead.Thereasonforthisisthatit'shardtokeeptrackofallbrowsersandtheirdifferentversions.It'smucheasiertosimplycheckifthefeatureyouintendtouseisindeedavailableintheuser'sbrowser.Forexample,takealookatthefollowingcodesnippet:
if(typeofwindow.addEventListener==='function'){//featureissupported,let'suseit}else{//hmm,thisfeatureisnotsupported,willhaveto//thinkofanotherway}
AnotherreasontoavoiduserAgentsniffingisthatsomebrowsersallowuserstomodifythestringandpretendtheyareusingadifferentbrowser.
![Page 363: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/363.jpg)
Yourconsoleisacheatsheet
Theconsoleletsyouinspectwhat'sinanobjectandthisincludesalltheBOMandDOMproperties.Justtypethefollowingcode:
>navigator;
Thenclickontheresult.Theresultisalistofpropertiesandtheirvalues,asshowninthefollowingscreenshot:
![Page 364: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/364.jpg)
Usingwindow.locationproperty
ThelocationpropertypointstoanobjectthatcontainsinformationabouttheURLofthecurrentlyloadedpage.Forexample,location.hrefisthefullURLandlocation.hostnameisonlythedomain.Withasimpleloop,youcansee thefulllistofpropertiesofthelocationobject.
Imagineyou'reonapagewiththefollowingURL:
http://search.phpied.com:8080/search?q=java&what=script#results.
Considerthefollowingcode:
for(variinlocation){if(typeoflocation[i]==="string"){console.log(i+'="'+location[i]+'"');}}href="http://search.phpied.com:8080/search?q=java&what=script#results"hash="#results"host="search.phpied.com:8080"hostname="search.phpied.com"pathname="/search"port=<<8080>>protocol=<<http:>>search="?q=java&what=script"
Therearealsothreemethodsthatlocationpropertyprovides,namelyreload(),assign(),andreplace().
It'sinterestinghowmanydifferentwaysexistforyoutonavigatetoanotherpage.Thefollowingareafewways:
>window.location.href='http://www.packtpub.com';>location.href='http://www.packtpub.com';>location='http://www.packtpub.com';>location.assign('http://www.packtpub.com');
Thereplace()methodisalmostthesameasassign().Thedifferenceisthatitdoesn'tcreateanentryinthebrowser'shistorylistasfollows:
>location.replace('http://www.yahoo.com');
Toreloadapage,youcanusethefollowingcode:
>location.reload();
![Page 365: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/365.jpg)
Alternatively,youcanuselocation.hreftopointittoitself,asfollows:
>window.location.href=window.location.href;
Or,simplyusethefollowingcode:
>location=location;
![Page 366: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/366.jpg)
Usingwindow.historyproperty
Thewindow.historypropertyallowslimitedaccesstothepreviouslyvisitedpagesinthesamebrowsersession.Forexample,youcanseehowmanypagestheuserhasvisitedbeforecomingtoyourpage,asfollows:
>window.history.length;5
YoucannotseetheactualURLsthough.Forprivacyreasons,thisdoesn'twork.Seethefollowingcode:
>window.history[0];
Youcan,however,navigatebackandforththroughtheuser'ssessionasiftheuserhadclickedontheback/forwardbrowserbuttons,asfollows:
>history.forward();>history.back();
Youcanalsoskippagesbackandforthwithhistory.go().Thisisthesameascallinghistory.back().Thecodeforhistory.go()isasfollows:
>history.go(-1);
Togotwopagesback,usethefollowingcode:
>history.go(-2);
Reloadthecurrentpageusingthefollowingcode:
>history.go(0);
MorerecentbrowsersalsosupportHTML5historyAPI,whichletsyouchangetheURLwithoutreloading the page. This is perfect for dynamic pages because they can allow users to bookmark aspecificURL,whichrepresentsthestateoftheapplication,andwhentheycomeback,orsharewiththeirfriends,thepagecanrestoretheapplicationstatebasedontheURL.TogetasenseofthehistoryAPI,gotoanypageandwritethefollowinglinesofcodeintheconsole:
>history.pushState({a:1},"","hello");> history.pushState({b: 2}, "", "hello-you-too");
>history.state;
NoticehowtheURLchanges,butthepageisthesame.Now,experimentwithbackandforwardbuttonsinthebrowserandinspectthehistory.stateobjectagain.
![Page 367: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/367.jpg)
usingwindow.framesproperty
Thewindow.framespropertyisacollectionofalloftheframesinthecurrentpage.Itdoesn'tdistinguishbetweenframesandiframes(inlineframes).Regardlessofwhetherthereareframesonthepageornot,window.framesalwaysexistsandpointstowindow,asfollows:
> window.frames === window;true
Let'sconsideranexamplewhereyouhaveapagewithoneiframe,asfollows:
<iframename="myframe"src="hello.html"/>
Inordertotellifthereareanyframesonthepage,youcancheckthelengthproperty.Incaseofoneiframe,you'llseethefollowingoutput:
>frames.length1
Eachframecontainsanotherpage,whichhasitsownglobalwindowobject.
Togetaccesstotheiframe'swindow,youcanexecuteanyofthefollowing:
>window.frames[0];>window.frames[0].window;>window.frames[0].window.frames;>frames[0].window;>frames[0];
Fromtheparentpage,youcanaccesspropertiesofthechildframeaswell.Forexample,youcanreloadtheframeasfollows:
> frames[0].window.location.reload();
Frominsidethechild,youcanaccesstheparentasfollows:
>frames[0].parent===window;true
Usingapropertycalledtop,youcanaccessthetop-mostpage-theonethatcontainsalltheotherframes-fromwithinanyframe,asfollows:
>window.frames[0].window.top===window;true>window.frames[0].window.top===window.top;true>window.frames[0].window.top===top;true
![Page 368: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/368.jpg)
Inaddition,selfisthesameaswindow,asyoucanseeinthefollowingcodesnippet:
>self===window;true>frames[0].self==frames[0].window;true
Ifaframehasanameattribute,youcannotonlyaccesstheframebyname, butalsobyindex,asshowninthefollowingpieceofcode:
>window.frames['myframe']===window.frames[0];true
Or,alternatively,youcanusethefollowingcode:
>frames.myframe===window.frames[0];true
![Page 369: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/369.jpg)
Usingwindow.screenproperty
Thescreenpropertyprovidesinformationabout theenvironmentoutsidethebrowser.Forexample,thescreen.colorDepthpropertycontainsthecolorbitdepth(thecolorquality)ofthemonitor.Thisismostlyusedforstatisticalpurposes.Takealookatthefollowinglineofcode:
> window.screen.colorDepth;32
Youcanalsochecktheavailablescreenrealestate(theresolution),asfollows:
>screen.width;1440>screen.availWidth;1440>screen.height;900>screen.availHeight;847
ThedifferencebetweenheightandavailHeightisthatheightisthewholescreen,whileavailHeightsubtractsanyoperatingsystemmenus,suchastheWindowstaskbar.ThesameisthecaseforwidthandavailWidth.
Somewhatrelatedisthepropertymentionedinthefollowingcode:
>window.devicePixelRatio;1
Ittellsyouthedifference(ratio)betweenphysicalpixelsanddevicepixelsintheretinadisplaysinmobiledevices,forexample,value2iniPhone.
![Page 370: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/370.jpg)
window.open()/close()method
Havingexploredsomeofthemostcommoncross-browserpropertiesofthewindowobject,let'smovetosomeofthemethods.Onesuchmethodisopen(),whichallowsyoutoopennewbrowserwindows(popups).Variousbrowserpoliciesandusersettingsmaypreventyoufromopeningapopup(duetoabuseofthetechniqueformarketingpurposes),butgenerally,youshouldbeabletoopenanewwindowifitwasinitiatedbytheuser.Otherwise,ifyoutrytoopenapopupasthepageloads,itwillmostlikelybeblocked,becausetheuserdidn'tinitiateitexplicitly.
Thewindow.open()methodacceptsthefollowingparameters:
URLtoloadinthenewwindowNameofthenewwindowthatcanbeusedasthevalueofaform'stargetattributeComma-separatedlistoffeatures,whichisasfollows:
resizable:Shouldtheuserbeabletoresizethenewwindowwidth,height:Widthandheightofthepopupstatus:Shouldthestatusbarbevisible
Thewindow.open()methodreturnsareferencetothewindowobjectofthenewlycreatedbrowserinstance.Thefollowingisanexample:
varwin=window.open('http://www.packtpub.com','packt','width=300,height=300,resizable=yes');
Thewinvariablepointstothewindowobjectofthepopup.Youcancheckifwinhasafalsyvalue,whichmeansthatthepopupwasblocked.
Thewin.close()methodclosesthenewwindow.
It'sbesttostayawayfromopeningnewwindowsforaccessibilityandusabilityreasons.Ifyoudon'tlikesitespoppingupwindowstoyou,whydoittoyourusers?Therearelegitimatepurposes,suchasprovidinghelpinformationwhilefillingoutaform,butoften,thesamecanbeachievedwithalternativesolutions,suchasusingafloating<div>insidethepage.
![Page 371: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/371.jpg)
window.moveTo()andwindow.resizeTo()methods
Continuingwiththeshadypracticesfromthepast,thefollowingaremoremethodstoirritateyourusers,providedtheirbrowserandpersonalsettingsallowyoutodoso:
window.moveTo(100,100):Thismovesthebrowserwindowtoscreenlocationx=100andy=100,whichiscountedfromthetop-leftcornerwindow.moveBy(10,-10):Thismovesthewindow10pixelstotherightand10pixelsupfromitscurrentlocationwindow.resizeTo(x,y)andwindow.resizeBy(x,y):Theseacceptthesameparametersasthemovemethods,buttheyresizethewindowasopposedtomovingit
Again,trytosolvetheproblemyou'refacingwithoutresortingtothesemethods.
![Page 372: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/372.jpg)
window.alert(),window.prompt(),andwindow.confirm()methods
InChapter2,PrimitiveDataTypes,Arrays,Loops,andConditions,wetalkedaboutthealert()function.Nowyouknowthatglobalfunctionsareaccessibleasmethodsoftheglobalobject,soalert('Watchout!')andwindow.alert('Watchout!')areexactlythesame.
Thealert()functionisnotanECMAScriptfunctionbutaBOMmethod.Inadditiontoit,twootherBOMmethodsallowyoutointeractwiththeuserthroughsystemmessages.Thefollowingarethemethods:
confirm():Thisgivestheusertwooptions,OKandCancelprompt():Thiscollectstextualinput
Thisishowitworks:
>varanswer=confirm('Areyoucool?');>answer;
It presents you with a window similar to the following screenshot (the exact look depends on thebrowserandtheoperatingsystem):
You'llnoticethefollowingthings:
Nothinggetswrittentotheconsoleuntilyou closethismessage,whichmeansthatanyJavaScriptcodeexecutionfreezes,waitingfortheuser'sanswerClickingonOKreturnstrue,clickingonCancelorclosingthemessageusingtheXicon,ortheESCkey,returnsfalse
Thisishandytoconfirmuseractions,asshowninthefollowingpieceofcode:
if(confirm('Sureyouwanttodeletethis?')){//delete}else{//abort
![Page 373: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/373.jpg)
}
MakesureyouprovideanalternativewaytoconfirmuseractionsforpeoplewhohavedisabledJavaScript,orforsearchenginespiders.
Thewindow.prompt()methodpresentstheuserwithadialogtoentertext,asfollows:
>varanswer=prompt('Andyournamewas?');>answer;
Thisresultsinthefollowingdialogbox(Chrome,MacOS):
Thevalueofanswerisoneofthefollowing:
null:ThishappensifyouclickonCancel,theXicon,orpressESCkey""(emptystring):ThishappensifyouclickonOKorpressEnterwithouttypinganythingAtextstring:ThisisifyoutypesomethingandthenclickonOKorpressEnter
Thefunctionalsotakesastringasasecondparameteranddisplaysitasadefaultvalueprefilledintotheinputfield.
![Page 374: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/374.jpg)
Usingwindow.setTimeout()andwindow.setInterval()methods
ThesetTimeout()andsetInterval()methodsallowschedulingtheexecutionofapieceofcode.ThesetTimeout()methodattemptstoexecutethegivencodeonce,afteraspecifiednumberofmilliseconds.ThesetInterval()methodattemptstoexecuteitrepeatedlyafteraspecifiednumberofmillisecondshaspassed.
Thisshowsanalertafterapproximately2seconds(2000milliseconds).Considerthefollowingcode:
>functionboo(){alert('Boo!');}>setTimeout(boo,2000);4
Asyoucansee,thefunctionreturnedaninteger(inthiscase,4)representingtheIDofthetimeout.YoucanusethisIDtocancelthetimeoutusingclearTimeout().Inthefollowingexample,ifyou'requickenough,andclearthetimeoutbefore 2secondshavepassed,thealertwillneverbeshown,asyoucanseeinthefollowingcode:
>varid=setTimeout(boo,2000);>clearTimeout(id);
Let'schangeboo()tosomethinglessintrusive,asfollows:
>functionboo(){console.log('boo');}
Now,usingsetInterval(),youcanscheduleboo()toexecuteevery2seconds,untilyoucancelthescheduledexecutionwithclearInterval().Considerthefollowingcode:
>varid=setInterval(boo,2000);booboobooboobooboo>clearInterval(id);
Notethatbothfunctionsacceptapointertoacallbackfunctionasafirstparameter.Theycanalsoacceptastring,whichisevaluatedwitheval();however,asyouknow,eval()isevil,soitshouldbeavoided.Moreover,whatifyouwanttopassargumentstothefunction?Insuchcases,youcanjustwrapthefunctioncallinsideanother function.
Thefollowingcodeisvalid,butnotrecommended:
//badidea
![Page 375: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/375.jpg)
varid=setInterval("alert('boo,boo')",2000);
Thisalternativeispreferred:
varid=setInterval(function(){alert('boo,boo');},2000
);
Beawarethatschedulingafunctioninsomeamountofmillisecondsisnotaguaranteethatitwillexecuteexactlyatthattime.Onereasonisthatmostbrowsersdon'thavemillisecondresolutiontime.Ifyouschedulesomethingin3milliseconds,itwillexecuteafteraminimumof15inolderIEsandsoonerinmoremodernbrowsers,butmostlikely,notin1millisecond.Theotherreasonisthatthebrowsersmaintainaqueueofwhatyourequestthemtodo.100millisecondstimeoutmeansaddtothequeueafter100milliseconds.However,ifthequeueisdelayedbysomethingslowhappening,yourfunctionwillhavetowaitandexecuteafter,say,120milliseconds.
MorerecentbrowsersimplementtherequestAnimationFrame()function.It'spreferabletothetimeoutfunctionsbecauseyou'reaskingthebrowsertocallyourfunctionwheneverithasavailableresources,notafterapredefinedtimeinmilliseconds.Tryexecutingthefollowingcodesnippetinyourconsole:
functionanimateMe(){webkitRequestAnimationFrame(function(){console.log(newDate());animateMe();});}
animateMe();
![Page 376: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/376.jpg)
window.documentproperty
Thewindow.documentpropertyisaBOMobjectthatreferstothecurrentlyloadeddocument(page).ItsmethodsandpropertiesfallintotheDOMcategoryofobjects.Takeadeepbreath(andmaybefirstlookattheBOMexercisesattheendofthechapter)andlet'sdiveintotheDOM.
![Page 377: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/377.jpg)
DOMThe DOM represents an XMLor an HTMLdocument as a tree of nodes. Using DOMmethods andproperties,youcanaccessanyelementonthepage,modifyorremoveelements,oraddnewones.TheDOMisalanguage-independentAPIandcanbeimplementednotonlyinJavaScript,butalsoinanyotherlanguage.Forexample,youcangeneratepagesontheserver-sidewithPHP'sDOMimplementation(http://php.net/dom).
TakealookatthisexampleHTMLpage:
<!DOCTYPEhtml><html><head><title>Mypage</title>
</head><body><pclass="opener">firstparagraph</p><p><em>second</em>paragraph</p><pid="closer">final</p><!--andthat'saboutit--></body></html>
Considerthesecondparagraph(<p><em>second</em>paragraph</p>).Youwillseethatit'sa<p>tag,andit'scontainedinthe<body>tag.Ifyouthinkintermsoffamilyrelationships,youcansaythat<body>istheparentof<p>and<p>isthechild.Thefirstandthe thirdparagraphswouldalsobechildrenofthe<body>tag,andatthesametime,siblingsofthesecondparagraph.The<em>tagisachildofthesecond<p>,so<p>isitsparent.Theparent-childrelationshipscanberepresentedgraphicallyinanancestrytree,calledtheDOMtree:
![Page 378: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/378.jpg)
Thepreviousscreenshotshowswhatyou'llseeintheWebKitconsole'sElementstabafteryouexpandeachnode.
Youcanseehowallofthetagsareshownasexpandablenodesonthetree.Althoughnotshown,thereexiststheso-calledtextnodes,forexample,thetextinsidethe<em>tag(thewordsecond)isatextnode.Whitespaceisalsoconsideredatextnode.CommentsinsidetheHTMLcodearealsonodesinthetree,the<!-andthat'saboutit->commentintheHTMLsourceisacommentnodeinthetree.
EverynodeintheDOMtreeisanobjectandthePropertiessectionontherightlistsallofthepropertiesandmethodsyoucanusetoworkwith theseobjects,followingtheinheritancechainofhowthisobjectwascreated:
![Page 379: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/379.jpg)
Youcanalsoseetheconstructorfunctionthatwasusedbehindthescenestocreateeachoftheseobjects.Although,thisisnottoopracticalforday-to-daytasks,itmaybeinterestingtoknowthat,forexample,<p>iscreatedbytheHTMLParagraphElement()constructor,theobjectthatrepresentstheheadtagiscreatedbyHTMLHeadElement(),andsoon.Youcannotcreateobjectsusingtheseconstructorsdirectly,though.
![Page 380: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/380.jpg)
CoreDOMandHTMLDOM
Onelastdiversionbeforemovingontomorepracticalexamples.Asyounowknow,theDOMrepresentsbothXMLdocumentsandHTMLdocuments.Infact,HTMLdocumentsareXMLdocuments,butalittlemorespecific.Therefore,aspartofDOMLevel1,thereisaCoreDOMspecificationthatisapplicabletoallXMLdocuments,andthereisalsoanHTMLDOMspecification,whichextendsandbuildsuponthecoreDOM.Ofcourse,theHTMLDOMdoesn'tapplytoallXMLdocuments,butonlytoHTMLdocuments.Let'sseesomeexamplesofCoreDOMandHTMLDOMconstructors:
Constructor Inherits fromCore orHTML
Comment
Node Core Anynodeonthetree
Document Node Core Thedocumentobject,themainentrypointtoanyXMLdocument
HTMLDocument Document HTMLThisiswindow.documentorsimplydocument,theHTML-specificversionofthepreviousobject,whichyou'lluseextensively
Element Node CoreEverytaginthesourceisrepresentedbyanelement.That'swhyyousay-thePelementmeaningthe<p></p>tag
HTMLElement Element HTML General-purposeconstructor,allconstructorsforHTMLelementsinheritfromit
HTMLBodyElement HTMLElement HTML Elementrepresentingthe<body>tag
HTMLLinkElement HTMLElement HTML AnAelement:an<ahref="..."></a>tag
Andothersuchconstructors
HTMLElement HTML AlltherestoftheHTMLelements
CharacterData Node Core General-purposeconstructorfordealingwithtexts
Text CharacterData CoreTextnodeinside atag;in<em>second</em>,youhavetheelementnodeEMandthetextnodewithvaluesecond
Comment CharacterData Core <!--anycomment-->
Attr Node CoreRepresentsanattributeofatag;in<pid="closer">,theidattributeisaDOMobjectcreatedbytheAttr()constructor
NodeList Core Alistofnodes,anarray-likeobjectthathasalengthproperty
![Page 381: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/381.jpg)
NamedNodeMap CoreSameasNodeList,butthenodescanbeaccessedbyname,notonlybynumericindex.
HTMLCollection HTML Similar to NamedNodeMap but specific for HTML.
Theseare,bynomeans,alloftheCoreDOMandHTMLDOMobjects.Forthefulllist,consulthttp://www.w3.org/TR/DOM-Level-1/.
NowthatthisbitoftheDOMtheoryisbehindyou,let'sfocusonthepracticalsideofworkingwith the DOM. In the following sections, you'll learn how to do the following topics:
AccessDOMnodesModifynodesCreatenewnodesRemovenodes
![Page 382: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/382.jpg)
AccessingDOMnodes
Beforeyoucanvalidatetheuserinputinaformonapageorswapanimage,youneedtogetaccesstotheelementyouwanttoinspectormodify.Luckily,therearemanywaystogettoanyelement,eitherbynavigatingaroundtraversingtheDOMtreeorbyusingashortcut.
It'sbestifyoustartexperimentingwithallofthenewobjectsandmethods.Theexamplesyou'llseeusethesamesimpledocumentthatyousawatthebeginningoftheDOMsection,andwhichyoucanaccessathttp://www.phpied.com/files/jsoop/ch7.html.Openyourconsole,andlet'sgetstarted.
Thedocumentnode
Thedocumentnodegivesyouaccesstothecurrentdocument.Toexplore thisobject,youcanuseyourconsoleasacheatsheet.Typeconsole.dir(document)andclickontheresult:
Alternatively,youcanbrowseallofthepropertiesandmethodsofthedocumentobjectDOMpropertiesintheElementspanel:
![Page 383: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/383.jpg)
Allnodes,includingthedocumentnode,textnodes,elementnodes,andattributenodeshavenodeType,nodeNameandnodeValueproperties:
>document.nodeType;9
Thereare12nodetypes,representedbyintegers.Asyoucansee,thedocumentnodetypeis9.Themostcommonlyusedare1(element),2(attribute),and3(text).
Nodesalsohavenames.ForHTMLtags,thenodenameisthetagname(tagNameproperty).Fortextnodes,it's#text,andfordocumentnodes,thenameisasfollows:
>document.nodeName;"#document"
Nodes can also have node values. For example, for text nodes, the value is the actual text. Thedocumentnodedoesn'thaveavalue,whichcanbeseenasfollows:
>document.nodeValue;null
![Page 384: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/384.jpg)
documentElement
Now,let'smovearoundthetree.XMLdocumentsalwayshaveonerootnodethatwrapstherestofthedocument.ForHTMLdocuments,therootisthe<html>tag.Toaccesstheroot,youwillusethedocumentElementpropertyofthedocumentobject.
>document.documentElement;<html>...</html>
nodeTypeis1(anelementnode)whichcanbeseenasfollows:
>document.documentElement.nodeType;1
Forelementnodes,bothnodeNameandtagNamepropertiescontainthenameofthetag,asseeninthefollowingoutput:
>document.documentElement.nodeName;"HTML">document.documentElement.tagName;"HTML"
Childnodes
Inordertotellifanodehasanychildren,youwillusehasChildNodes(),asfollows:
>document.documentElement.hasChildNodes();true
TheHTMLelementhasthreechildren,theheadandthebodyelementsandthewhitespacebetweenthem(whitespaceiscountedinmost,butnotallbrowsers).YoucanaccessthemusingthechildNodesarray-likecollection,asfollows:
>document.documentElement.childNodes.length;3>document.documentElement.childNodes[0];<head>...</head>>document.documentElement.childNodes[1];#text>document.documentElement.childNodes[2];<body>...</body>
AnychildhasaccesstoitsparentthroughtheparentNodeproperty,asseeninthefollowingcode:
>document.documentElement.childNodes[1].parentNode;<html>...</html>
Let'sassignareferencetobodytoavariable,asfollows:
![Page 385: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/385.jpg)
>varbd=document.documentElement.childNodes[2];
Howmanychildrendoesthebodyelementhave?Considerthefollowingpieceofcode
>bd.childNodes.length;9
Asarefresher,here,again,isthebodyofthedocument:
<body><pclass="opener">firstparagraph</p><p><em>second</em>paragraph</p><pid="closer">final</p><!--andthat'saboutit--></body>
Howcomebodyhas9children?Well,threeparagraphsplusonecommentmakesfournodes.Thewhitespacebetweenthesefournodesmakesthreemoretextnodes.Thismakesatotalofsevensofar.Thewhitespacebetween<body>andthefirst<p>istheeighthnode.Thewhitespacebetweenthecommentandtheclosing</body>isanothertextnode.Thismakesatotalofninechildnodes.Justtypebd.childNodesintheconsoletoinspectthemall.
Attributes
As the first child of the body is a whitespace, the second child (index 1) is the first paragraph.Refertothefollowingpieceofcode:
>bd.childNodes[1];<pclass="opener">firstparagraph</p>
YoucancheckwhetheranelementhasattributesusinghasAttributes(),asfollows:
>bd.childNodes[1].hasAttributes();true
Howmanyattributes?Inthisexample,oneistheclassattribute,whichcanbeseenasfollows:
>bd.childNodes[1].attributes.length;1
Youcanaccesstheattributesbyindexandname.YoucanalsogetthevalueusingthegetAttribute()method,whichisasfollows:
>bd.childNodes[1].attributes[0].nodeName;"class">bd.childNodes[1].attributes[0].nodeValue;"opener">bd.childNodes[1].attributes['class'].nodeValue;"opener">bd.childNodes[1].getAttribute('class');
![Page 386: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/386.jpg)
"opener"
Accessingthecontentinsideatag
Let'stakealookatthefirstparagraph:
>bd.childNodes[1].nodeName;"P"
YoucangetthetextcontainedintheparagraphusingthetextContentproperty.Itdoesn'texistinolderIEs,butanotherpropertycalledinnerTextreturnsthesamevalue,asseeninthefollowingoutput:
>bd.childNodes[1].textContent;"firstparagraph"
ThereisalsotheinnerHTMLproperty.It'sarelativelynewadditiontotheDOMstandard,despitethefactthatitpreviouslyexistedinallmajorbrowsers.Itreturns(orsets)HTMLcodecontainedinanode.YoucanseehowthisisalittleinconsistentasDOMtreatsthedocumentasatreeofnodes,notasastringoftags.However,innerHTMLissoconvenienttousethatyou'llseeiteverywhere.Refertothefollowingcode:
>bd.childNodes[1].innerHTML;"firstparagraph"
The first paragraph contains only text, so innerHTML is the same as textContent (or innerTextin IE). However, the second paragraph does contain an em node, so you can see the difference asfollows:
>bd.childNodes[3].innerHTML;"<em>second</em>paragraph">bd.childNodes[3].textContent;"secondparagraph"
AnotherwaytogetthetextcontainedinthefirstparagraphisbyusingthenodeValuemethodofthetextnodecontainedinsidethepnode,asfollows:
>bd.childNodes[1].childNodes.length;1>bd.childNodes[1].childNodes[0].nodeName;"#text">bd.childNodes[1].childNodes[0].nodeValue;"firstparagraph"
DOMaccessshortcuts
UsingchildNodes,parentNode,nodeName,nodeValue,andattributes,youcannavigateupanddownthetreeanddoanythingwiththedocument.However,thefactthatwhitespaceisatextnodemakesthisafragilewayofworkingwiththeDOM.Ifthepagechanges,yourscriptmayno
![Page 387: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/387.jpg)
longerworkcorrectly.Also,ifyouwanttogettoanodedeeperinthetree,itcouldtakeabitofcodebeforeyougetthere.That'swhyyouhaveshortcutmethods,namely,getElementsByTagName(),getElementsByName(),andgetElementById().
The getElementsByTagName() method takes a tag name (the name of an element node) andreturns an HTMLcollection (array-like object) of nodes with the matching tag name. Forexample,thefollowingexampleasks-givemeacountofallparagraphs,whichisgivenasfollows:
>document.getElementsByTagName('p').length;3
Youcanaccessaniteminthelistusingthebracketsnotation,ortheitem()method,andpassingtheindex(0forthefirstelement).Usingitem()isdiscouraged,asarraybracketsaremoreconsistentandalsoshortertotype.Refertothefollowingpieceofcode:
>document.getElementsByTagName('p')[0];<pclass="opener">firstparagraph</p>>document.getElementsByTagName('p').item(0);<pclass="opener">firstparagraph</p>
Gettingthecontentsofthefirstpcanbedoneasfollows:
>document.getElementsByTagName('p')[0].innerHTML;"firstparagraph"
Accessingthelastpcanbedoneasfollows:
>document.getElementsByTagName('p')[2];<pid="closer">final</p>
Toaccesstheattributesofanelement,youcanusetheattributescollectionorgetAttribute(),asshownpreviously.However,ashorterwayistousetheattributenameasapropertyoftheelementyou'reworkingwith.So,togetthevalueoftheid attribute,youwilljustuseidasaproperty,whichisasfollows:
>document.getElementsByTagName('p')[2].id;"closer"
Gettingtheclassattributeofthefirstparagraphwon'tworkthough.It'sanexceptionbecauseitjusthappenssothatclassisareservedwordinECMAScript.YoucanuseclassNameinstead,asfollows:
>document.getElementsByTagName('p')[0].className;"opener"
UsinggetElementsByTagName(),youcangetalloftheelementsonthepage,asfollows:
![Page 388: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/388.jpg)
>document.getElementsByTagName('*').length;8
InearlierversionsofIEbeforeIE7,*isnotacceptableasatagname.Togetallelements,youcanuseIE'sproprietarydocument.allcollection,although,selectingeveryelementisrarelyneeded.
TheothershortcutmentionedisgetElementById().Thisisprobablythemostcommonwayofaccessinganelement.YoujustassignIDstotheelementsyouplantoplay withandthey'llbeeasytoaccesslateron,asseeninthefollowingcode:
>document.getElementById('closer');<pid="closer">final</p>
Additionalshortcutmethodsinmorerecentbrowsersincludethefollowing:
getElementByClassName():ThismethodfindselementsusingtheirclassattributequerySelector():ThismethodfindsanelementusingaCSSselectorstringquerySelectorAll():Thismethodisthesameasthepreviousonebutreturnsallmatchingelements,notjustthefirst
Siblings,body,first, andlastchild
ThenextSiblingandpreviousSiblingaretwootherconvenientpropertiestonavigatetheDOMtreeonceyouhaveareferencetooneelement.Considerthefollowingcode:
> var para = document.getElementById('closer');>para.nextSibling;#text>para.previousSibling;#text>para.previousSibling.previousSibling;<p>...</p>>para.previousSibling.previousSibling.previousSibling;#text>para.previousSibling.previousSibling.nextSibling.nextSibling;<pid="closer">final</p>
Thebodyelementisusedsooftenthatithasitsownshortcut,whichisasfollows:
>document.body;<body>...</body>>document.body.nextSibling;null>document.body.previousSibling.previousSibling;<head>...</head>
ThefirstChildandlastChildpropertiesarealsoconvenient.ThefirstChildpropertyisthesameaschildNodes[0]andlastChildisthesameaschildNodes[childNodes.length-
![Page 389: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/389.jpg)
1]properties:
>document.body.firstChild;#text>document.body.lastChild;#text>document.body.lastChild.previousSibling;<!--andthat'saboutit-->>document.body.lastChild.previousSibling.nodeValue;
" and that's about it "
Thefollowingscreenshotshowsthefamilyrelationshipsbetweenthebodyandthethreeparagraphsinit.Forsimplicity,allthewhitespacetextnodesareremovedfromthescreenshot:
WalktheDOM
Towrapup,here'safunctionthattakesanynodeandwalksthroughtheDOMtreerecursively,startingfromthegivennode,asfollows:
functionwalkDOM(n){do{console.log(n);if(n.hasChildNodes()){walkDOM(n.firstChild);}}while(n=n.nextSibling);}
Youcantestthefunctionasfollows:
![Page 390: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/390.jpg)
>walkDOM(document.documentElement);>walkDOM(document.body);
![Page 391: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/391.jpg)
ModifyingDOMnodes
NowthatyouknowawholelotofmethodstoaccessanynodeoftheDOMtreeanditsproperties,let'sseehowyoucanmodifythesenodes:
Let'sassignapointertothelastparagraphtothevariablemy,asfollows:
>varmy=document.getElementById('closer');
Now,changingthetextoftheparagraphcanbeaseasyaschangingtheinnerHTMLvalue,whichisasfollows:
>my.innerHTML='final!!!';"final!!!"
AsinnerHTMLacceptsastringofHTMLsourcecode,youcanalsocreateanewemnodeintheDOMtreeasfollows:
>my.innerHTML='<em>my</em>final';"<em>my</em>final"
Thenewemnodebecomesapartofthetree.Letstakealookatthefollowingcode:
>my.firstChild;<em>my</em>>my.firstChild.firstChild;"my"
AnotherwaytochangetextistogettheactualtextnodeandchangeitsnodeValue,asshowninthefollowingpieceofcode:
>my.firstChild.firstChild.nodeValue='your';"your"
Modifyingstyles
Oftenyoudon'tchangethecontentofanode,butitspresentation.Theelementshaveastyleproperty,whichinturnhasapropertymappedtoeachCSSproperty.Forexample,changingthestyleoftheparagraphtoaddaredborder,asfollows:
>my.style.border="1pxsolidred";"1pxsolidred"
CSSpropertiesoftenhavedashes,butdashesarenotacceptableinJavaScriptidentifiers.Insuchcases,youskipthedashanduppercasethenextletter.So,padding-topbecomespaddingTop,margin-leftbecomesmarginLeft,andsoon.Takealookatthefollowingcode:
>my.style.fontWeight='bold';
![Page 392: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/392.jpg)
"bold"
YoualsohaveaccesstothecssTextpropertyofstyle,whichletsyouworkwithstylesasstrings,asyoucanseeinthefollowingcodesnippet:
>my.style.cssText;"border:1pxsolidred;font-weight:bold;"
Moreover,modifyingstylesisastringmanipulation:
>my.style.cssText+="border-style:dashed;""border:1pxdashedred;font-weight:bold;border-style:dashed;"
Funwithforms
Asmentionedearlier,JavaScriptisgreatforclient-sideinputvalidationandcansaveafewround-triptotheserver.Let'spracticeformmanipulationsandplayalittlebitwithaformlocatedonapopularpage,www.google.com:
FindingthefirsttextinputusingthequerySelector()methodandaCSSselectorstringisasfollows:
>varinput=document.querySelector('input[type=text]');
Accessingthesearchbox.Considerthefollowingcode:
>input.name;"q"
Changingthesearchquerybysettingthetextcontainedinthevalueattributeisdoneasfollows:
> input.value = 'my query';"myquery"
Now,let'shavesomefunandchangethewordLuckywithTrickyinthebutton:
>varfeeling=document.querySelectorAll("button")[2];>feeling.textContent=feelingtextContent.replace(/Lu/,'Tri');"I'mFeelingTricky"
![Page 393: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/393.jpg)
Now,let'simplementthetrickypartandmakethatbuttonshowandhideforonesecond.Youcandothiswithasimplefunction.Let'scallittoggle().Everytimeyoucallthefunction,itchecksthevalueoftheCSSpropertyvisibility,andsetsittovisibleifit'shiddenandviceversausingthefollowingcodesnippet:
functiontoggle(){varst=document.querySelectorAll('button')[2].style;st.visibility=(st.visibility==='hidden')?'visible'
: 'hidden';}
Insteadofcallingthefunctionmanually,let'ssetanintervalandcalliteverysecond:
>varmyint=setInterval(toggle,1000);
Theresult?Thebuttonstartsblinking,makingittrickiertoclick.Whenyou'retiredofchasingit,justremovethetimeoutintervalbywritingthefollowinglineofcode:
>clearInterval(myint);
![Page 394: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/394.jpg)
Creatingnewnodes
Tocreatenewnodes,youcanusethecreateElement()andcreateTextNode()methods.Onceyouhavethenewnodes,youcanaddthemtotheDOMtreeusingappendChild(),insertBefore(),orreplaceChild().
Reloadhttp://www.phpied.com/files/jsoop/ch7.htmlandlet'splay.
CreateanewpelementandsetitsinnerHTML,asshowninthefollowingcode:
>varmyp=document.createElement('p');>myp.innerHTML='yetanother';"yetanother"
Thenewelementautomaticallygetsallthedefaultproperties,suchasstyle,whichyoucanmodifyasfollows:
>myp.style;CSSStyleDeclaration>myp.style.border='2pxdottedblue';"2pxdottedblue"
UsingappendChild(),youcanaddthenewnodetotheDOMtree.Callingthismethodonthedocument.bodynodemeanscreatingonemorechildnoderightafterthelastchild,asfollows:
>document.body.appendChild(myp);<pstyle="border:2pxdottedblue;">yetanother</p>
Here'sanillustrationofhowthepagelookslikeafterthenewnodeisappended:
DOM-onlymethod
TheinnerHTMLpropertygetsthingsdonealittlemorequicklythanusingpureDOM.InpureDOM,youwillneedtoperformthefollowingsteps:
1. Createanewtextnodecontainingyetanothertext.
![Page 395: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/395.jpg)
2. Createanewparagraphnode.3. Appendthetextnodeasachildtotheparagraph.4. Appendtheparagraphasachildtothebody.
Thisway,youcancreateanynumberoftextnodesandelementsandnestthem,howeveryoulike.Let'ssay,youwanttoaddthefollowingHTMLtotheendofthebody:
<p>onemoreparagraph<strong>bold</strong></p>
Presentingthepreceding codeasahierarchywouldbesomethinglikethefollowingcodesnippet:
Pelementtextnodewithvalue"onemoreparagraph"STRONGelementtextnodewithvalue"bold"
Thecodethataccomplishesthisisasfollows:
//createPvarmyp=document.createElement('p');
// create text node and append to Pvarmyt=document.createTextNode('onemoreparagraph');myp.appendChild(myt);//createSTRONGandappendanothertextnodetoitvarstr=document.createElement('strong');str.appendChild(document.createTextNode('bold'));//appendSTRONGtoPmyp.appendChild(str);//appendPtoBODYdocument.body.appendChild(myp);
UsingcloneNode()method
Anotherwaytocreatenodesisbycopyingorcloningexistingones.ThecloneNode()methoddoesthisandacceptsaBooleanparameter(true=deepcopywithallthechildren,false=shallowcopy,onlythisnode).Let'stestthemethod.
Gettingareferencetotheelementyouwanttoclonecanbedoneasfollows:
>varel=document.getElementsByTagName('p')[1];
Now,elreferstothesecondparagraphonthepagethatlookslikethefollowingcode:
<p><em>second</em>paragraph</p>
Let'screateashallowcloneofelandappendittothebodyasfollows:
>document.body.appendChild(el.cloneNode(false));
![Page 396: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/396.jpg)
Youwon'tseeadifferenceonthepagebecausetheshallowcopyonlycopiedthePnodewithoutanychildren.Thismeansthatthetextinsidetheparagraph,whichisatext nodechild,wasnotcloned.Theprecedinglinewillbeequivalenttothefollowingcodeline:
>document.body.appendChild(document.createElement('p'));
However,ifyoucreateadeepcopy,thewholeDOMsubtreestartingfromPiscopied,andthisincludestextnodesandtheEMelement.Thislinecopies(visuallytoo)the secondparagraphtotheendofthedocument.Considerthefollowinglineofcode:
>document.body.appendChild(el.cloneNode(true));
YoucanalsocopyonlytheEMifyouwant,asshowninthefollowinglinesofcode:
>document.body.appendChild(el.firstChild.cloneNode(true));<em>second</em>
Or,youcancopyonlythetextnodewithvaluesecond,asfollows:
>document.body.appendChild(el.firstChild.firstChild.cloneNode(false));"second"
UsinginsertBefore()method
UsingappendChild(),youcanonlyaddnewchildrenattheendoftheselectedelement.Formorecontrolovertheexactlocation,thereisinsertBefore().ThisisthesameasappendChild(),butacceptsanextraparameterspecifyingwhere(beforewhichelement)toinsertthenewnode.Forexample,thefollowingcodeinsertsatextnodeattheendofthebodyelement:
>document.body.appendChild(document.createTextNode('boo!'));
Moreover,thiscreatesanothertextnodeandaddsitasthefirstchildofthebodyelement:
document.body.insertBefore(document.createTextNode('firstboo!'),document.body.firstChild);
![Page 397: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/397.jpg)
Removingnodes
ToremovenodesfromtheDOMtree,youcanusetheremoveChild()method.Again,let'sstartfreshwiththesamepagewiththebody:
<body><pclass="opener">firstparagraph</p><p><em>second</em>paragraph</p><pid="closer">final</p><!--andthat'saboutit--></body>
Here'showyoucanremovethesecondparagraph:
>varmyp=document.getElementsByTagName('p')[1];>varremoved=document.body.removeChild(myp);
Themethodreturnstheremovednodeifyouwanttouseitlater.YoucanstillusealltheDOMmethodseventhoughtheelementisnolongerinthetree.Letstakealookonthefollowingcode:
>removed;<p>...</p>>removed.firstChild;<em>second</em>
There'salsothereplaceChild()methodthatremovesanodeandputsanotheroneinitsplace.
Afterremovingthenode,thetreelooksasfollows:
<body><pclass="opener">firstparagraph</p><pid="closer">final</p><!--andthat'saboutit--></body>
Now,thesecondparagraphistheonewiththeID"closer",whichisasfollows:
>varp=document.getElementsByTagName('p')[1];>p;<pid="closer">final</p>
Let'sreplacethisparagraphwiththeoneintheremovedvariable.Considerthefollowingcode:
>varreplaced=document.body.replaceChild(removed,p);
JustlikeremoveChild(),replaceChild()returnsareferencetothenodethatisnowoutofthetree:
>replaced;<pid="closer">final</p>
![Page 398: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/398.jpg)
Now,thebodylookslikethefollowingpieceofcode:
<body><pclass="opener">firstparagraph</p><p><em>second</em>paragraph</p><!--andthat'saboutit--></body>
Aquickwaytowipeout allofthecontentofasubtreeistosetinnerHTMLtoablankstring.Thisremovesallthechildrenofthebodyelement:
>document.body.innerHTML='';""
Testingisdoneasfollows:
>document.body.firstChild;null
RemovingwithinnerHTMLisfastandeasy.TheDOM-onlywaywillbetogooverallofthechildnodesandremoveeachoneindividually.Here'salittlefunctionthatremovesallnodesfromagivenstartnode:
functionremoveAll(n){while(n.firstChild){n.removeChild(n.firstChild);}}
Ifyouwanttodeleteallthechildrenfromthebodyelementandleavethepagewithanempty<body></body>,usethefollowingcode:
>removeAll(document.body);
![Page 399: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/399.jpg)
HTML-onlyDOMobjects
Asyoualreadyknow,theDOMappliestobothXMLandHTMLdocuments.Whatyou'velearnedearlierabouttraversingthetreeandthenadding,removing,ormodifyingnodes,appliestoanyXMLdocument.Thereare,however,someHTML-onlyobjectsandproperties.
Thedocument.bodyisonesuchHTML-onlyobject.It'ssocommontohavea<body>taginHTMLdocuments,andit'saccessedsooften,thatitmakessensetohaveanobjectthat'sshorterandfriendlierthantheequivalentdocument.getElementsByTagName('body')[0].
Thedocument.bodyelementisoneexampleofalegacyobjectinheritedfromtheprehistoricDOMLevel0andmovedtotheHTMLextension oftheDOMspecification.Thereareotherobjectssimilartodocument.bodyelement.Forsomeofthem,thereisnocoreDOMequivalent,forothers,thereisanequivalent;however,theDOM0originalwasanywayportedforsimplicityand legacy purposes. Let's see some of those objects.
Primitivewaystoaccessthedocument
totheelementsofanHTMLdocument.Thiswasdonemainlythroughanumberofcollections,whichareasfollows:UnliketheDOM,whichgivesyouaccesstoanyelement,andevencommentsandwhitespace,initially,JavaScripthadonlylimitedaccesstotheelementsofanHTMLdocument.Thiswasdonemainlythroughanumberofcollections,whichareasfollows:
document.images:Thisisacollectionofalloftheimagesonthepage.TheCoreDOMequivalentisdocument.getElementsByTagName('img').document.applets:Thisisthesameasdocument.getElementsByTagName('applet').document.links:Thedocument.linkscollectioncontainsalistofall<ahref="..."></a>tagsonthepage,meaningthe<a>tagsthathaveanhrefattribute.document.anchors:Thedocument.anchorscollectioncontainsalllinkswithanameattribute(<aname="..."></a>).document.forms:Oneofthemostwidelyusedcollectionsisdocument.forms,whichcontainsalistof<form>elements.
Let'splaywithapagethatcontainsaformandaninput(http://www.phpied.com/files/jsoop/ch7-form.html).Thefollowinglineofcodegivesyouaccesstothefirstformonthepage:
>document.forms[0];
It'sthesameasthefollowinglineofcode:
>document.getElementsByTagName('forms')[0];
Thedocument.formscollectioncontainscollectionsofinputfieldsandbuttons,accessiblethroughtheelementsproperty.Here'showtoaccessthefirstinputofthefirstformonthepage:
![Page 400: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/400.jpg)
>document.forms[0].elements[0];
Onceyouhaveaccessto anelement,youcanaccessitsattributesasobjectproperties.Thefirstfieldofthefirstforminthetestpageisasfollows:
<inputname="search"id="search"type="text"size="50"maxlength="255"value="Enteremail..."/>
Youcanchangethetextinthefield(thevalueofthevalueattribute)usingthefollowingcode:
>document.forms[0].elements[0].value='[email protected]';"[email protected]"
Ifyouwanttodisablethefielddynamically,usethefollowingcode:
>document.forms[0].elements[0].disabled=true;
Whenformsorformelementshaveanameattribute,youcanaccessthembynametoo,asshowninthefollowingcode:
>document.forms[0].elements['search'];//arraynotation>document.forms[0].elements.search;//objectproperty
Usingdocument.write()method
Thedocument.write()methodallowsyoutoinsertHTMLintothepagewhilethepageisbeingloaded.Youcanhavesomethinglikethefollowingcode:
<p>Itisnow<script>document.write("<em>"+newDate()+"</em>");</script></p>
ThisisthesameasifyouhadthedatedirectlyinthesourceoftheHTMLdocument,asfollows:
<p>Itisnow<em>FriApr26201316:55:16GMT-0700(PDT)</em></p>
Notethatyoucanonlyusedocument.write()methodwhilethepageisbeingloaded.Ifyoutryitafterpageload,itwill replacethecontentofthewholepage.
It'srarethatyouwouldneeddocument.write()method,andifyouthinkyoudo,tryanalternativeapproach.ThewaystomodifythecontentsofthepageprovidedbyDOMLevel1arepreferredandaremuchmoreflexible.
Cookies,title,referrer,anddomain
Thefouradditionalpropertiesofdocumentyou'llseeinthissectionarealsoportedfromDOM
![Page 401: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/401.jpg)
Level0totheHTMLextensionofDOMLevel1. Unlikethepreviousones,fortheseproperties,therearenocoreDOMequivalents.
The document.cookie is a property that contains a string. This string is the content of thecookies exchanged between the server and the client. When the server sends a page to thebrowser,itmayincludetheSet-CookieHTTPheader.Whentheclientsendsarequesttotheserver,itsendsthecookieinformationbackwiththeCookieheader.Usingdocument.cookie,youcanalterthecookiesthebrowsersendstotheserver.Forexample,visitingcnn.comandtypingdocument.cookieintheconsolegivesyouthefollowingoutput:
>document.cookie;"mbox=check#true#1356053765|session#1356053704195-121286#1356055565;...
Thedocument.titlepropertyallowsyoutochangethetitleofthepagedisplayedinthebrowserwindow.Forexample,seethefollowingcode:
>document.title='Mytitle';"Mytitle"
Notethatthisdoesn'tchangethevalueofthe<title>element,butonlythedisplayinthebrowserwindow,soit'snotequivalenttodocument.querySelector('title').
Thedocument.referrerpropertytellsyoutheURLofthepreviouslyvisitedpage.ThisisthesamevaluethebrowsersendsintheRefererHTTPheaderwhenrequestingthepage.(NotethatRefererismisspelledintheHTTPheaders,butiscorrectinJavaScript'sdocument.referrer).Ifyou'vevisitedtheCNNpagebysearchingonYahoofirst,youcanseesomethinglikethefollowing:
>document.referrer;"http://search.yahoo.com/search?p=cnn&ei=UTF-8&fr=moz2"
Thedocument.domainpropertygivesyouaccesstothedomainnameofthecurrentlyloadedpage.Thisiscommonlyusedwhenyouneedtoperformso-calleddomainrelaxation.Imagineyourpageiswww.yahoo.com,andinsideit,youhaveaniframehostedonmusic.yahoo.comsubdomain.Thesearetwoseparatedomains,sothebrowser'ssecurityrestrictionswon'tallowthepageandtheiframetocommunicate.Toresolvethis,youcansetdocument.domainpropertyonbothpagestoyahoo.comandthey'llbeabletotalktoeachother.
Notethatyoucanonlysetthedomaintoalessspecificone,forexample,youcanchangewww.yahoo.comtoyahoo.com,butyoucannotchangeyahoo.comtowww.yahoo.com,oranyothernon-yahoodomain.Considerthefollowingcode:
>document.domain;"www.yahoo.com">document.domain='yahoo.com';"yahoo.com"
![Page 402: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/402.jpg)
>document.domain='www.yahoo.com';Error:SecurityError:DOMException18>document.domain='www.example.org';Error:SecurityError:DOMException18
Previously,inthischapter,yousawthewindow.locationobject.Well,thesamefunctionalityisalsoavailableasdocument.locationobject:
>window.location===document.location;true
![Page 403: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/403.jpg)
EventsImagine you are listening to a radio program and they announce, "Big event! Huge! Aliens havelandedonEarth!"Youmightthink,"Yeah,whatever";someotherlistenersmightthink"Theycomeinpeace";andsomemightthink,"We'reallgonnadie!".Similarly,thebrowserbroadcastsevents,andyourcodecanbenotifiedshoulditdecidetotuneinandlistentotheeventsastheyhappen.Someexampleeventsareasfollows:
TheuserclicksabuttonTheusertypesacharacterinaformfieldThepagefinishesloading
YoucanattachaJavaScriptfunctioncalledevent listeneroreventhandlertoaspecificeventandthebrowserwillinvokeyourfunctionassoonastheeventoccurs.Let'sseehowthisisdone.
![Page 404: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/404.jpg)
InlineHTMLattributes
Addingspecificattributestoatagisthelaziestbuttheleastmaintainableway;takethefollowinglineofcodeasanexample:
<divonclick="alert('Ouch!')">click</div>
Inthiscase,whentheuserclickson<div>,theclickeventfiresandthestringofJavaScriptcodecontainedintheonclickattributeisexecuted.There'snoexplicitfunctionthatlistenstotheclickevent;however,behindthescenes,afunctionisstillcreated,anditcontainsthecodeyouspecifiedasavalueoftheonclickattribute.
![Page 405: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/405.jpg)
ElementProperties
AnotherwaytohavesomecodeexecutedwhenaclickeventfiresistoassignafunctiontotheonclickpropertyofaDOMnodeelement.Forexample,takealookatthefollowingpieceofcode:
<divid="my-div">click</div><script>varmyelement=document.getElementById('my-div');myelement.onclick=function(){
alert('Ouch!');alert('Anddoubleouch!');};</script>
Thiswayisbetterbecauseithelpsyoukeepyour<div>tagcleanofanyJavaScriptcode.AlwayskeepinmindthatHTMLisforcontent,JavaScriptforbehavior,andCSSforformatting,andyoushouldkeepthesethreeseparateasmuchaspossible.
Thismethodhasthedrawbackthatyoucanattachonlyonefunctiontotheevent,asiftheradioprogramhasonlyonelistener.It'struethatyoucanhavealothappeninginsidethesamefunction,butthisisnotalwaysconvenient,asifalltheradiolistenersareinthesameroom.
![Page 406: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/406.jpg)
DOMeventlisteners
ThebestwaytoworkwithbrowsereventsistousetheeventlistenerapproachoutlinedinDOMLevel2,whereyoucanhavemanyfunctionslisteningtoanevent.Whenaneventfires,allthefunctionsareexecuted.Allofthelistenersdon'tneedtoknowabouteachotherandcanworkindependently.Theycantuneinandoutatanytime,withoutaffectingtheotherlisteners.
Let'susethesamesimplemarkupfromtheprevioussection,whichisavailableforyoutoplaywithathttp://www.phpied.com/files/jsoop/ch7.html.Ithasthispieceofmarkup,whichisasfollows:
<pid="closer">final</p>
YourJavaScriptcodecanassignlistenerstotheclickeventusingtheaddEventListener()method.Let'sattachtwolistenersasfollows:
varmypara=document.getElementById('closer');mypara.addEventListener('click',function(){alert('Boo!');
}, false);mypara.addEventListener('click',console.log.bind(console),false);
Asyoucansee,addEventListeners
![Page 407: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/407.jpg)
Capturingandbubbling
InthecallstoaddEventListener(),therewasathirdparameter-false. Let'sseewhatitisfor.
Let'ssayyouhavealinkinsideanunorderedlist,whichisasfollows:
<body><ul><li><ahref="http://phpied.com">myblog</a></li></ul></body>
Whenyouclickonthelink,you'reactuallyalsoclickingonthelistitem,<li>,the<ul>list,the<body>tag,andeventually,thedocumentasawhole.Thisiscalledevent propagation.Aclickonalinkcanalsobeseenasaclickonthedocument.Theprocessofpropagatinganeventcanbeimplementedinthetwofollowingways:
Eventcapturing:Thisclickhappensinthedocumentfirst,thenitpropagatesdowntothebody,thelist,thelistitem,andfinally,tothelinkEventbubbling:Thisclickhappensonthelinkandthenbubblesuptothedocument
DOMlevel2eventsspecificationsuggeststhattheeventspropagateinthreephases,namely,capturing,attarget,andbubbling.Thismeansthattheeventpropagatesfromthedocumenttothelink(target)andthenbubblesbackuptothedocument.TheeventobjectshaveaneventPhaseproperty,whichreflectsthecurrentphase:
![Page 408: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/408.jpg)
Historically, IE and Netscape (working on their own and without a standard to follow)implementedtheexactopposites.IEimplementedonlybubblingandNetscapeonlycapturing.Today,longaftertheDOMspecification,modernbrowsersimplementall threephases.
![Page 409: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/409.jpg)
Thepracticalimplicationsrelatedtotheeventpropagationareasfollows:
ThethirdparametertoaddEventListener()specifieswhetherornotcapturingshouldbeused.Inordertohaveyourcodemoreportableacrossbrowsers,it'sbettertoalwayssetthisparametertofalseandusebubblingonly.Youcanstopthepropagationoftheeventinyourlistenerssothatitstopsbubblingupandneverreachesthedocument.Todothis,youcancallthestopPropagation()methodoftheeventobject;thereisanexampleinthenextsection.Youcanalsouseeventdelegation.Ifyouhavetenbuttonsinside<div>,youcanalwaysattachteneventlisteners,oneforeachbutton.However,asmarterthingtodoistoattachonlyonelistenertothewrapping<div>andoncetheeventhappens,checkwhichbuttonwasthetargetoftheclick.
Asasidenote,thereisawaytouseeventcapturinginoldIEstoo(usingsetCapture()andreleaseCapture()methods)butonlyformouseevents.Capturinganyotherevents(keystrokeeventsforexample)isnotsupported.
![Page 410: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/410.jpg)
Stoppropagation
Let'sseeanexampleofhowyoucanstoptheeventfrombubblingup.Goingbacktothetestdocument,thereisthispieceofcode:
<pid="closer">final</p>
Let'sdefineafunctionthathandlesclicksontheparagraph,asfollows:
functionparaHandler(){alert('clickedparagraph');}
Now,let'sattachthisfunctionasalistenertotheclickevent:
varpara=document.getElementById('closer');para.addEventListener('click',paraHandler,false);
Let'salsoattachlistenerstotheclickeventonthebody,thedocument,andthebrowserwindow:
document.body.addEventListener('click',function(){alert('clickedbody');},false);
document.addEventListener('click', function () {alert('clickeddoc');},false);window.addEventListener('click',function(){alert('clickedwindow');},false);
NotethattheDOMspecificationsdon'tsayanythingabouteventsonthewindow.Andwhywouldthey,asDOMdealswiththedocumentandnotthebrowser.Sobrowsersimplementwindoweventsinconsistently.
Now,ifyouclickontheparagraph,you'llseefouralertssaying:
clickedparagraphclickedbodyclickeddocclickedwindow
Thisillustrateshowthesamesingleclickeventpropagates(bubblesup)fromthetargetallthewayuptothewindow.
The opposite of addEventLister() is removeEventListener(), and it accepts exactly thesame parameters. Let's remove the listener attached to the paragraph by writing the following lineofcode:
![Page 411: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/411.jpg)
>para.removeEventListener('click',paraHandler,false);
Ifyoutrynow,you'llseealertsonlyfortheclickeventonthebody,document,andwindow,butnotontheparagraph.
Now,let'sstopthepropagationoftheevent.Thefunctionyouaddasalistenerreceivestheeventobjectasaparameter,andyoucancallthestopPropagation()methodofthateventobjectasfollows:
functionparaHandler(e){alert('clickedparagraph');e.stopPropagation();}
Addingthemodifiedlistenerisdoneasfollows:
para.addEventListener('click',paraHandler,false);
Now,whenyouclickontheparagraph,youwillseeonlyonealertbecausetheeventdoesn'tbubbleuptothebody,thedocument,orthewindow.
Notethatwhenyouremovealistener,youhavetopassapointertothesamefunctionyoupreviouslyattached.Otherwise,doingthefollowingdoesnotworkbecausethesecondargumentisanewfunction,notthesameyoupassedwhenaddingtheeventlistener,evenifthebodyisexactlythesame.Considerthefollowingcode:
document.body.removeEventListener('click',function(){alert('clickedbody');},false);//doesNOTremovethehandler
![Page 412: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/412.jpg)
Preventdefaultbehavior
Somebrowsereventshaveapredefinedbehavior.Forexample,clickingalinkcausesthebrowsertonavigatetoanotherpage.Youcanattachlistenerstoclicksonalink,andyoucanalsodisablethedefaultbehaviorbycallingthepreventDefault()methodontheeventobject.
Let'sseehowyoucanannoyyourvisitorsbyasking"Areyousureyouwanttofollowthislink?"everytimetheyclickalink?IftheuserclicksonCancel(causingconfirm()toreturnfalse),thepreventDefault()methodiscalled,whichisshownasfollows:
//alllinksvarall_links=document.getElementsByTagName('a');for(vari=0;i<all_links.length;i++){//loopalllinks
all_links[i].addEventListener('click',//eventtypefunction(e){//handlerif(!confirm('Sureyouwanttofollowthislink?')){e.preventDefault();}},false//don'tusecapturing);}
Notethatnotalleventsallowyoutopreventthedefaultbehavior.Mostdo,butifyouwanttobesure,youcancheckthecancellablepropertyoftheeventobject.
![Page 413: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/413.jpg)
Cross-browsereventlisteners
Asyoualreadyknow,mostmodernbrowsersalmostfullyimplementtheDOMLevel1specification.However,theeventswerenotstandardizeduntilDOM2.Asaresult,therearequiteafewdifferencesinhowIE,beforeversion9,implementsthisfunctionalitycomparedtomodernbrowsers.
CheckoutanexamplethatcausesnodeNameofaclickedelement(thetargetelement)tobewrittentotheconsole:
document.addEventListener('click',function(e){console.log(e.target.nodeName);},false);
Now,let'stakealookathowIEisdifferent:
InIE,there'snoaddEventListener()method;although,sinceIEVersion5,thereisanequivalentattachEvent()method.Forearlierversions,youronlychoiceisaccessingthepropertydirectly,suchasonclick.TheclickeventbecomesonclickwhenusingattachEvent().Ifyoulistentoeventstheoldfashionedway (forexample,bysettingafunctionvaluetotheonclickproperty),whenthecallbackfunctionisinvoked,itdoesn'tgetaneventobjectpassedasaparameter.However,regardlessofhowyouattachthelistenerinIE,thereisalwaysaglobalobjectwindow.eventthatpointstothelatestevent.InIE,theeventobjectdoesn'tgetatargetattributetellingyoutheelementonwhichtheeventfired,butitdoeshaveanequivalentpropertycalledsrcElement.Asmentionedearlier,eventcapturingdoesn'tapplytoallevents,soonlybubblingshouldbeused.There'snostopPropagation()method,butyoucansettheIE-onlycancelBubblepropertytotrue.There'snopreventDefault()method,butyoucansettheIE-onlyreturnValuepropertytofalse.Tostoplisteningtoanevent,insteadofremoveEventListener()inIE,you'llneeddetachEvent().
So,here'stherevisedversionofthepreviouscodethatworksacrossbrowsers:
functioncallback(evt){//prepworkevt=evt||window.event;vartarget=evt.target||evt.srcElement;
//actualcallbackworkconsole.log(target.nodeName);}
![Page 414: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/414.jpg)
//startlisteningforclickeventsif(document.addEventListener){//Modernbrowsersdocument.addEventListener('click',callback,false);}elseif(document.attachEvent){//oldIEdocument.attachEvent('onclick',callback);}else{document.onclick=callback;//ancient}
![Page 415: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/415.jpg)
Typesofevents
Nowyouknowhowtohandlecross-browserevents.However,alloftheprecedingexamplesusedonlyclickevents.Whatothereventsarehappeningoutthere?Asyoucanprobablyguess,differentbrowsersprovidedifferentevents.Thereisasubsetofcross-browserevents,andsomebrowser-specificones.Forafulllistofevents,youshouldconsultthebrowser'sdocumentation,buthere'saselectionofcross-browserevents:
Mouseeventsmouseup,mousedown,click(thesequenceismousedown-up-click),dblclickmouseover(mouseisoveranelement),mouseout(mousewasoveranelementbutleftit),mousemove
Keyboardeventskeydown,keypress,keyup(occurinthissequence)
Loading/windoweventsload(animageorapageandallofitscomponentsaredoneloading),unload(userleavesthepage),beforeunload(thescriptcanprovidetheuserwithanoptiontostoptheunload)abort(userstopsloadingthepageoranimageinIE),error(aJavaScripterror,alsowhenanimagecannotbeloadedinIE)resize(thebrowserwindowisresized),scroll(thepageisscrolled),contextmenu(theright-clickmenuappears)
Form eventsfocus(enteraformfield),blur(leavetheformfield)change(leaveafieldafterthevaluehaschanged),select(selecttextinatextfield)reset(wipeoutalluserinput),submit(sendtheform)
Additionally,modernbrowsersprovidedragevents(dragstart,dragend,drop,andamongothers)andtouchdevicesprovidetouchstart,touchmove,andtouchend.
Thisconcludesthediscussionofevents.Refertotheexercisesectionattheendofthischapterforalittlechallengeofcreatingyourowneventutilitytohandlecross-browserevents.
![Page 416: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/416.jpg)
XMLHttpRequestXMLHttpRequest() is an object (a constructor function) that allows you to send HTTP requestsfrom JavaScript. Historically, XHR (XMLHttpRequest) was introduced in IE and wasimplemented as an ActiveX object. Starting with IE7, it's a native browser object, the same wayasit'sintheotherbrowsers.Thecommonimplementationofthisobjectacrossbrowsersgavebirthtotheso-calledAjaxapplications,whereit'snolongernecessarytorefreshthewholepageeverytimeyouneednewcontent.WithJavaScript,youcanmakeanHTTPrequesttotheserver,gettheresponse,andupdateonlyapartofthepage.Thisway,youcanbuildmuchmoreresponsiveanddesktop-likewebpages.
AjaxstandsforAsynchronousJavaScriptandXML:
Asynchronousbecause,aftersendinganHTTPrequest,yourcodedoesn'tneedtowaitfortheresponse;however,itcandootherstuffandbenotified,throughanevent,whentheresponsearrives.JavaScriptbecauseit'sobviousthatXHRobjectsarecreatedwithJavaScript.XMLbecauseinitiallydevelopersweremakingHTTPrequestsforXMLdocumentsandwereusingthedatacontainedinthemtoupdatethepage.Thisisnolongeracommonpractice,though,asyoucanrequestdatainplaintext,inthemuchmoreconvenientJSONformat,orsimplyasHTMLreadytobeinsertedintothepage.
TherearetwostepstousingtheXMLHttpRequestobject,whichareasfollows:
Sendtherequest:ThisincludescreatinganXMLHttpRequestobjectandattachinganeventlistenerProcesstheresponse:Thishappenswhenyoureventlistenergetsnotifiedthattheresponsehasarrived,andyourcodegetsbusydoingsomethingamazingwiththeresponse
![Page 417: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/417.jpg)
Sendingtherequest
Inordertocreateanobject,youwillsimplyusethefollowingcode(let'sdealwithbrowserinconsistenciesinjustabit):
varxhr=newXMLHttpRequest();
Thenextthingistoattachaneventlistenertothereadystatechangeeventfiredbytheobject:
xhr.onreadystatechange=myCallback;
Then,youwillneedtocalltheopen()method,asfollows:
xhr.open('GET','somefile.txt',true);
ThefirstparameterspecifiesthetypeofHTTPrequest,suchasGET,POST,HEAD,andsoon.GETandPOSTarethemostcommonones.UseGETwhenyoudon'tneedtosendmuchdatawiththerequestandyourrequestdoesn'tmodify(write)dataontheserver,otherwise,usePOST.ThesecondparameteristheURLyouarerequesting.Inthisexample,it'sthetextfilesomefile.txtlocatedinthesamedirectoryasthepage.ThelastparameterisaBooleanspecifyingwhethertherequestisasynchronous(true,alwayspreferthis)ornot(false,blocksalltheJavaScriptexecutionandwaitsuntiltheresponsearrives).
Thelaststepistofireofftherequest,whichisdoneasfollows:
xhr.send('');
Thesend()methodacceptsanydatayouwanttosendwiththerequest.ForGETrequests,thisisanemptystringbecausethedataisintheURL.ForPOSTrequest,it'saquerystringinthekey=value&key2=value2form.
Atthispoint,therequestissentandyourcodeandtheusercanmoveontoothertasks.Thecallbackfunction,myCallback,willbeinvokedwhentheresponsecomesbackfromtheserver.
![Page 418: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/418.jpg)
Processingtheresponse
Alistenerisattachedtothereadystatechangeevent.So,whatexactlyisthereadystateandhowdoesitchange?
ThereisapropertyoftheXHRobjectcalledreadyState.Everytimeitchanges,thereadystatechangeeventfires.ThepossiblevaluesofthereadyStatepropertyareasfollows:
0-uninitialized1-loading2-loaded3-interactive4-complete
WhenreadyStategetsthevalueof4,itmeanstheresponseisbackandreadytobeprocessed.InmyCallback,afteryoumakesurereadyStateis4,theotherthingtocheckisthestatuscodeoftheHTTPrequest.Youmighthaverequestedanon-existingURL,forexample,andgota404(Filenotfound)statuscode.Theinterestingcode isthe200(OK)code,somyCallbackshouldcheckforthisvalue.ThestatuscodeisavailableinthestatuspropertyoftheXHRobject.
Oncexhr.readyStateis4andxhr.statusis200,youcanaccessthecontentsoftherequestedURLusingthexhr.responseTextproperty.Let'sseehowmyCallbackcanbeimplementedtosimplyalert()thecontentsoftherequestedURL:
functionmyCallback(){
if(xhr.readyState<4){return;//notreadyyet}if(xhr.status!==200){alert('Error!');//theHTTPstatuscodeisnotOKreturn;}
//allisfine,dotheworkalert(xhr.responseText);}
Onceyou'vereceivedthenewcontentyourequested,youcanaddittothepage,useitforsomecalculations,orforanyotherpurposeyoufindsuitable.
Overall, this two-step process (send request and process response) is the core of the wholeXHR/Ajaxfunctionality.Nowthatyouknowthebasics,youcanmoveontobuildingthenextGmail.Ohyes,let'stakealookatsomeminorbrowserinconsistencies.
![Page 419: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/419.jpg)
CreatingXMLHttpRequestobjectsinIEpriortoVersion7
InInternetExplorer,priortoversion7,theXMLHttpRequestobjectwasanActiveXobject,socreatinganXHRinstanceisalittledifferent.Itgoesasfollows:
varxhr=newActiveXObject('MSXML2.XMLHTTP.3.0');
MSXML2.XMLHTTP.3.0istheidentifieroftheobjectyouwanttocreate.ThereareseveralversionsoftheXMLHttpRequestobject,andifyourpagevisitordoesn'thavethelatestoneinstalled,youcantrytwoolderonesbeforeyougiveup.
Forafully-cross-browsersolution,youshouldfirsttesttoseeiftheuser'sbrowsersupportsXMLHttpRequestasanativeobject,andifnot,trytheIEway.Therefore, thewholeprocessofcreatinganXHRinstancecouldbelikethefollowing:
varids=['MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Microsoft.XMLHTTP'];varxhr;if(XMLHttpRequest){
xhr = new XMLHttpRequest();}else{//IE:trytofindanActiveXobjecttousefor(vari=0;i<ids.length;i++){try{xhr=newActiveXObject(ids[i]);break;}catch(e){}}}
Whatisthisdoing?TheidsarraycontainsalistofActiveXprogramIDstotry.ThexhrvariablepointstothenewXHRobject.ThecodefirstcheckstoseeifXMLHttpRequestexists.Ifso,thismeansthatthebrowsersupportsXMLHttpRequest()natively,sothebrowserisrelativelymodern.Ifitisnot,thecodeloopsthroughidstryingtocreateanobject.Thecatch(e)blockquietlyignoresfailuresandtheloopcontinues.Assoonasanxhrobjectiscreated,youbreakoutoftheloop.
Asyoucansee,thisisquiteabitofcode,soit'sbesttoabstractitintoafunction.Actually,oneoftheexercisesattheendofthechapterpromptsyoutocreateyourownAjaxutility.
![Page 420: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/420.jpg)
AisforAsynchronous
NowyouknowhowtocreateanXHRobject,giveitaURLandhandletheresponsetotherequest.Whathappenswhenyousendtworequestsasynchronously?Whatiftheresponsetothesecondrequestcomesbeforethefirst?
Intheprecedingexample,theXHRobjectwasglobalandmyCallbackwasrelyingonthepresenceofthisglobalobjectinordertoaccessitsreadyState,status,andresponseTextproperties.Anotherway,whichpreventsyoufromrelyingonglobalvariables,istowrapthecallbackinaclosure.Let'sseehow:
varxhr=newXMLHttpRequest();
xhr.onreadystatechange=(function(myxhr){returnfunction(){myCallback(myxhr);};}(xhr));
xhr.open('GET','somefile.txt',true);xhr.send('');
Inthiscase,myCallback()receivestheXHRobjectasaparameterandwillnotgolookingforitintheglobalspace.This alsomeansthatatthetimetheresponseisreceived,theoriginalxhrmightbereusedforasecondrequest.Theclosurekeepspointingtotheoriginalobject.
![Page 421: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/421.jpg)
XisforXML
AlthoughthesedaysJSON(discussedinthenextchapter)ispreferredoverXMLasadatatransferformat,XMLisstillanoption.InadditiontotheresponseTextproperty,theXHRobjectsalsohaveanotherpropertycalledresponseXML.WhenyousendanHTTPrequestforanXMLdocument,responseXMLpointstoanXMLDOMdocumentobject.Toworkwiththisdocument,youcanuseallofthecoreDOMmethodsdiscussedpreviouslyinthischapter,suchasgetElementsByTagName(),getElementById(),andsoon.
![Page 422: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/422.jpg)
Anexample
Let'swrapupthedifferentXHRtopicswithanexample.Youcanvisitthepagelocatedathttp://www.phpied.com/files/jsoop/xhr.htmltoworkontheexampleyourself.
Themainpage,xhr.html,isasimplestaticpagethatcontainsnothingbutthree<div>tags,whichareasfollows:
<divid="text">Textwillbehere</div><divid="html">HTMLwillbehere</div><divid="xml">XMLwillbehere</div>
Usingtheconsole,youcanwritecodethatrequeststhreefilesandloadstheirrespectivecontentsinto each <div>.
Thethreefilestoloadareasfollows:
content.txt:ThisisasimpletextfilecontainingthetextIamatextfilecontent.html:ThisisafilecontainingHTMLcodeIam<strong>formatted</strong><em>HTML</em>
content.xml:ThisisanXMLfilecontainingthefollowingcode:
<?xmlversion="1.0"?><root>I'mXMLdata.</root>
Allofthefilesarestoredinthesamedirectoryasxhr.html.
Note
Forsecurityreasons,youcanonlyusetheoriginalXMLHttpRequesttorequestfilesthatareonthesamedomain.However,modernbrowserssupportXHR2,whichletsyoumakecross-domainrequests,providedthattheappropriateAccess-Control-Allow-OriginHTTPheaderisinplace.
First,let'screateafunctiontoabstracttherequest/responsepart:
function request(url, callback) {varxhr=newXMLHttpRequest();xhr.onreadystatechange=(function(myxhr){returnfunction(){if(myxhr.readyState===4&&myxhr.status===200){callback(myxhr);}};}(xhr));xhr.open('GET',url,true);xhr.send('');
![Page 423: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/423.jpg)
}
ThisfunctionacceptsaURLtorequestandacallbackfunctiontocalloncetheresponsearrives.Let'scallthefunctionthreetimes,onceforeachfile,asfollows:
request('http://www.phpied.com/files/jsoop/content.txt',function(o){document.getElementById('text').innerHTML=o.responseText;});request('http://www.phpied.com/files/jsoop/content.html',
function (o) {document.getElementById('html').innerHTML=o.responseText;});request('http://www.phpied.com/files/jsoop/content.xml',function(o){document.getElementById('xml').innerHTML=o.responseXML.getElementsByTagName('root')[0].firstChild.nodeValue;});
Thecallbackfunctionsaredefinedinline.Thefirsttwoareidentical.TheyjustreplacetheHTMLofthecorresponding<div>withthecontentsoftherequestedfile.ThethirdoneisalittledifferentasitdealswiththeXMLdocument.First,youwillaccesstheXMLDOMobjectaso.responseXML.Then,usinggetElementsByTagName(),youwillgetalistofallthe<root>tags(thereisonlyone).ThefirstChildof<root>isatextnodeandnodeValueisthetextcontainedinit(I'mXMLdata).Then,justreplacetheHTMLof<divid="xml">withthenewcontent.Theresultisshowninthefollowingscreenshot:
![Page 424: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/424.jpg)
WhenworkingwiththeXMLdocument,youcanalsouseo.responseXML.documentElementtogettothe<root>elementinsteadofo.responseXML.getElementsByTagName('root')[0].RememberthatdocumentElementgivesyoutherootnodeofanXMLdocument.TherootinHTMLdocumentsisalwaysthe<html>tag.
![Page 425: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/425.jpg)
ExercisesIn the previous chapters, the solutions to the exercises could be found in the text of the chapter.Thistime,someoftheexercisesrequireyoutodosomemorereading,orexperimentation,outsidethisbook.
1. BOM:AsaBOMexercise,trycodingsomethingwrong,obtrusive,user-unfriendly,andallinall,veryWeb1.0,theshakingbrowserwindow.Tryimplementingcodethatopensa200x200popupwindowandthenresizesitslowlyandgraduallyto400x400.Next,movethewindowaroundasifthere'sanearthquake.Allyou'llneedisoneofthemove*()functions,oneormorecallstosetInterval(),andmaybeonetosetTimeout()/clearInterval()tostopthewholething.Or,here'saneasierone-printthecurrentdate/timeindocument.titleandupdateiteverysecond,likeaclock.
2. DOM:ImplementwalkDOM()differently.Also,makeitacceptacallbackfunctioninsteadofhardcodingconsole.log().RemovingcontentwithinnerHTMLiseasy(document.body.innerHTML=''),butnotalwaysbest.Theproblemwillbewhenthereareeventlistenersattachedtotheremovedelements;theywon'tberemovedinIE,causingthebrowsertoleakmemorybecause it stores references to something that doesn't exist. Implement a general-purposefunctionthatdeletesDOMnodes,butremovesanyeventlistenersfirst.Youcanloopthroughtheattributesofanodeandcheckifthevalueisafunction.Ifitis,it'smostlikelyanattributelikeonclick.Youneedtosetittonullbeforeremovingtheelementfromthetree.Createafunctioncalledinclude()thatincludesexternalscriptsondemand.Thismeansyouneedtocreateanew<script>tagdynamically,setitssrcattribute,andappendtothedocument's<head>.Testitbyusingthefollowingcode:
>include('somescript.js');
3. Events:Createaneventutility(object)calledmyevent,whichhasthefollowingmethodsworkingcross-browser:
TheaddListener(element,event_name,callback),whereelementcanalsobeanarrayofelementsremoveListener(element,event_name,callback)getEvent(event)justtocheckforawindow.eventforolderversionsofIEgetTarget(event)stopPropagation(event)preventDefault(event)
Usageexampleisasfollows:
functionmyCallback(e){
![Page 426: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/426.jpg)
e=myevent.getEvent(e);alert(myevent.getTarget(e).href);myevent.stopPropagation(e);myevent.preventDefault(e);}myevent.addListener(document.links,'click',myCallback);
Theresultoftheexamplecodeshouldbethatallofthelinksinthedocumentleadnowhere,butonlyalertthehrefattribute.Createanabsolutelypositioned<div>,sayatx=100px,y=100px.Writethecodetobeabletomovedivaroundthepage usingthearrowkeysortheJ(left),K(right),M(down),andI(up)keys.Reuseyourowneventutilityfrom3.1.
4. XMLHttpRequest:CreateyourownXHRutility(object)calledajax.Forexample,takealookatthefollowingcode:
functionmyCallback(xhr){alert(xhr.responseText);}ajax.request('somefile.txt','get',myCallback);ajax.request('script.php','post',myCallback,'first=John&last=Smith');
![Page 427: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/427.jpg)
SummaryYou learned quite a bit in this chapter. You learned the following cross-browser BOM objects:
Propertiesoftheglobalwindowobject,suchasnavigator,location,history,frames,screen
MethodssuchassetInterval()andsetTimeout();alert(),confirm()andprompt();moveTo/By()andresizeTo/By()
Then,youlearnedabouttheDOM,anAPItorepresentanHTMLorXMLdocumentasatreestructure,whereeachtagortextisanodeonthetree.Youalsolearnedhowtoperformthefollowingactions:
Accessingnodes:Usingparent/childrelationshipproperties,suchasparentNode,childNodes,firstChild,lastChild,nextSibling,andpreviousSiblingUsinggetElementsById(),getElementsByTagName(),getElementsByName(),andquerySelectorAll()
Modifyingnodes:UsinginnerHTMLorinnerText/textContentUsingnodeValueorsetAttribute(),orjustusingattributesasobjectproperties
RemovingnodeswithremoveChild()orreplaceChild()AddingnewoneswithappendChild(),cloneNode(),andinsertBefore()
YoualsolearnedthefollowingDOM0(pre-standardization)properties,portedtoDOMLevel1:
Collections,suchasdocument.forms,images,links,anchors,applets.UsingthesearediscouragedasDOM1hasthemuchmoreflexiblegetElementsByTagName()method.Thedocument.bodyelement,whichgivesyouconvenientaccessto<body>.Thedocument.title,cookie,referrer,anddomain.
Next,youlearnedhowthebrowserbroadcastseventsthatyoucanlistento.It'snotstraightforwardtodothisinacross-browsermanner,butit'spossible.Eventsbubbleup,soyoucanuseeventdelegationtolistentoeventsmoreglobally.Youcanalsostopthepropagationofeventsandinterferewiththedefaultbrowserbehavior.
Finally,youlearnedabouttheXMLHttpRequestobjectthatallowsyoutobuildresponsivewebpagesthatdothefollowingtasks:
MakeHTTPrequeststotheservertogetpiecesofdataProcesstheresponsetoupdateportionsofthepage
![Page 428: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/428.jpg)
Chapter 11. Coding and Design PatternsNow that you know all about the objects in JavaScript, mastered prototypes and inheritance, andseensomepracticalexamplesofusingbrowser-specificobjects,let'smoveforward,orrather,movealevelup.Let'stakealookatsomecommonJavaScriptpatterns.
Butfirst,what'sapattern?Inshort,apatternisagoodsolutiontoacommonproblem.Codifyingthesolutionintoapatternmakesitrepeatableaswell.
Sometimes,whenyou'refacinganewprogrammingproblem,youmayrecognizerightawaythatyou'vepreviouslysolvedanother,suspiciouslysimilarproblem.Insuchcases,it'sworthisolatingthisclassofproblemsandsearchingforacommonsolution.Apatternisaprovenandreusablesolution(oranapproach toasolution)toaclassofproblems.
Therearecaseswhereapatternisnothingmorethananideaoraname.Sometimes,justusinganame helps you think more clearly about a problem. Also, when working with other developers inateam,it'smucheasiertocommunicatewheneverybodyusesthesameterminologytodiscussaproblemorasolution.
Othertimes,youmaycomeacrossauniqueproblemthatdoesn'tlooklike anythingyou'veseenbeforeanddoesn'treadilyfitintoaknownpattern.Blindlyapplyingapatternjustforthesakeofusingapattern,isnotagoodidea.It'spreferabletonotuseanyknownpatternthantotrytotweakyourproblemsothatitfitsanexistingsolution.
Thischaptertalksabouttwotypesofpatterns,whichareasfollows:
Codingpatterns:ThesearemostlyJavaScript-specificbestpracticesDesignpatterns:Thesearelanguage-independentpatterns,popularizedbythefamousGangofFourbook
![Page 429: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/429.jpg)
Coding patternsLet's start with some patterns that reflect JavaScript's unique features. Some patterns aim to helpyouorganizeyourcode,forexample,namespacing;othersarerelatedtoimprovingperformance,suchaslazydefinitionsandinit-timebranching;andsomemakeupformissingfeatures,suchasprivateproperties.Thepatternsdiscussedinthissectionincludethefollowingtopics:
SeparatingbehaviorNamespacesInit-timebranchingLazydefinitionConfigurationobjectsPrivatevariablesandmethodsPrivileged methodsPrivatefunctionsaspublicmethodsImmediatefunctionsChainingJSON
![Page 430: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/430.jpg)
Separatingbehavior
Asdiscussedpreviously,thethreebuildingblocksofawebpageareasfollows:
Content (HTML)Presentation(CSS)Behavior(JavaScript)
Content
HTMListhecontentofthewebpage,theactualtext.Ideally,thecontentshouldbemarked-upusingtheleastamountof HTMLtagsthatsufficientlydescribethesemanticmeaningofthatcontent.Forexample,ifyou'reworkingonanavigationmenu,it'sagoodideatousethe<ul>and<li>tagsasanavigationmenuisinessence,justalistoflinks.
Yourcontent(HTML)shouldbefreefromanyformattingelements.VisualformattingbelongstothepresentationlayerandshouldbeachievedthroughtheuseofCSS(CascadingStyleSheets).Thismeansthefollowing:
ThestyleattributeofHTMLtagsshouldnotbeused,ifpossible.PresentationalHTMLtagssuchas<font>shouldnotbeusedatall.Tagsshouldbeusedfortheirsemanticmeaning,notbecauseofhowbrowsersrenderthembydefault.Forinstance,developerssometimesusea<div>tagwherea<p>wouldbemoreappropriate.It'salsofavorabletouse<strong>and<em>insteadof<b>and<i>asthelatterdescribethevisualpresentationratherthanthemeaning.
Presentation
Agoodapproachtokeeppresentationoutofthecontentistoresetornullifyallbrowserdefaults,forexample,usingreset.cssfromtheYahoo!UIlibrary.Thisway,thebrowser'sdefaultrenderingwon'tdistractyoufromconsciouslythinkingaboutthepropersemantictagstouse.
Behavior
Thethirdcomponentofawebpageisthebehavior.Behaviorshouldbekeptseparatefromboththecontentandthepresentation.ItisusuallyaddedbyusingJavaScriptthatisisolatedto<script>tags,andpreferablycontainedinexternalfiles.Thismeansnotusinganyinlineattributes,suchasonclick,onmouseover,andsoon.Instead,youcanusetheaddEventListener/attachEventmethodsfromthepreviouschapter.
Thebeststrategytoseparatebehaviorfromcontentisasfollows:
Minimizethenumberof<script>tagsAvoidinlineeventhandlersDonotuseCSSexpressionsTowardtheendofyourcontent,whenyouarereadytoclosethe<body>tag,insertasingle
![Page 431: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/431.jpg)
external.jsfile
Exampleofseparatingbehavior
Let'ssayyouhaveasearchformonapage,andyouwanttovalidatetheformwithJavaScript.So,yougoaheadandkeeptheformtagsfreefromanyJavaScript,andthenimmediatelybeforeclosingthe</body>tag, youinserta<script>tagthatlinkstoanexternalfile,asfollows:
<body><formid="myform"method="post"action="server.php"><fieldset><legend>Search</legend><inputname="search"id="search"type="text"/><inputtype="submit"/></fieldset></form><scriptsrc="behaviors.js"></script></body>
Inbehaviors.jsyouattachaneventlistenertothesubmitevent.Inyourlistener,youcanchecktoseeifthetextinputfieldwasleftblankand,ifso,stoptheformfrombeingsubmitted.Thisway,youwillsavearoundtripbetweentheserverandtheclientandmaketheapplicationimmediatelyresponsive.
Thecontentofbehaviors.jsisgiveninthefollowingcode.Itassumesthatyou'vecreatedyourmyeventutilityfromtheexerciseattheendofthepreviouschapter:
//initmyevent.addListener('myform','submit',function(e){//noneedtopropagatefurthere=myevent.getEvent(e);myevent.stopPropagation(e);//validatevarel=document.getElementById('search');if(!el.value){//toobad,fieldisemptymyevent.preventDefault(e);//preventtheformsubmissionalert('Pleaseenterasearchstring');}});
AsynchronousJavaScriptloading
You noticed how the script was loaded at the end of the HTML, right before closing the body. ThereasonisthatJavaScript blockstheDOMconstructionofthepage,andinsomebrowsers,evendownloadsoftheothercomponentsthatfollow.Bymovingthescriptstothebottomofthepage,youensurethatthescriptisoutoftheway,andwhenitarrives,itsimplyenhancesthealready
![Page 432: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/432.jpg)
usablepage.
AnotherwaytopreventexternalJavaScriptfilesfromblockingthepageistoloadthemasynchronously. This way you can start loading them earlier. HTML5 has the defer attribute forthis purpose. Consider the following line of code:
<scriptdefersrc="behaviors.js"></script>
Unfortunately,thedefer attributeisnotsupportedbyolderbrowsers,butluckily,thereisasolutionthatworksacrossbrowsers,oldandnew.ThesolutionistocreateascriptnodedynamicallyandappendittotheDOM.Inotherwords,youcanuseabitofinlineJavaScripttoloadtheexternalJavaScriptfile.Youcanhavethisscriptloadersnippetatthetopofyourdocumentsothatthedownloadhasanearlystart. Takealookatthefollowingcodeexample:
...<head><script>(function(){vars=document.createElement('script');s.src='behaviors.js';
document.getElementsByTagName('head')[0].appendChild(s);}());</script></head>...
![Page 433: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/433.jpg)
Namespaces
Globalvariablesshouldbeavoidedinordertoreducethepossibilityofvariablenamingcollisions.Youcanminimizethenumberofglobalsbynamespacingyourvariablesandfunctions.Theideaissimple,youwillcreateonlyoneglobalobject,andallyourothervariablesandfunctionsbecomepropertiesofthatobject.
AnObjectasanamespace
Let'screateaglobalobjectcalledMYAPP:
//globalnamespacevarMYAPP=MYAPP||{};
Now,insteadofhavingaglobalmyeventutility(fromthepreviouschapter),youcanhaveitasaneventpropertyoftheMYAPPobject,asfollows:
//sub-objectMYAPP.event={};
Addingthemethodstotheeventutilityisstillthesame.Considerthefollowingexample:
//objecttogetherwiththemethoddeclarationsMYAPP.event={addListener:function(el,type,fn){//..dothething},removeListener:function(el,type,fn){//...},getEvent:function(e){//...}//...othermethodsorproperties};
Namespacedconstructors
Usinganamespacedoesn'tpreventyoufromcreatingconstructorfunctions.HereishowyoucanhaveaDOMutilitythathasanElementconstructor,whichallowsyoutocreateDOMelementseasily:
MYAPP.dom={};MYAPP.dom.Element=function(type,properties){vartmp=document.createElement(type);for(variinproperties){if(properties.hasOwnProperty(i)){tmp.setAttribute(i,properties[i]);}}
![Page 434: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/434.jpg)
returntmp;};
Similarly,youcanhaveaTextconstructortocreatetextnodes.Considerthefollowingcodeexample:
MYAPP.dom.Text=function(txt){returndocument.createTextNode(txt);};
Usingtheconstructorstocreatealinkatthebottomofapagecanbedoneasfollows:
varlink=newMYAPP.dom.Element('a',{href:'http://phpied.com',target:'_blank'});vartext=newMYAPP.dom.Text('clickme');link.appendChild(text);document.body.appendChild(link);
Anamespace()method
Youcancreateanamespaceutilitythatmakesyourlifeeasiersothatyoucanusemoreconvenientsyntaxasfollows:
MYAPP.namespace('dom.style');
Insteadofthemoreverbosesyntaxasfollows:
MYAPP.dom={};MYAPP.dom.style={};
Here's how you can create such a namespace() method. First, you will create an array bysplitting the input string using the period (.) as a separator. Then, for every element in the newarray, you will add a property to your global object, if one doesn't already exist, as follows:
varMYAPP={};MYAPP.namespace=function(name){varparts=name.split('.');varcurrent=MYAPP;for(vari=0;i<parts.length;i++){if(!current[parts[i]]){current[parts[i]]={};}current=current[parts[i]];}};
Testingthenewmethodisdoneasfollows:
MYAPP.namespace('event');MYAPP.namespace('dom.style');
![Page 435: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/435.jpg)
Theresultoftheprecedingcodeisthesameasifyoudidthefollowing:
varMYAPP={event:{},dom:{style:{}}};
![Page 436: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/436.jpg)
Init-timebranching
Inthepreviouschapter,younoticedthatsometimes,differentbrowsershavedifferentimplementationsforthesameorsimilarfunctionalities.Insuchcases,youwillneedtobranchyourcode,dependingon what'ssupportedbythebrowsercurrentlyexecutingyourscript.Dependingonyourprogram,thisbranchingcanhappenfartoooftenand,asaresult,mayslowdownthescriptexecution.
Youcanmitigatethisproblembybranchingsomepartsofthecodeduringinitialization,whenthescriptloads,ratherthanduringruntime.Buildingupontheabilitytodefinefunctionsdynamically,youcanbranchanddefinethesamefunctionwith adifferentbody,dependingonthebrowser.Let'sseehow.
First,let'sdefineanamespaceandplaceholdermethodfortheeventutility:
varMYAPP={};MYAPP.event={addListener:null,removeListener:null};
Atthispoint,themethodstoaddorremovealistenerarenotimplemented.Basedontheresultsfromfeaturesniffing,thesemethodscanbedefineddifferently,asfollows:
if(window.addEventListener){MYAPP.event.addListener=function(el,type,fn){el.addEventListener(type,fn,false);};MYAPP.event.removeListener=function(el,type,fn){el.removeEventListener(type,fn,false);
};}elseif(document.attachEvent){//IEMYAPP.event.addListener=function(el,type,fn){el.attachEvent('on'+type,fn);};MYAPP.event.removeListener=function(el,type,fn){el.detachEvent('on'+type,fn);};}else{//olderbrowsersMYAPP.event.addListener=function(el,type,fn){el['on'+type]=fn;};MYAPP.event.removeListener=function(el,type){el['on'+type]=null;};}
Afterthisscriptexecutes,youhavetheaddListener()andremoveListener()methodsdefinedinabrowser-dependentway.Now,everytimeyouinvokeoneofthesemethods,there'snomore
![Page 437: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/437.jpg)
feature-sniffing,anditresultsinlessworkandfasterexecution.
Onethingtowatchoutforwhensniffingfeaturesisnottoassumetoomuchaftercheckingforonefeature. In the previous example, this rule is broken because the code only checks foraddEventListenersupport,butthendefinesbothaddListener()andremoveListener().Inthiscase,it'sprobablysafetoassumethatifabrowserimplementsaddEventListener(),italsoimplementsremoveEventListener().However,imaginewhathappensifabrowserimplementsstopPropagation()butnotpreventDefault(),andyouhaven'tcheckedfortheseindividually.YouhaveassumedthatbecauseaddEventListener()isnotdefined,thebrowsermustbeanoldIEandwriteyourcodeusingyourknowledgeandassumptionsofhowIEworks.Rememberthatallofyourknowledgeisbasedonthewayacertainbrowserworkstoday,butnotnecessarilythewayitwillworktomorrow.So,toavoidmanyrewritesofyourcodeasnewbrowserversionsareshipped,it'sbesttoindividuallycheckforfeaturesyouintendtouseanddon'tgeneralizeonwhatacertainbrowsersupports.
![Page 438: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/438.jpg)
Lazydefinition
Thelazydefinitionpatternissimilartothepreviousinit-timebranchingpattern.Thedifferenceisthatthebranchinghappensonlywhenthefunctioniscalledforthefirsttime.Whenthefunctioniscalled,itredefinesitself withthebestimplementation.Unliketheinit-timebranching,wheretheifhappensonce,duringloading,hereitmaynothappenatall,incaseswhenthefunctionisnevercalled.Thelazydefinitionalsomakestheinitializationprocesslighterasthere'snoinit-timebranchingworktobedone.
Let'sseeanexamplethatillustratesthisviathedefinitionofanaddListener()function.Thefunctionisfirstdefinedwithagenericbody.Itcheckswhichfunctionalityissupportedbythebrowserwhenit'scalledforthefirsttimeandthenredefinesitselfusingthemostsuitableimplementation.Attheendofthefirstcall,thefunctioncallsitself,sothattheactualeventattachingisperformed.Thenexttimeyoucallthesamefunction,itwillbedefinedwithitsnewbodyandbereadyforuse,sonofurtherbranchingisnecessary.Thefollowingisthecodesnippet:
varMYAPP={};MYAPP.myevent={addListener:function(el,type,fn){if(el.addEventListener){MYAPP.myevent.addListener=function(el,type,fn){el.addEventListener(type,fn,false);};}elseif(el.attachEvent){MYAPP.myevent.addListener=function(el,type,fn){el.attachEvent('on'+type,fn);};}else{MYAPP.myevent.addListener=function(el,type,fn){el['on'+type]=fn;
};}MYAPP.myevent.addListener(el,type,fn);}};
![Page 439: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/439.jpg)
Configurationobject
Thispatternisconvenientwhenyouhaveafunctionormethodthatacceptsalotofoptionalparameters.It'suptoyoutodecidehowmanyconstitutesalot.Butgenerally,afunctionwithmorethanthreeparametersisnotconvenienttocall,becauseyouhavetoremembertheorderoftheparameters,anditisevenmoreinconvenientwhensomeoftheparametersareoptional.
Insteadofhavingmanyparameters,youcanuseoneparameterandmakeitanobject.Thepropertiesoftheobjectaretheactualparameters.Thisissuitabletopassconfigurationoptionsbecausethesetendtobenumerousandoptional(withsmartdefaults).Thebeautyofusingasingleobjectasopposedtomultipleparametersisdescribedasfollows:
Theorderdoesn'tmatterYoucaneasilyskip parametersthatyoudon'twanttosetIt'seasytoaddmoreoptionalconfigurationattributesItmakesthecodemorereadablebecausetheconfigurationobject'spropertiesarepresentinthecallingcodealongwiththeirnames
ImagineyouhavesomesortofUIwidgetconstructoryouusetocreatefancybuttons.Itacceptsthetexttoputinsidethebutton(thevalueattributeofthe<input>tag)andanoptionalparameterofthetypeofbutton.Forsimplicity,let'ssaythefancybuttontakesthesameconfigurationasaregularbutton.Takealookatthefollowingcode:
//aconstructorthatcreatesbuttonsMYAPP.dom.FancyButton=function(text,type){varb=document.createElement('input');b.type=type||'submit';b.value=text;returnb;
};
Usingtheconstructorissimple;youjustgiveitastring.Then,youcanaddthenewbuttontothebodyofthedocumentasfollows:
document.body.appendChild(newMYAPP.dom.FancyButton('puuush'));
Thisisallwellandworksfine,butthenyoudecideyoualsowanttobeabletosetsomeofthestylepropertiesofthebutton,suchascolorsandfonts.Youcanendupwithadefinitionlikethefollowing:
MYAPP.dom.FancyButton=function(text,type,color,border,font){//...
};
![Page 440: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/440.jpg)
Now,usingtheconstructorcanbecomealittleinconvenient,especiallywhenyouwanttosetthethirdandfifthparameter,butnotthesecondorthefourth.Considerthefollowingexample:
newMYAPP.dom.FancyButton('puuush',null,'white',null,'Arial');
Abetterapproachistouseoneconfigobjectparameterforallthesettings.Thefunctiondefinitioncanbecomesomethinglikethefollowingcodesnippet:
MYAPP.dom.FancyButton=function(text,conf){vartype=conf.type||'submit';varfont=conf.font||'Verdana';//...};
Usingtheconstructorisshownasfollows:
varconfig={font:'Arial,Verdana,sans-serif',color:'white'
};newMYAPP.dom.FancyButton('puuush',config);
Anotherusageexampleisasfollows:
document.body.appendChild(newMYAPP.dom.FancyButton('dude',{color:'red'}));
Asyoucansee,it'seasytosetonlysomeoftheparametersandtoswitcharoundtheirorder.Inaddition,thecodeisfriendlierandeasiertounderstandwhenyouseethenamesoftheparametersatthesameplacewhereyoucallthemethod.
Adrawbackofthispatternisthesameasitsstrength.It'strivialtokeepaddingmoreparameters,whichmeanstrivialtoabusethetechnique.Onceyouhaveanexcusetoaddtothisfree-for-allbagofproperties,youwillfindittemptingtokeepaddingsomethatarenotentirelyoptional,orsomethataredependentonotherproperties.
Asaruleofthumb,allthesepropertiesshouldbeindependentandoptional.Ifyouhavetocheckallpossiblecombinationsinsideyourfunction("oh,Aisset,butAisonlyusedifBisalsoset"),thisisarecipeforalargefunctionbody,whichquicklybecomesconfusinganddifficult,ifnotimpossible,totest,becauseofallthecombinations.
![Page 441: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/441.jpg)
Privatepropertiesandmethods
JavaScriptdoesn'thavethenotionofaccessmodifiers,whichsettheprivilegesofthepropertiesinanobject.Otherlanguagesoftenhaveaccessmodifiers,asfollows:
Public:AllusersofanobjectcanaccessthesepropertiesormethodsPrivate:OnlytheobjectitselfcanaccessthesepropertiesProtected:Onlyobjectsinheritingtheobjectinquestioncanaccesstheseproperties
JavaScriptdoesn'thaveaspecialsyntaxtodenoteprivatepropertiesormethods,butasdiscussedinChapter3,Functions, youcanuselocalvariablesandmethodsinsideafunctionandachievethesamelevelofprotection.
ContinuingwiththeexampleoftheFancyButtonconstructor,youcanhavelocalvariablestylesthatcontainsallthedefaults,andalocalsetStyle()function.Theseareinvisibletothecodeoutsideoftheconstructor.Here'showFancyButtoncanmakeuseofthelocalprivateproperties:
varMYAPP={};MYAPP.dom={};MYAPP.dom.FancyButton=function(text,conf){varstyles={font:'Verdana',border:'1pxsolidblack',color:'black',background:'grey'};functionsetStyles(b){vari;for(iinstyles){if(styles.hasOwnProperty(i)){b.style[i]=conf[i]||styles[i];}}
}conf=conf||{};varb=document.createElement('input');b.type=conf.type||'submit';b.value=text;setStyles(b);returnb;};
Inthisimplementation,stylesisaprivatepropertyandsetStyle()isaprivatemethod.Theconstructorusestheminternally(andtheycanaccessanythinginsidetheconstructor),buttheyarenotavailabletocodeoutsideofthefunction.
![Page 442: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/442.jpg)
Privilegedmethods
Privilegedmethods(this termwascoinedbyDouglasCrockford)arenormalpublicmethodsthatcanaccessprivatemethodsorproperties.Theycanactlikeabridgeinmakingsomeoftheprivatefunctionalityaccessible,butinacontrolledmanner,wrappedinaprivilegedmethod.
![Page 443: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/443.jpg)
Privatefunctionsaspublicmethods
Let'ssayyou'vedefinedafunctionthatyouabsolutelyneedtokeepintact, soyoumakeitprivate.However,youalsowanttoprovideaccesstothesamefunction,sothatoutsidecodecanalsobenefitfromit.Inthiscase,youcanassigntheprivatefunctiontoapubliclyavailableproperty.
Let'sdefine_setStyle()and_getStyle()asprivatefunctions,butthenassignthemtothepublicsetStyle()andgetStyle(),considerthefollowingexample:
varMYAPP={};MYAPP.dom=(function(){var_setStyle=function(el,prop,value){
console.log('setStyle');};var_getStyle=function(el,prop){console.log('getStyle');};return{setStyle:_setStyle,getStyle:_getStyle,yetAnother:_setStyle};}());
Now,whenyoucallMYAPP.dom.setStyle(),itinvokestheprivate_setStyle()function.YoucanalsooverwritesetStyle()fromtheoutsideasfollows:
MYAPP.dom.setStyle=function(){alert('b');};
Now,theresultisasfollows:
MYAPP.dom.setStylepointstothenewfunctionMYAPP.dom.yetAnotherstillpointsto_setStyle()_setStyle()isalwaysavailablewhenanyotherinternalcodereliesonittobeworkingasintended,regardlessoftheoutsidecode
Whenyouexposesomethingprivate,keepinmindthatobjects(functionsandarraysareobjectstoo)arepassedbyreferenceand,therefore,canbemodifiedfromtheoutside.
![Page 444: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/444.jpg)
Immediatefunctions
Anotherpatternthathelpsyoukeeptheglobalnamespacecleanistowrapyourcodeinananonymousfunctionandexecutethatfunctionimmediately.Thisway,anyvariablesinsidethefunctionarelocal,aslongasyouusethevarstatement,andaredestroyedwhenthefunctionreturns,iftheyaren'tpartofaclosure.ThispatternwasdiscussedinmoredetailinChapter3,Functions.Takealookatthefollowingcode:
(function(){//codegoeshere...}());
Thispatternisespeciallysuitableforon-offinitializationtask,performedwhenthescriptloads.
Theimmediateself-executingfunctionpatterncanbeextendedtocreateandreturnobjects.Ifthecreationoftheseobjectsismorecomplicatedandinvolvessomeinitializationwork,thenyoucandothisinthefirstpartoftheself-executablefunctionandreturnasingleobjectthatcanaccessandbenefitfromanyprivatepropertiesatthetopportion,asfollows:
varMYAPP={};MYAPP.dom=(function(){//initializationcode...function_private(){//...
}return{getStyle:function(el,prop){console.log('getStyle');_private();},setStyle:function(el,prop,value){console.log('setStyle');}};}());
![Page 445: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/445.jpg)
Modules
Combiningseveralofthepreviouspatternsgives youanewpattern,commonlyreferredtoasamodulepattern.Theconceptofmodulesinprogrammingisconvenientasitallowsyoutocodeseparatepiecesorlibrariesandcombinethemas needed,justlikepiecesofapuzzle.
Themodulepatternincludesthefollowing:
NamespacestoreducenamingconflictsamongmodulesAnimmediatefunctiontoprovideaprivatescopeandinitializationPrivatepropertiesandmethods
Note
ES5doesn'thaveabuilt-inconceptofmodules.Thereisthemodulespecificationfromhttp://www.commonjs.org,whichdefinesarequire()functionandanexportsobject.ES6,however,supportsmodules.Chapter8,ClassesandModuleshascoveredmodulesindetail.
Returninganobject thathasthepublicAPIofthemoduleasfollows:
namespace('MYAPP.module.amazing');MYAPP.module.amazing=(function(){//shortnamesfordependenciesvaranother=MYAPP.module.another;//local/privatevariablesvari,j;//privatefunctionsfunctionhidden(){}//publicAPIreturn{hi:function(){return"hello";}
};}());
And,youcanusethemoduleinthefollowingway:
MYAPP.module.amazing.hi();//"hello"
![Page 446: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/446.jpg)
Chaining
Chainingisapatternthatallowsyoutoinvokemultiplemethodsononelineasifthemethodsarethelinksinachain.Thisisconvenientwhencallingseveralrelatedmethods.Youinvokethenextmethodontheresultofthepreviouswithouttheuseofanintermediatevariable.
Sayyou'vecreatedaconstructorthathelpsyouworkwithDOMelements.Thecodetocreateanew<span>tagthatisaddedtothe<body>tagcanlooksomethinglikethefollowing:
varobj=newMYAPP.dom.Element('span');obj.setText('hello');obj.setStyle('color','red');obj.setStyle('font','Verdana');document.body.appendChild(obj);
Asyouknow,constructorsreturntheobjectreferredtoasthiskeywordthattheycreate.Youcanmakeyourmethods,suchassetText()andsetStyle(),alsoreturnthiskeyword,whichallowsyoutocallthenextmethodontheinstancereturnedbythepreviousone.Thisway,youcanchainmethodcalls,asfollows:
varobj=newMYAPP.dom.Element('span');obj.setText('hello').setStyle('color','red').setStyle('font','Verdana');document.body.appendChild(obj);
Youdon'tevenneedtheobjvariableifyoudon'tplanonusingitafterthe newelementhasbeenaddedtothetree,sothecodelookslikethefollowing:
document.body.appendChild(newMYAPP.dom.Element('span').setText('hello').setStyle('color','red').setStyle('font','Verdana'));
Adrawbackofthispatternisthatitmakesitalittlehardertodebugwhenanerroroccurssomewhereinalongchain,andyoudon'tknowwhichlinkistoblamebecausetheyareallonthesameline.
![Page 447: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/447.jpg)
JSON
Let'swrapupthecoding patternssectionofthischapterwithafewwordsaboutJSON.JSONisnottechnicallyacodingpattern,butyoucansaythatusingitisagoodpattern.
JSONisapopularlightweightformattoexchangedata.It'softenpreferredoverXMLwhenusingXMLHttpRequest()toretrievedatafromtheserver.There'snothingspecificallyinterestingaboutJSONotherthanthefactthatit'sextremelyconvenient.TheJSONformatconsistsofdatadefinedusingobjectandarrayliterals.HereisanexampleofaJSONstringthatyourservercanrespondwithafteranXHRrequest:
{'name':'Stoyan','family':'Stefanov','books':['OOJS','JSPatterns','JS4PHP']}
AnXMLequivalentofthiswillbesomethinglikethefollowingpieceofcode:
<?xmlversion="1.1"encoding="iso-8859-1"?><response><name>Stoyan</name><family>Stefanov</family><books><book>OOJS</book><book>JSPatterns</book><book>JS4PHP</book></books></response>
First,youcanseehowJSONislighterintermsofthenumberofbytes.However,themainbenefitisnotthesmallerbytesize,butthefactthatit'strivialtoworkwithJSONinJavaScript.Let'ssay,you'vemadeanXHRrequestandhavereceivedaJSONstringintheresponseTextpropertyoftheXHRobject.YoucanconvertthisstringofdataintoaworkingJavaScriptobjectbysimplyusingeval().Considerthefollowingexample:
//warning:counter-examplevarresponse=eval('('+xhr.responseText+')');
Now,youcanaccessthe datainobjasobjectpropertiesasfollows:
console.log(response.name);//"Stoyan"console.log(response.books[2]);//"JS4PHP"
Theproblemisthateval()isinsecure,soit'sbestifyouusetheJSONobjecttoparsetheJSONdata(afallbackforolderbrowsersisavailableathttp://json.org/).CreatinganobjectfromaJSONstringisstilltrivialasfollows:
![Page 448: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/448.jpg)
varresponse=JSON.parse(xhr.responseText);
Todotheopposite,thatis,toconvertanobjecttoaJSONstring,youcanusethestringify()method,asfollows:
varstr=JSON.stringify({hello:"you"});
Due to its simplicity, JSON has quickly become popular as a language-independent format toexchangedata,andyoucaneasilyproduceJSON ontheserversideusingyourpreferredlanguage.InPHP,forexample,therearethejson_encode()andjson_decode()functionsthatletyouserializeaPHParrayorobjectintoaJSONstring,andviceversa.
![Page 449: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/449.jpg)
Higherorderfunctions
Functionalprogrammingwasconfinedtoalimitedsetoflanguagessofar.Withmorelanguagesaddingfeaturestosupportfunctionalprogramming,interestintheareaisgainingmomentum.JavaScriptisevolvingtosupportcommonfeaturesoffunctionalprogramming.Youwillgraduallyseealotofcodewritteninthisstyle.Itisimportanttounderstandthefunctionalprogrammingstyle,evenifyoudon'tfeelinclinedjustyettouseitinyourcode.
Higherorderfunctionsareoneoftheimportantmainstaysoffunctionalprograming.Higherorderfunctionisafunctionthatdoesatleastoneofthefollowing:
TakesoneormorefunctionsasargumentsReturnsafunctionasaresult
AsfunctionsarefirstclassobjectsinJavaScript, passingandreturningfunctionstoandfromafunctionisaprettyroutineaffair.Callbacksarehigherorderfunctions.Let'stakealookathowwecantakethesetwoprinciplestogetherandwriteahigherorderfunction.
Let'swriteafilterfunction;thisfunctionfiltersoutvaluesfromanarraybasedonacriteriadeterminedbyafunction.Thisfunctiontakestwoarguments-afunction,whichreturnsaBooleanvalue,trueforkeepingthiselement.
Forexample,withthisfunction,wearefilteringalloddvaluesfromanarray.Considerthefollowinglinesofcode:
console.log([1,2,3,4,5].filter(function(ele){returnele%2==0;}));//[2,4]
Wearepassingananonymousfunctiontothefilterfunctionasthefirstargument.ThisfunctionreturnsaBooleanbasedonaconditionthatchecksiftheelementisoddoreven.
ThisisanexampleofoneoftheseveralhigherorderfunctionsaddedtoECMAScript5.ThepointwearetryingtomakehereisthatyouwillincreasinglyseesimilarpatternsofusageinJavaScript.Youmustfirstunderstandhowhigher orderfunctionsworkandlater,onceyouarecomfortable with the concept, try to incorporate them in your code as well.
WithES6functionsyntaxchanges,itisevenmoreeleganttowritehigherorderfunctions.Let'stakeasmallexampleinES5andseehowthattranslatesintoitsES6equivalent:
functionadd(x){returnfunction(y){returny+x;};}varadd3=add(3);
![Page 450: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/450.jpg)
console.log(add3(3));//=>6console.log(add(9)(10));//=>19
Theaddfunctiontakesx andreturnsafunctionthattakesyasanargumentandthenreturnsvalueofexpressiony+x.
Whenwelookedatarrowfunctions,wediscussedthatarrowfunctionsreturnresultsofasingleexpressionimplicitly.So,theprecedingfunctioncanbeturnedintoanarrowfunctionbymakingthebodyofthearrowfunctionanotherarrowfunction.Takealookatthefollowingexample:
constadd=x=>y=>y+x;
Here,wehaveanouterfunction,x=>[innerfunctionwithxasargument],andwehaveaninnerfunction,y=>y+x.
Thisintroductionwillhelpyougetfamiliarwiththeincreasingusageofhigherorderfunctions,andtheirincreasedimportanceinJavaScript.
![Page 451: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/451.jpg)
Design patternsThe second part of this chapter presents a JavaScript approach to a subset of the design patternsintroducedbyDesignPatterns:ElementsofReusableObject-OrientedSoftware,aninfluentialbookmostcommonlyreferredtoastheBookofFour,theGangofFour,orGoF(afteritsfourauthors).ThepatternsdiscussedintheGoFbook aredividedintothethreefollowinggroups:
Creationalpatternsthatdealwithhowobjectsarecreated(instantiated)StructuralpatternsthatdescribehowdifferentobjectscanbecomposedinordertoprovidenewfunctionalityBehavioralpatternsthatdescribewaysforobjectstocommunicatewitheachother
Thereare23patternsintheBookofFour,andmorepatternshavebeenidentifiedsincethebook'spublication.It'swaybeyondthescopeofthisbooktodiscussallofthem,sotheremainderofthechapterdemonstratesonlyfour,alongwithexamplesoftheirimplementationinJavaScript.Rememberthatthepatternsaremoreaboutinterfacesandrelationshipsratherthanimplementation.Onceyouhaveanunderstandingofadesignpattern,it'softennotdifficulttoimplementit,especiallyinadynamiclanguagesuchasJavaScript.
Thepatternsdiscussedthroughtherestofthechapterareasfollows:
SingletonFactoryDecoratorObserver
![Page 452: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/452.jpg)
Singletonpattern
Singletonisacreationaldesignpattern,meaningthatitsfocusisoncreatingobjects.Ithelpsyouwhenyouwanttomakesurethereisonlyoneobjectofagivenkindorclass.Inaclassicallanguage,thiswouldmeanthataninstanceofaclassisonlycreatedonce,andanysubsequentattemptstocreatenewobjectsofthesameclasswouldreturntheoriginalinstance.
InJavaScript,becausetherearenoclasses,asingletonisthedefaultandmostnaturalpattern.Everyobjectisasingletonobject.
The most basic implementation of the singleton in JavaScript is the object literal. Take a look atthefollowinglineofcode:
varsingle={};
Thatwaseasy,right?
![Page 453: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/453.jpg)
Singleton2pattern
Ifyouwanttouseaclass-likesyntaxandstillimplementthesingletonpattern,thingsbecomeabitmoreinteresting.Let'ssay,youhaveaconstructorcalledLogger(),andyouwanttobeabletodosomethinglikethefollowing:
varmy_log=newLogger();my_log.log('someevent');
//...1000linesofcodelaterinadifferentscope...
varother_log=newLogger();other_log.log('somenewevent');console.log(other_log===my_log);//true
Theideaisthat,althoughyouusenew,onlyoneinstanceneedstobecreated,andthisinstanceisthenreturnedinconsecutivecalls.
Globalvariable
Oneapproachistouseaglobalvariabletostorethesingleinstance.Yourconstructorcouldlooklikethefollowingcodesnippet:
functionLogger(){if(typeofglobal_log==="undefined"){global_log=this;}returnglobal_log;}
Usingthisconstructorgivestheexpectedresult,whichisasfollows:
vara=newLogger();varb=newLogger();console.log(a===b);//true
Thedrawbackis,obviously,theuseofaglobalvariable.Itcanbeoverwrittenatanytime,evenaccidentally,andyoucanlosetheinstance.Theopposite,yourglobalvariableoverwritingsomeoneelse'sisalsopossible.
Propertyoftheconstructor
Asyouknow,functionsareobjectsandtheyhaveproperties.Youcanassignthesingleinstancetoapropertyoftheconstructorfunction,asfollows:
functionLogger(){if(!Logger.single_instance){Logger.single_instance=this;}
![Page 454: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/454.jpg)
returnLogger.single_instance;}
Ifyouwritevara=newLogger(),apointstothenewlycreatedLogger.single_instanceproperty.Asubsequentvarb=newLogger()callresultsinbpointingtothesameLogger.single_instanceproperty,whichisexactlywhatyouwant.
Thisapproachcertainlysolvestheglobalnamespaceissuebecausenoglobalvariablesarecreated.TheonlydrawbackisthatthepropertyoftheLoggerconstructor ispubliclyvisible,soitcanbeoverwrittenatanytime.Insuchcases,thesingleinstancecanbelostormodified.Ofcourse,youcanonlyprovidesomuchprotectionagainstfellowprogrammersshootingthemselvesinthefoot.Afterall,ifsomeonecanmesswiththesingle-instanceproperty,theycanmessuptheLoggerconstructordirectlyaswell.
Inaprivateproperty
Thesolutiontotheproblemofoverwritingthepubliclyvisiblepropertyisnottouseapublicproperty,butaprivateone.Youalreadyknowhowtoprotectvariableswithaclosure,soasanexercise,youcanimplementthisapproachtothesingletonpattern.
![Page 455: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/455.jpg)
Factorypattern
Thefactoryisanothercreationaldesignpattern,asitdealswithcreatingobjects.Thefactorycanhelpyouwhenyouhavesimilartypesofobjectsandyoudon'tknowinadvancewhichoneyouwanttouse.Basedonuserinputorothercriteria,yourcodedeterminesthetypeofobjectitneedsonthefly.
Let'ssayyouhavethreedifferentconstructorsthatimplementsimilarfunctionality.AlltheobjectstheycreatetakeaURLbutdodifferentthingswithit.OnecreatesatextDOMnode;thesecondcreatesalink;andthethird,animage,asfollows:
varMYAPP={};MYAPP.dom={};MYAPP.dom.Text=function(url){this.url=url;this.insert=function(where){vartxt=document.createTextNode(this.url);where.appendChild(txt);};};MYAPP.dom.Link=function(url){this.url=url;this.insert=function(where){varlink=document.createElement('a');link.href=this.url;link.appendChild(document.createTextNode(this.url));where.appendChild(link);};};MYAPP.dom.Image=function(url){
this.url = url;this.insert=function(where){varim=document.createElement('img');im.src=this.url;where.appendChild(im);};};
Usingthethreedifferentconstructorsisexactlythesame-passtheurlvariableandcalltheinsert()method,asfollows:
varurl='http://www.phpied.com/images/covers/oojs.jpg';
varo=newMYAPP.dom.Image(url);o.insert(document.body);
varo=newMYAPP.dom.Text(url);o.insert(document.body);
varo=newMYAPP.dom.Link(url);
![Page 456: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/456.jpg)
o.insert(document.body);
Imagineyourprogramdoesn'tknowinadvancewhichtypeofobjectisrequired.Theuserdecides,duringruntime,byclickingonabuttonforexample.Iftypecontainstherequiredtypeofobject,you'llneedtouseaniforaswitchstatement,andwritesomethinglikethefollowingpieceofcode:
varo;if(type==='Image'){o=newMYAPP.dom.Image(url);}if(type==='Link'){o=newMYAPP.dom.Link(url);}if(type==='Text'){o=newMYAPP.dom.Text(url);
}o.url='http://...';o.insert();
Thisworksfine;however,ifyouhavealotofconstructors,thecodebecomestoolengthyandhardtomaintain.Also,ifyouarecreatingalibraryoraframeworkthatallowsextensionsorplugins,youdon'tevenknowtheexactnamesofalltheconstructorfunctionsinadvance.Insuchcases,it'sconvenienttohaveafactoryfunctionthattakescareofcreatinganobjectofthedynamicallydeterminedtype.
Let'saddafactorymethodtotheMYAPP.domutility:
MYAPP.dom.factory=function(type,url){returnnewMYAPP.dom[type](url);};
Now,youcanreplacethethreeiffunctionswiththesimplercode,asfollows:
varimage=MYAPP.dom.factory("Image",url);image.insert(document.body);
Theexamplefactory()methodinthepreviouscodewassimple;however,inareal-lifescenario,you'dwanttodosomevalidationagainstthetypevalue(forexample,checkifMYAPP.dom[type]exists)andoptionallydosomesetupworkcommontoallobjecttypes(forexample,setuptheURLallconstructorsuse).
![Page 457: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/457.jpg)
Decoratorpattern
Thedecoratordesignpatternisastructuralpattern;itdoesn'thavemuchtodowithhowobjectsarecreated,butratherhowtheirfunctionalityisextended.Insteadofusinginheritance,whereyouextendinalinearway(parent-child-grandchild),youcanhaveonebaseobjectandapoolofdifferentdecoratorobjectsthatprovideextrafunctionality.Yourprogramcanpickandchoosewhichdecoratorsitwants,andinwhichorder.Foradifferentprogramor codepath,youmayhaveadifferentsetofrequirementsandpickdifferentdecoratorsoutofthesamepool.Takealookatthefollowingcodesnippettoseehowtheusagepartofthedecoratorpatterncanbeimplemented:
varobj={doSomething:function(){console.log('sure,asap');
}//...};obj=obj.getDecorator('deco1');obj=obj.getDecorator('deco13');obj=obj.getDecorator('deco5');obj.doSomething();
YoucanseehowyoucanstartwithasimpleobjectthathasadoSomething()method.Then,youcanpickoneofthedecoratorobjectsyouhavelyingaroundandwhichcanbeidentifiedbyname.AlldecoratorsprovideadoSomething()methodthatfirstcallsthesame methodofthepreviousdecoratorandthenproceedswithitsowncode.Everytimeyouaddadecorator,youoverwritethebaseobjwithanimprovedversionofit.Intheend,whenyouarefinishedaddingdecorators,youcalldoSomething().Asaresult,allofthedoSomething()methodsofallthedecoratorsareexecutedinsequence.Let'sseeanexample.
Decoratingachristmastree
Let'sillustratethedecoratorpatternwithanexampleofdecoratingaChristmastree.Youcanstartwiththedecorate()methodasfollows:
vartree={};tree.decorate=function(){alert('Makesurethetreewon'tfall');};
Now,let'simplementagetDecorator()methodthataddsextradecorators.Thedecoratorswillbeimplementedasconstructorfunctions,andthey'llallinheritfromthebasetreeobjectasfollows:
tree.getDecorator=function(deco){tree[deco].prototype=this;returnnewtree[deco];
![Page 458: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/458.jpg)
};
Now,let'screatethefirstdecorator,RedBalls(),asapropertyoftree,inordertokeeptheglobalnamespacecleaner.Theredballobjectsalsoprovideadecorate()method,buttheymakesuretheycalltheirparent'sdecorate()first.Forexample,takealookatthefollowingcode:
tree.RedBalls=function(){this.decorate=function(){this.RedBalls.prototype.decorate();alert('Putonsomeredballs');};
};
Similarly,implementBlueBalls()andAngel()decoratorsasfollows:
tree.BlueBalls=function(){this.decorate=function(){this.BlueBalls.prototype.decorate();alert('Addblueballs');};
};tree.Angel=function(){this.decorate=function(){this.Angel.prototype.decorate();alert('Anangelonthetop');};};
Now,let'saddallofthedecoratorstothebaseobject,asshowninthefollowingcodesnippet:
tree=tree.getDecorator('BlueBalls');tree=tree.getDecorator('Angel');tree=tree.getDecorator('RedBalls');
Finally,runthedecorate()methodasfollows:
tree.decorate();
Thissinglecallresultsinthefollowingalerts,specificallyinthisorder:
1. Makesurethetreewon'tfall.2. Addtheblueballs.3. Addanangelatthetop.4. Addsomeredballs.
Asyousee,thisfunctionalityallowsyoutohaveasmanydecoratorsasyoulike,andtochooseandcombinetheminanywayyoulike.
![Page 459: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/459.jpg)
Observerpattern
Theobserverpattern,alsoknownasthesubscriber-publisherpattern,isabehavioralpattern,whichmeansthatitdealswithhowdifferentobjectsinteractandcommunicatewitheachother.Whenimplementingtheobserverpattern,youhavethefollowingobjects:
Oneormorepublisherobjectsthatannouncewhentheydosomethingimportant.Oneormoresubscriberstunedintooneormorepublishers.Theylistentowhatthepublishersannounceandthenactappropriately.
Theobserverpatternmaylookfamiliartoyou.Itsoundssimilartothebrowsereventsdiscussedinthepreviouschapter,andrightlyso,becausethebrowsereventsareoneexampleapplicationofthispattern.Thebrowseristhepublisher;itannouncesthefactthatanevent,suchasaclick,hashappened.Youreventlistenerfunctionsthataresubscribedtolistentothistypeofeventwillbenotifiedwhenithappens.Thebrowser-publishersendsaneventobjecttoallofthesubscribers.Inyourcustomimplementations,youcansendanytypeofdatayoufindappropriate.
Therearetwosubtypesoftheobserverpattern:pushandpull.Pushiswherethepublishersareresponsibletonotifyeachsubscriber,andpulliswherethesubscribersmonitorforchangesinapublisher'sstate.
Let'stakealookatanexampleimplementationofthepushmodel.Let'skeeptheobserver-relatedcodeinaseparateobjectandthenusethisobjectasamix-in,addingitsfunctionalitytoanyotherobjectthatdecidestobeapublisher.Inthisway,anyobjectcanbecomeapublisherandanyfunctioncanbecomeasubscriber.Theobserverobjectwillhavethefollowingpropertiesandmethods:
AnarrayofsubscribersthatarejustcallbackfunctionsTheaddSubscriber()andremoveSubscriber()methodsthataddto,andremovefrom,thesubscriberscollectionApublish()methodthattakesdataandcallsallsubscribers,passingthedatatothemAmake()methodthattakesanyobjectandturnsitintoapublisherbyaddingallofthemethodsmentionedpreviouslytoit
Here'stheobservermix-inobjectthatcontainsallthesubscription-relatedmethodsandcanbeusedtoturnanyobjectintoapublisher:
varobserver={addSubscriber:function(callback){if(typeofcallback==="function"){this.subscribers[this.subscribers.length]=callback;}},removeSubscriber:function(callback){for(vari=0;i<this.subscribers.length;i++){if(this.subscribers[i]===callback){
![Page 460: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/460.jpg)
deletethis.subscribers[i];}}},publish:function(what){for(vari=0;i<this.subscribers.length;i++){if(typeofthis.subscribers[i]==='function'){this.subscribers[i](what);}}},make:function(o){//turnsanobjectintoapublisherfor(variinthis){if(this.hasOwnProperty(i)){o[i]=this[i];o.subscribers=[];}}}};
Now,let'screatesomepublishers.Apublishercanbeanyobjectanditsonlydutyistocallthepublish()methodwheneversomethingimportantoccurs.Here'sabloggerobjectthatcallspublish()everytimeanewblogpostingisready:
varblogger={writeBlogPost:function(){varcontent='Todayis'+newDate();this.publish(content);}};
AnotherobjectcanbetheLATimesnewspaperthatcallspublish()whenanewnewspaperissueisout.Considerthefollowinglinesofcode:
varla_times={newIssue:function(){varpaper='MartianshavelandedonEarth!';this.publish(paper);}};
Youcanturntheseobjectsintopublishersasfollows:
observer.make(blogger);observer.make(la_times);
Now,let'shavethefollowingtwosimpleobjects,jackandjill:
varjack={read:function(what){console.log("Ijustreadthat"+what)
![Page 461: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/461.jpg)
}};varjill={gossip:function(what){console.log("Youdidn'thearitfromme,but"+what)}};
Thejackandjillobjectscansubscribetothebloggerobjectbyprovidingthecallbackmethodstheywanttocallwhensomethingispublished,asfollows:
blogger.addSubscriber(jack.read);blogger.addSubscriber(jill.gossip);
Whathappensnow,whenthebloggerobjectwritesanewpost?Theresultisthatjackandjillwillgetnotified:
>blogger.writeBlogPost();IjustreadthatTodayisFriJan04201319:02:12GMT-0800(PST)Youdidn'thearitfromme,butTodayisFriJan04201319:02:12GMT-
0800(PST)
Atanytime,jillmaydecidetocancelhersubscription.Then,whenwritinganotherblogpost,theunsubscribedobjectisnolongernotified.Considerthefollowingcodesnippet:
>blogger.removeSubscriber(jill.gossip);>blogger.writeBlogPost();IjustreadthatTodayisFriJan04201319:03:29GMT-0800(PST)
ThejillobjectmaydecidetosubscribetoLATimes,asanobjectcanbeasubscribertomanypublishers,asfollows:
>la_times.addSubscriber(jill.gossip);
Then,whenLATimespublishesanewissue,jillgetsnotifiedandjill.gossip()isexecuted,asfollows:
>la_times.newIssue();Youdidn'thearitfromme,butMartianshavelandedonEarth!
![Page 462: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/462.jpg)
SummaryIn this chapter, you learned about common JavaScript coding patterns and learned how to makeyourprogramscleaner,faster,andbetteratworkingwithotherprogramsandlibraries.Then,yousawadiscussionandsampleimplementationsofahandfulofthedesignpatternsfromtheBookofFour.YoucanseehowJavaScriptisafullyfeatureddynamicprogramminglanguage,andthatimplementingclassicalpatternsinadynamiclooselytypedlanguageisprettyeasy.Thepatternsare,ingeneral,alargetopic,andyoucanjointheauthorofthisbookinafurtherdiscussionoftheJavaScriptpatternsatJSPatterns.com,ortakealookattheJavaScriptPatternsbook.Thenextchapterfocusesontestinganddebuggingmethodologies.
![Page 463: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/463.jpg)
Chapter 12. Testing and DebuggingAs you write JavaScript applications, you will soon realize that having a sound testing strategy isindispensable.Infact,notwritingenoughtestsisalmostalwaysabadidea.Itisessentialtocoverallnontrivialfunctionalityofyourcodetomakesureofthefollowingpoints:
ExistingcodebehavesasperthespecificationsAnynewcodedoesnotbreakthebehaviordefinedbythespecifications
Both these points are very important. Many engineers consider only the first point as the solereasontocoveryourcodewithenoughtests.Themostobviousadvantage oftestcoverageistoreallymakesurethatthecodebeingpushedtoproductionsystemismostlyerrorfree.Writingtestcasestosmartlycovermaximumfunctionalareas ofthecode,generallygivesgoodindicationaroundtheoverallqualityofthecode.Thereshouldbenoargumentsorcompromisesaroundthispoint.Although,itisunfortunatethatmanyproductionsystemsarestillbereftofadequatecodecoverage.Itisveryimportanttobuildanengineeringculturewheredevelopersthinkaboutwritingtestsasmuchastheythinkaboutwritingcode.
Thesecondpointisevenmoreimportant.Legacysystemsareusuallyverydifficulttomanage.Whenyouareworkingoncode,eitherwrittenbysomeoneelseorwritten byalargedistributedteam,itisfairlyeasytointroducebugsandbreakthings.Eventhebestengineersmakemistakes.Whenyouareworkingonalargecodebaseyouareunfamiliarwith,ifthereisnosoundtestcoveragetohelpyou,youwillintroducebugs.Asyouwon'thavetheconfidenceinthechangesyouaremaking,becausetherearenotestcasestoconfirmyourchanges,yourcodereleaseswillbeshaky,slow,andobviouslyfullofhiddenbugs.
You will refrain from refactoring or optimizing your code, because you won't be really sure whatchangestothecodebasewouldpotentiallybreaksomething(again,becausetherearenotestcasetoconfirmyourchanges);allthisisaviciouscircle.It'slikeacivilengineersaying-althoughIhaveconstructedthisbridge,Ihavenoconfidenceonthequalityoftheconstruction.Itmaycollapseimmediatelyornever.Althoughthismaysoundlikeanexaggeration,Ihaveseenalotofhighimpactproductioncodebeingpushedwithnotestcoverage.Thisisriskyandshouldbeavoided.Whenyouarewritingenoughtestcasestocovermajorityofyourfunctionalcode,whenyoumakechangetothosepieces,youwillimmediatelyrealizeifthereisaproblemwiththisnewchange.Ifyourchangesmakethetestcasefail,youwillrealizetheproblem.Ifyourrefactorbreaksthetestscenario,youwillrealizetheproblem;allofthishappensmuchbeforethecodeispushedtoproduction.
Inrecentyears,ideasliketest-drivendevelopmentandself-testingcodearegainingprominence,especiallyinagilemethodology.Thesearefundamentallysoundideasandwillhelpyouwriterobustcode-thecodeyouareconfidentof.Wewilldiscussalltheseideasinthischapter.WewillunderstandhowtowritegoodtestcasesinmodernJavaScript.Wewillalsolookatseveraltoolsandmethodstodebugyourcode.JavaScriptwastraditionallyabitdifficulttotestand
![Page 464: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/464.jpg)
debug,primarilyduetolackoftools,butmoderntoolsmakebothoftheseeasyandnatural.
![Page 465: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/465.jpg)
Unit testingWhen we talk about test cases, we mostly mean unit tests. It is incorrect to assume that the unit wewanttotestisalwaysafunction.Theunit,orunitofwork,isalogicalunitthatconstitutessinglebehavior.Thisunitshouldbeabletobeinvokedviaapublicinterfaceandshouldbetestableindependently.
Thus,aunittestcanperformthefollowingfunctions:
It tests a single logical functionItcanrunwithoutaspecificorderofexecutionIttakescareofitsowndependenciesandmockdataItalwaysreturnsthesameresultforthesameinputItshouldbeself-explanatory,maintainable,andreadable
MartinFowleradvocatestheTestPyramid(http://martinfowler.com/bliki/TestPyramid.html)strategytomakesurewehaveahighnumberofunitteststoensuremaximumcodecoverage.Therearetwoimportanttestingstrategiesthatwewilldiscussinthischapter.
![Page 466: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/466.jpg)
TestDrivenDevelopment
Testdrivendevelopment(TDD)hasgainedalotofprominenceinthelastfewyears.Theconceptwasfirstproposedaspartoftheextremeprogrammingmethodology.Theideaistohaveshortrepetitivedevelopmentcycleswherethefocusisonwritingthetestcasesfirst.Thecyclelookslikethefollowing:
1. Addatestcaseasperthespecificationsforthespecificunitofcode.2. Runexistingsuiteoftestcasestoseeifthenewtestcaseyouwrotefails;itshould,becausethereisnocodefor thatunityet.Thisstepensuresthatthecurrenttestharnessworkswell.
3. Writethecodethatmainlyservestoconfirmtothetestcase.Thiscodeisnotoptimized,refactored,orevenentirelycorrect.However,thisisfineatthismoment.
4. Reruntestsandseeifallthetestcasespass.Afterthisstep,youareconfidentthatthenewcodeisnotbreakinganything.
5. Refactorcodetomakesureyouareoptimizingtheunitandhandlingallcornercases
Thesestepsarerepeatedforanynewcodeyouadd.Thisisanelegantstrategythatworksreallywellforagilemethodology.TDDwillbesuccessfulonlyifthetestableunitsofcodearesmallandconfirmsonlytothetestcase.
![Page 467: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/467.jpg)
BehaviorDrivenDevelopment
AverycommonproblemwhiletryingtofollowTDDisvocabularyandthedefinitionofcorrectness.BDDtriestointroduceaubiquitouslanguagewhilewritingthetestcaseswhenyouarefollowingTDD.Thislanguagemakessurethatboththebusinessandtheengineeringaretalkingaboutthesamething.
WewilluseJasmineastheprimaryBDDframeworkandexplorevarioustestingstrategies.
Note
YoucaninstallJasminebydownloadingthestandalonepackagefromhttps://github.com/jasmine/jasmine/releases/download/v2.3.4/jasmine-standalone-2.3.4.zip.
Whenyouunzipthispackage,youwillseethefollowingdirectorystructure:
![Page 468: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/468.jpg)
ThelibdirectorycontainstheJavaScriptfilesthatyouneedinyourprojecttostartwritingJasminetestcases.IfyouopenSpecRunner.html,youwillfindthefollowingJavaScriptfilesincludedinit:
<scriptsrc="lib/jasmine-2.3.4/jasmine.js"></script><scriptsrc="lib/jasmine-2.3.4/jasmine-html.js"></script><scriptsrc="lib/jasmine-2.3.4/boot.js"></script>
<!--includesourcefileshere...--><scriptsrc="src/Player.js"></script><scriptsrc="src/Song.js"></script>
![Page 469: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/469.jpg)
<!--includespecfileshere...--><scriptsrc="spec/SpecHelper.js"></script><scriptsrc="spec/PlayerSpec.js"></script>
ThefirstthreeareJasmine'sownframeworkfiles.Thenextsectionincludesthesourcefileswewanttotestandtheactualtestspecifications.
Let'sexperimentwithJasmineviaaveryordinaryexample.Createabigfatjavascriptcode.jsfileandplaceitinthesrc/directory.Thefunctionwewilltestisasfollows:
functioncapitalizeName(name){returnname.toUpperCase();}
Thisisasimplefunctionthatdoesonesinglething.Itreceivesastringandreturnsacapitalizedstring.Wewilltestvariousscenariosaroundthisfunction.Thisistheunit ofcode,whichwediscussedearlier.
Next,createthetestspecifications.CreateoneJavaScriptfile,test.spec.js,andplaceitinthespec/directory.YouwillneedtoaddthefollowingtwolinesintoyourSpecRunner.html:Thefileshouldcontainthefollowing:
<scriptsrc="src/bigfatjavascriptcode.js"></script><scriptsrc="spec/test.spec.js"></script>
Theorderofthisinclusiondoesnotmatter.WhenwerunSpecRunner.html,youwillseesomethinglikethefollowingimage:
![Page 470: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/470.jpg)
ThisistheJasminereportthatshowsdetailsaboutthenumberofteststhatwereexecutedandthecountoffailuresandsuccesses.Now,let'smakethetestcasefail.Wewanttotestacasewhereanundefined variable is passed to the function. Let's add one more test case, as follows:
it("canhandleundefined",function(){varstr=undefined;expect(capitalizeName(str)).toEqual(undefined);});
Now,whenyourunSpecRunner,youwillseethefollowingresult:
Asyoucansee,thefailureisdisplayedforthistestcaseinadetailederrorstack.Now,wewillgoaboutfixingthis.InyouroriginalJScode,handleundefinedasfollows:
functioncapitalizeName(name){if(name){returnname.toUpperCase();}}
Withthischange,yourtestcasewillpass,andyouwillseethefollowingresultintheJasminereport:
![Page 471: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/471.jpg)
Thisisverysimilartowhatatest-drivendevelopmentwouldlooklike.Youwritetestcasesandthenfillthenecessarycodetoconfirmtothespecificationsandrerunthetestsuite.Let'sunderstandthestructureoftheJasminetests.
Ourtestspecificationlookslikethefollowingpieceofcode:
describe("TestStringUtilities",function(){it("convertstocapital",function(){varstr="albert";expect(capitalizeName(str)).toEqual("ALBERT");});it("canhandleundefined",function(){varstr=undefined;expect(capitalizeName(str)).toEqual(undefined);});});
Thedescribe("TestStringUtilities"iswhatatestsuiteis.Thenameofthetestsuiteshoulddescribetheunit-of-codewearetesting;thiscanbeafunctionoragroupofrelatedfunctionality.Inside the specs, you will call the global Jasmine function,it, to which you will pass the title ofthe spec and the function that validates the condition of the testcase This function is the actual testcase.Youcancatchoneormoreassertionsorthegeneralexpectationsusingtheexpectfunction.Whenallexpectationsaretrue,yourspecispassed.YoucanwriteanyvalidJavaScriptcodeinsidedescribeanditfunctions.Thevaluesyouverifyaspartoftheexpectationsarematchedusingamatcher.Inourexample,toEqualisthematcherthatmatchestwovaluesforequality.Jasminecontainsarichsetofmatchestosuitmostofthecommonusecases.SomecommonmatcherssupportedbyJasmineareasfollows:
![Page 472: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/472.jpg)
toBe:Thismatcher checksiftwoobjectsbeingcomparedareequal. Thisissameasthe===comparison.Forexample,checkoutthefollowingcodesnippet:
vara={value:1};varb={value:1};expect(a).toEqual(b);//success,sameas==comparisonexpect(b).toBe(b);//failure,sameas===comparisonexpect(a).toBe(a);//success,sameas===comparison
not:Youcannegateamatcherwithanotprefix.Forexample,expect(1).not.toEqual(2);willnegatethematchmadebytoEqual().toContain:Thischecksifanelementispartofanarray.ItisnotanexactobjectmatchastoBe.Forexample,takealookatthefollowinglinesofcode:
expect([1,2,3]).toContain(3);expect("astronomy is a science").toContain("science");
toBeDefinedandtoBeUndefined:Thesetwomatchesarehandytocheckwhetheravariableisundefinedornot.toBeNull:Thischecksifavariable'svalue isnull.toBeGreaterThanandtoBeLessThan:Thesematcherperformsnumericcomparison(worksonstringstoo).Forexample,considerthefollowingpieceofcode:
expect(2).toBeGreaterThan(1);expect(1).toBeLessThan(2);expect("a").toBeLessThan("b");
AninterestingfeatureofJasmineisthespies.Whenyouarewritingalargesystem,itisnotpossibletomakesurethatallsystemsarealwaysavailableandcorrect.Atthesametime,youdon't want your unit tests to fail due to a dependency that may be broken or unavailable. Tosimulateasituationwherealldependenciesareavailableforaunitofcodewewanttotest,wewillmockthisdependencytoalwaysgivetheresponseweexpect.Mockingisanimportantaspectoftesting,andmosttestingframeworksprovidesupportformocking.JasmineallowsmockingusingafeaturecalledaSpy.Jasminespiesessentiallystubsthefunctionswemaynothavereadyatthetimeof writingthetestcase,butaspartofthefunctionality,wewillneedtotrackthatweareexecutingthosedependenciesandnotignoringthem.Considerthefollowingexample:
describe("mockingconfigurator",function(){varcofigurator=null;varresponseJSON={};
beforeEach(function(){configurator={submitPOSTRequest:function(payload){//Thisisamockservicethatwilleventuallybereplaced//byarealserviceconsole.log(payload);
![Page 473: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/473.jpg)
return{"status":"200"};}};spyOn(configurator,'submitPOSTRequest').and.returnValue({"status":"200"});configurator.submitPOSTRequest({"port":"8000","client-encoding":"UTF-8"});});
it("thespywascalled",function(){expect(configurator.submitPOSTRequest).toHaveBeenCalled();});
it("theargumentsofthespy'scallaretracked",function(){expect(configurator.submitPOSTRequest).toHaveBeenCalledWith({"port":"8000","client-encoding":"UTF-8"});});});
Inthisexample,whilewearewritingthistestcase,weeitherdon'thavetherealimplementationofthedependency,configurator.submitPOSTRequest(),orsomeoneisfixingthisparticulardependency;inanycase,wedon'thaveitavailable.Forourtesttowork,wewillneedtomockit.Jasminespiesallowustoreplaceafunctionwithitsmockandallowsustotrackitsexecution.
Inthiscase,wewillneedtoensurethatwecalledthedependency.Whentheactualdependencyisready,wewillrevisitthistestcasetomakesureitfitsthespecifications;however,atthistime,allweneedtoensurethatthedependencyiscalled.JasminefunctiontohaveBeenCalled()letsustracktheexecutionofafunctionthatmaybeamock.WecanusetoHaveBeenCalledWith(),whichallowsustodetermineifthestubfunctionwascalledwithcorrectparameters.ThereareseveralotherinterestingscenariosyoucancreateusingJasminespies.Thescopeofthischapterwon'tpermitustocoverthemall,butIwouldencourageyoutodiscoverthoseareasonyourown.
![Page 474: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/474.jpg)
Mocha,ChaiandSinon
ThoughJasmineisthemostprominentJavaScripttestingframework,mochaandchaiaregainingprominenceintheNode.jsenvironment:
Mocha is the testing framework used to describe and run test casesChaiistheassertionlibrarysupportedbyMochaSinoncomesinhandywhilecreatingmocksandstubsforyourtests
Wewon'tdiscusstheseframeworksinthisbook;however,experienceonJasminewillbehandyifyouwanttoexperimentwiththeseframeworks.
![Page 475: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/475.jpg)
JavaScript debuggingIf you are not a completely new programmer, I am sure you must have spent some amount of timedebuggingyourorsomeoneelse'scode.Debuggingisalmostlikeanartform.Everylanguagehasdifferentmethodsandchallengesaroundthedebugging.JavaScriptistraditionallyadifficultlanguagetodebug.Ihavespentdaysandnightsinmisery,tryingtodebugbadlywrittenJavaScriptcodeusingalert()functions.Fortunately,modernbrowsers,suchasMozilla,Firefox,andGoogleChrome,haveexcellentDeveloperToolstohelpdebugJavaScriptinthebrowser.ThereareIDEslikeIntelliJIDEAandWebStormwithgreatdebuggingsupportforJavaScriptandNode.js.Inthischapter,wewillfocusprimarilyonGoogleChrome'sbuilt-indevelopertool.FirefoxalsosupportsFirebugextensionandhasexcellent built-indevelopertools,butastheybehave moreorlessthesameasGoogleChrome'sDeveloperTools,wewilldiscusscommondebuggingapproachesthatworkinbothofthesetools.
Beforewetalkaboutthe specificdebuggingtechniques,let'sunderstandthetypeoferrorswewouldbeinterestedinwhilewetrytodebugourcode.
![Page 476: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/476.jpg)
Syntaxerrors
WhenyourcodehassomethingthatdoesnotconfirmtotheJavaScriptlanguagegrammar,theinterpreterrejectsthatpieceofcode.TheseareeasytocatchifyourIDEishelpingyouwithsyntaxchecking.MostmodernIDEshelpwiththeseerrors.Earlier,wediscussedtheusefulnessoftools,suchasJSLintandJSHint,aroundcatchingsyntaxissueswithyourcode.Theyanalyzethecodeandflagerrorsinthesyntax.TheJSHintoutputcanbeveryilluminating.Forexample,thefollowingoutputshowsupsomanythingswe canchangeinthecode.Thefollowingcodesnippetisfromoneofmyexistingprojects:
tempgit:(dev_branch)Xjshinttest.jstest.js:line1,col1,Usethefunctionformof"usestrict".test.js:line4,col1,'destructuringexpression'isavailableinES6(useesnextoption)orMozillaJSextensions(usemoz).test.js:line44,col70,'arrowfunctionsyntax(=>)'isonlyavailableinES6(useesnextoption).test.js:line61,col33,'arrowfunctionsyntax(=>)'isonlyavailableinES6(useesnextoption).test.js:line200,col29,Expected')'tomatch'('fromline200andinsteadsaw':'.test.js:line200,col29,'functionclosureexpressions'isonlyavailableinMozillaJavaScriptextensions(usemozoption).test.js:line200,col37,Expected'}'tomatch'{'fromline36andinsteadsaw')'.test.js:line200,col39,Expected')'andinsteadsaw'{'.test.js:line200,col40,Missingsemicolon.
Usingstrict
Webrieflydiscussedthe strictmodeinearlierchapters.Whenyouenablestrictmode,JavaScriptstopsbeingacceptingofsyntacticalerrorsinyourcode.Ratherthansilentlyfailing,strictmodemakesthesefailurethrowerrorsinstead.Italsohelpsyouconvertmistakesintoactualerrors.Therearetwowaysofenforcingstrictmode.Ifyouwantthestrictmodefortheentirescript,youcanjustaddtheusestrictstatement(withthequotes)asthefirstlineofyourJavaScriptprogram.Ifyouwantaspecificfunctiontoconfirmtostrictmode,youcanaddthedirectiveasthefirst line of a function. For example, take a look at the following code snippet:
functionstrictFn(){//ThislinemakesEVERYTHINGunderthisscrictmode'usestrict';...functionnestedStrictFn(){//Everythinginthisfunctionisalsonested...}}
![Page 477: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/477.jpg)
Runtimeexceptions
Theseerrorsappearwhenyouexecutethecode,trytorefertoanundefinedvariable,ortrytoprocessanull.Whenaruntimeexceptionoccurs,anycodeafterthatparticularline,whichcausedtheexception,doesnotgetexecuted.Itisessentialtocorrectlyhandlesuchexceptionalscenariosinthecode.Whileexceptionhandlingcanhelppreventcrashes,theyalsoaidindebugging.Youcanwrapthecodethatmayencounteraruntimeexceptionintoatry{}block.Whenanycodeinsidethisblockgeneratesaruntimeexception,acorrespondinghandlercapturesit.Thehandlerisdefinedbyacatch(exception){}block.Let'sclarifythisusingthefollowingexample:
try{vara=doesnotexist;//throwsaruntimeexception}catch(e){console.log(e.message);//handletheexception//prints-"doesnotexistisnotdefined"}
Inthisexample,thevara=doesnotexistlinetriestoassignanundefinedvariable,doesnotexist,toanothervariablea.Thiscausesaruntimeexception.Whenwewrapthisproblematiccodeintotry{}catch(){}blockorwhentheexceptionoccurs(oristhrown),theexecutionstopsinthetry{}blockandgoesdirectlytothecatch(){}handler.Thecatchhandlerisresponsibleforhandlingtheexceptionalscenario.Inthiscase,wearedisplayingtheerrormessageontheconsolefordebuggingpurposes.Youcanexplicitlythrowanexceptiontotriggeranunhandledscenariointhecode.Considerthefollowingexample:
functionengageGear(gear){if(gear==="R"){console.log("Reversing");}if(gear==="D"){console.log("Driving");}if(gear==="N"){console.log("Neutral/Parking");}thrownewError("InvalidGearState");}try{engageGear("R");//ReversingengageGear("P");//InvalidGearState}catch(e){console.log(e.message);}
Inthisexample,wearehandlingvalidstatesofagearshift:R,N,andD;however,whenwereceiveaninvalidstate,weareexplicitlythrowinganexceptionclearlystatingthereason.Whenwecallthefunctionwhichwethinkmaythrowanexception,wewillwrapthecodeinthetry{}blockandattachacatch(){}handlerwithit.Whentheexceptioniscaughtbythecatch()block,wewillhandletheexceptionalconditionappropriately.
![Page 478: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/478.jpg)
Console.logandasserts
Displayingthestateofexecutiononconsolecanbeveryusefulwhiledebugging.Although,moderndevelopertoolsallowyoutoputbreakpointsandhaltexecutiontoinspectaparticularvalueduringruntime.Youcanquicklydetectsmallissuesbyloggingsomevariablestateontheconsole.
Withtheseconceptswithus,let'sseehowwecanuseChromeDeveloperToolstodebugJavaScriptcode.
ChromeDeveloperTools
You can start Chrome Developer Tools by clickingmenu |More tools |Developer Tools. Take alookatthefollowingscreenshot:
![Page 479: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/479.jpg)
Chromedevelopertoolopensuponthelowerpaneofyourbrowserandhasabunchofveryusefulsections.Considerthefollowingscreenshot:
TheElementspanelhelpsyouinspectandmonitortheDOMtreeandassociatedstylesheetforeachofthesecomponents.
TheNetworkpanelisusefultounderstandnetworkactivity.Forexample,youcanmonitortheresourcesbeingdownloadedoverthenetworkinrealtime.
ThemostimportantpaneforusistheSourcespane.ThispaneiswheretheJavaScriptandthedebuggeraredisplayed.Let'screateasampleHTMLwiththefollowingcontent:
<!DOCTYPEhtml><html><head><metacharset="utf-8"><title>Thistest</title><scripttype="text/javascript">functionengageGear(gear){if(gear==="R"){console.log("Reversing");}if(gear==="D"){console.log("Driving");}if(gear==="N"){console.log("Neutral/Parking");}thrownewError("InvalidGearState");}try{engageGear("R");//ReversingengageGear("P");//InvalidGearState}catch(e){console.log(e.message);
}</script></head><body></body></html>
![Page 480: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/480.jpg)
SavethisHTMLfileandopenitinGoogleChrome.OpenDeveloperToolsinthebrowser,andyouwillseethefollowingscreen:
ThisistheviewoftheSourcespanel.YoucanseetheHTMLandembeddedJavaScriptsourceinthispanel.YoucanseetheConsolewindowaswell,andyoucanseethatthefileisexecutedandtheoutputisdisplayedonconsole.
Ontherightside,youwillseethedebuggerwindow,asshowninthefollowingscreenshot:
![Page 481: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/481.jpg)
IntheSourcespanel,clickonthelinenumbers8and15toaddabreakpoint.Thebreakpointsallowyoutostopexecutionofthescriptatthespecifiedpoint.Considerthefollowingscreenshot:
![Page 482: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/482.jpg)
Inthedebugpane,youcanseeallexistingbreakpoints.Takealookatthefollowingscreenshot:
Now,whenyourerunthesamepage,youwillseethattheexecutionstopsatthedebugpoint.Considerthefollowingscreenshot:
![Page 483: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/483.jpg)
This window now has all the action. You can see that the execution is paused on line 15. In thedebugwindow,youcanseewhichbreakpointisbeingtriggered.YoucanalsoseetheCallStackandresumeexecutioninseveralways.Thedebugcommandwindowhasabunchofactions.Takealookatthefollowingscreenshot:
Youcanresumeexecution,whichwillexecuteuntilthenextbreakpoint,byclickingonthefollowingbutton:
Whenyoudothat,theexecutioncontinuesuntilthenextbreakpointisencountered.Inourcase,wewillhaltatline8.Considerthefollowingscreenshot:
![Page 484: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/484.jpg)
YoucanobservethattheCallStackwindowshowshowwearrivedatline8.TheScopepanelshowstheLocalscopewhereyoucanseethevariablesinthescopewhenthebreakpointwasarrivedat.YoucanalsoStep-IntoorStep-overthenextfunction.
ThereareotherveryusefulmechanismstodebugandprofileyourcodeusingChromeDeveloperTools.Iwouldsuggestyoutoexperimentwiththetoolandmakeitapartofyourregulardevelopmentflow.
![Page 485: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/485.jpg)
SummaryBoth testing and debugging phases are essential to developing robust JavaScript code. TDD andBDDareapproachescloselyassociatedwiththeagilemethodologyandiswidelyembracedbytheJavaScriptdevelopercommunity.Inthischapter,wereviewedbestpracticesaroundTDDandtheusageofJasmineasthetestingframework.Additionally,wesawvariousmethodsofdebuggingJavaScriptusingChromeDeveloperTools.
Inthenextchapter,wewillexplorethenewandexcitingworldofES6,DOMManipulationandcross-browserstrategies.
![Page 486: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/486.jpg)
Chapter 13. Reactive Programming andReactAlongwithES6,severalnewideasareemerging.Thesearepowerfulideasandcanhelpyoubuildpowerfulsystemswithmorestreamlinedcodeanddesign.Inthischapter,wewillintroduceyoutotwosuchideas-reactiveprogrammingandreact.Althoughtheysoundsimilar,theyareverydifferent.Thischapterdoesnotgointopracticaldetailsoftheseideasbutgivesyounecessaryinformationtobecomeawareofwhattheseideasarecapableof.Withthatinformation,youcanstartincorporatingtheseideasandframeworksintoyourprojects.Wewilldiscussthebasicideaofreactiveprogrammingandtakeabitmoredetailedlookatreact.
![Page 487: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/487.jpg)
Reactive programmingReactive programming is getting a lot of focus lately. This idea is relatively new and, like manynewideas,haslotsofconfusing,andsometimescontradictoryinformationfloatingaround.Wediscussedasynchronousprogrammingearlierinthisbook.JavaScripttakesasynchronousprogrammingtonewheightsbyprovidingfirstclasslanguageconstructsthatsupportit.
Reactiveprogrammingisessentiallyprogrammingwithasynchronouseventstreams.Aneventstreamisasequenceofeventshappeningovertime.Considerthefollowingdiagram:
Intheprecedingdiagram,timepassesfromlefttorightanddifferenteventsoccurovertime.Astheeventhappensovertime,wecanaddaneventlistenertothiswholesequence.Wheneveraneventhappens,wecanreacttoitbydoingsomething.
AnothertypeofsequenceinJavaScriptisanarray.Forexample,considerthefollowinglinesofcode:
vararr=[1,1,13,'Rx',0,0];console.log(arr);>>>[1,1,13,"Rx",0,0]
Inthiscase,theentiresequencelivesinmemoryatthesametime.However,incaseofeventstream,eventshappenovertimeandthereisnostateatthispointoftime.Considerthefollowinglinesofcode:
vararr=Rx.Observable.interval(500).take(9).map(a=>[1,1,13,'Rx',0,0][a]);
![Page 488: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/488.jpg)
varresult=arr;result.subscribe(x=>console.log(x));
Don'tworrytoomuchaboutwhatisgoingoninthisexamplejustyet.Here,eventsarehappeningovertime.Insteadofhavingafixedbunchofelementsinanarray,heretheyarehappeningovertime,after500ms.
Wewilladdaneventlistenertothearreventstream,andwhenaneventhappens,wewillprinttheelementonconsole.Youcanseeasimilaritybetweenthemethodsinarraysandtheeventstreams.Now,toexpandonthissimilarity,let'ssay,youwanttofilterallnon-numbersfromthislist.Youcanusethemapfunctiontothiseventstream,justlikeyouwoulduseitonanarray,andthenyouwouldwanttofiltertheresultstoshowonlyintegers.Considerthefollowinglinesofcode:
vararr=[1,1,13,'Rx',0,0];varresult=arr.map(x=>parseInt(x)).filter(x=>!isNan(x));console.log(result);
Interestingly,thesamemethodsworkforeventstreamsaswell.Takealookatthefollowingcodeexample:
vararr=Rx.Observable.interval(500).take(9).map(a=>[1,1,13,'Rx',0,0][a]);varresult=arr.map(x=>parseInt(x)).filter(x=>!isNaN(x));result.subscribe(x=>console.log(x));
Thesearesimplerexamplesjusttomakesureyoustartseeinghoweventstreamsflowovertime.Pleasedon'tbotheraboutthesyntaxandconstructjustyet.Beforewecanlookatthem,wewillneedtomakesureweunderstandhowtothinkinreactiveprogramming.Eventstreamsarefundamentaltoreactiveprogramming;theyallow youtodefinethedynamicbehaviorofavalueatdeclarationtime(definitiontakenfromAndreStaltz'sblog).
Let'ssayyouhaveanavariable,whichhasinitiallythevalue3.Then,youhaveabvariable,whichis10*a.Ifweconsolelogoutb,wewillsee30.Considerthefollowinglinesofcode:
leta=3;let b = a * 10;
console.log(b);//30a=4;console.log(b);//Still30
Weknowtheresultisverystraightforward.Whenwechangethevalueofato4,thevalueofbwillnotchange.Thisishowstaticdeclarationworks.Whenwetalkaboutreactiveprogrammingandeventstreams,thisistheareawherepeoplefinddifficultyinunderstandinghoweventsflow.Ideally, we want to create a formula, b=a*10, and over time, whenever the value of a changes,the changed value is reflected in the formula.
![Page 489: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/489.jpg)
Thatiswhatwecanaccomplishwitheventstreams.Let'ssayaisaneventstreamofjustthevalue3.Then,wehavestreamB,whichisstreamAmapped.Eachoftheseavalueswillbemappedto10*a.
IfweaddaneventlistenertothatstreamB,andweconsolelog,wewillseebbeing30.Takealookatthefollowingexample:
varstreamA=Rx.Observable.of(3,4);varstreamB=streamA.map(a=>10*a);streamB.subscribe(b=>console.log(b));
Ifwedothis,wehaveaneventstreamthatsimplyhasjusttwoevents.Ithasevent3,andthenithasevent4,andbwillchangeaccordinglywheneverachanges.Ifwerunthis,weseebbeing30and40.
Nowthatwehavespentsometimeingettingthebasicsofreactiveprogrammingsorted,youmayaskthefollowingquestion.
![Page 490: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/490.jpg)
Whyshouldyouconsiderreactiveprogramming?
AswewritehighlyresponsiveandinteractiveUIapplicationsonmodernwebandmobile,thereisastrongneedtofinda waytodealwithreal-timeeventswithoutstoppingtheuserinteractionsontheUI.WhenyouaredealingwithmultipleUI andservereventsbeingfired,youwillbespendingmostofyourtimewritingcodetodealwiththeseevents.Thisistedious.Reactiveprogramminggivesyouastructuredframeworktodealwithasynchronouseventswithminimalcodewhileyoufocusonthebusinesslogicforyourapplication.
ReactiveprogrammingisnotlimitedtoJavaScript.Reactiveextensionsareavailableinmanyplatformsandlanguages,suchasJava,Scala,Clojure,Ruby,Python,andObjectC/Cocoa.Rx.jsandBacon.jsarepopularJavaScriptlibrariesthatprovidereactiveprogrammingsupport.
AdeepdiveintoRx.jsisnottheintentionofthischapter.Theideawastointroduceyoutotheideaofreactiveprogramming.Ifyouarekeenonadoptingreactiveprogrammingforyourprojects,youshouldtakelookatAndreStaltz'sexcellentintroduction(https://gist.github.com/staltz/868e7e9bc2a7b8c1f754).
![Page 491: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/491.jpg)
ReactReact is taking the JavaScript world by storm. Facebook created the react framework to solve anage-oldproblem-howtodealefficientlywiththeviewpartofthetraditionalModel-View-Controllerapplications.
Reactprovidesadeclarativeandflexiblewaytobuilduserinterfaces.Themostimportantthingtorememberaboutreactisthatitdealswithonlyonething-theview,ortheUI.Reactdoesnotdealwithdata,databindings,oranythingelse.Therearecompleteframeworks,suchasAngular,thatdealwithdata,bindings,andUI;Reactisnotthat.
ReactgivesatemplatelanguageandasmallsetoffunctionstorenderHTML.Reactcomponentscanstoretheirownstateinmemory.Tobuildafull-fledgedapplication,youwillneedotherpiecesaswell;Reactisjusttohandletheviewpartofthatapplication.
A big challenge when writing complex UI is to manage state of the UI elements when the modelchanges.ReactprovidesadeclarativeAPIsothatyoudon'thavetoworryaboutexactlywhatchangesoneveryupdate.Thismakeswritingapplicationsaloteasier.ReactusesVirtualDOManddiffingalgorithm,sothatcomponentupdatesarepredictablewhilebeingfastenoughforhigh-performanceapps.
![Page 492: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/492.jpg)
Virtual DOMLet's take a moment to understand what is a Virtual DOM. We discussed DOM (document objectmodel),atreestructureofHTMLelementonawebpage.DOMisdefacto,andtheprimaryrenderingmechanismoftheweb.TheDOMAPIs,suchasgetElementById(),allowtraversingandmodificationoftheelementsintheDOMtree.DOMisatreeandthisstructureworksprettywellwithtraversalandupdatingofelements.However,boththetraversingandupdatingofDOMisnotveryquick.Foralargepage,theDOMtreecanbeprettybig.When youwantacomplexUIthathasbunchofuserinteractions,updatingDOMelementscanbetediousandslow.WehavetriedjQueryandotherlibrariestoreducethetedioussyntaxforfrequentDOMmodifications,butDOMasastructureitselfisquitelimited.
Whatifwedon'thavetotraversetheDOMoverandoveragaintomodifyelements?Whatifyoujustdeclarehowacomponentshouldlooklikeandletsomeonehandlethelogicofhowtorenderthatcomponent?reactdoesexactlythat.ReactletsyoudeclarehowyouwantyourUIelementtolooklikeandabstractsoutlow-levelDOMmanipulationAPIs.Apartfromthisveryusefulabstraction,reactdoessomethingprettysmarttosolvetheperformanceproblemaswell.
ReactusessomethingcalledaVirtualDOM.AvirtualDOMisalightweightabstractionoftheHTMLDOM.Youcanthinkofitasalocalin-memorycopyoftheHTMLDOM.Reactusesittodo all computations necessary to render the state of a UI component.
Youcanfindmoredetailsofthisoptimizationathttps://facebook.github.io/react/docs/reconciliation.html.
React'sprimarystrength,however,isnotjustVirtualDOM.Reactisafantasticabstractionthatmakescomposition,unidirectionaldataflow,andstaticmodelingeasierwhiledevelopinglargeapplications.
![Page 493: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/493.jpg)
Installing and running reactFirst, let's install react. Earlier, installing and getting react set up on your machine needed a bunchofdependenciestobetakencareof.However,wewillusearelativelyfasterwaytogetreactupandrunning.Wewillusecreate-react-apptowhichwecaninstallreactwithoutanybuildconfiguration.Installationisdonevianpmwhichisasfollows:
npminstall-gcreate-react-app
Here,weareinstallingthecreate-react-appnodemoduleglobally.Oncecreate-react-appisinstalled,youcansetupthedirectoryforyourapplication.Considerthefollowingcommands:
create-react-appreact-appcdreact-app/
npm start
Then,openhttp://localhost:3000/toseeyourapp.Youshouldseesomethinglikethefollowingscreenshot:
Ifyouopenthedirectory inaneditor,youwillseeseveralfilescreatedforyou,asyoucanseein
![Page 494: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/494.jpg)
thefollowingscreenshot:
![Page 495: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/495.jpg)
Inthisproject,node_modulesarethedependenciesrequiredtorunthisprojectanddependenciesofreactitself.Theimportantdirectoryissrc,wherethesourcecodeiskept.Forthisexample,let'skeeponlytwofiles-App.jsandindex.js.The/public/index.htmlfileshouldcontainjusttherootdiv,whichwillbeusedasatargetforourreactcomponents.Considerthefollowingcodesnippet:
<!doctypehtml><html lang="en">
<head><title>ReactApp</title></head><body><divid="root"></div></body></html>
Themomentyoumakethischange,youwillseethefollowingerror:
Beauty of developing with react is that the code changes are live-reloaded, and you can getimmediatefeedback.
Next,clearoffallcontentofApp.js,andreplaceitwiththefollowinglinesofcode:
importReactfrom'react';constApp=()=><h1>HelloReact</h1>exportdefaultApp
Now,gotoindex.jsandremovetheimport./index.css;line.Withoutyoudoinganything,suchasrestartingserverandrefreshingbrowser,youwillseethemodifiedpageonthebrowser.Considerthefollowingscreenshot:
![Page 496: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/496.jpg)
BeforewecreateaHelloWorldreactcomponent,acoupleofimportantthingstonoticesofar.
InApp.jsandindex.js,weareimportingtwolibrariesnecessarytocreatereactcomponents.Considerthefollowinglinesofcode:
importReactfrom'react';importReactDOMfrom'react-dom';
Here,we'reimportingReact,whichisthelibrarythatallowsustobuildreactcomponents.We'realsoimportingReactDOM,whichisthelibrarythatallowsustoplaceourcomponentsandworkwiththeminthecontextoftheDOM.Then,we'reimportingthecomponentthatwejustworkedon-theAppcomponent.
We also created our first component in App.js. Consider the following line of code:
constApp=()=><h1>HelloReact</h1>
Thisisastatelessfunctioncomponent.Theotherwaytocreateacomponentistocreateaclasscomponent.Wecanreplacetheprecedingcomponentwiththefollowingclasscomponent:
classAppextendsReact.Component{render(){return<h1>HelloWorld</h1>}}
Thereareabunchofinterestingthingsgoingonhere.First,wearecreatingaclasscomponentwiththeclasskeywordthatextendsfromthesuperclassReact.Component.
OurcomponentAppisareactcomponentclassorreactcomponenttype.Acomponenttakesinparameters,alsocalledprops,andreturnsahierarchyofviewstodisplayviatherenderfunction.
![Page 497: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/497.jpg)
Therendermethodreturnsadescriptionofwhatyouwanttorender,andthenreacttakesthatdescriptionandrendersittothescreen.Inparticular,renderreturnsareactelement,whichisalightweightdescriptionofwhattorender.MostreactdevelopersuseaspecialsyntaxcalledJSX,whichmakesiteasiertowritethesestructures.The<div/>syntaxistransformedatbuildtimetoReact.createElement('div').TheJSXexpression,<h1>HelloWorld</h1>,istransformedatbuildtimeintothefollowing:
returnReact.createElement('h1',null,'HelloWorld');
Thedifferencebetweentheclasscomponentandstatelessfunctioncomponentisthattheclasscomponentcancontaina statewhilethestateless(hencethename)functioncomponentcannot.
Therendermethodofthereactcomponentisallowedtoreturnonlyasinglenode.Ifyoudosomethinglikethefollowing:
return<h1>HelloWorld</h1><p>ReactRocks</p>
Youwillgetthefollowingerror:
Errorin./src/App.jsSyntaxerror:AdjacentJSXelementsmustbewrappedinanenclosingtag(4:31)
ThisisbecauseyouareessentiallyreturningtwoReact.createElement functions,andthatisnotvalidJavaScript.Whilethismayseemlikeadealbreaker,thisiseasytosolve.Wecanwrapournodesintoaparentnodeandreturnthatparentnodefromtherenderfunction.Wecancreateaparentdivandwrapothernodesunderit.Considerthefollowingexample:
render(){return(<div><h1>HelloWorld</h1><p>ReactRocks</p></div>)}
![Page 498: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/498.jpg)
Componentsandprops
ComponentscanbeconceptuallyconsideredasJavaScriptfunctions.Theytakearbitrarynumberofinputslikenormalfunctions.Theseinputsarecalledprops.Toillustratethis,let'sconsiderthefollowingfunction:
functionGreet(props){return<h1>Hello,{props.name}</h1>;}
Thisisanormalfunctionandalsoavalidreactcomponent.IttakesaninputcalledpropsandreturnsavalidJSX.Wecanusethepropsinside JSXusingcurlybracesandpropertiessuchasnameusingastandardobjectnotation.NowthatGreetisafirstclassreactcomponent,let'suseitintherender()functionasfollows:
render(){return(return<Greetname="Joe"/>)}
WearecallingGreet()asanormalcomponentandpassingthis.propstoit.Itisrequiredtocapitalizeyourowncomponents.ReactconsiderscomponentnamesstartingwithalowercaseasstandardHTMLtagsandexpectscustomcomponentnamestostartwithacapitalletter.Aswesawearlier,wecancreateaclasscomponentusingES6class.ThiscomponentisasubclassofReact.component.AnequivalentcomponenttoourGreetfunctionisasfollows:
classGreetextendsReact.Component{render(){return<h1>Hello,{this.props.name}</h1>}}
Forallpracticalpurposes,wewillusethismethodofcreatingcomponents.Wewillsoonknowwhy.
Oneimportantpointtonoteisthatacomponentcannotmodifyitsownprops.Thismayseemlikealimitationbecause,inalmostallnon-trivialapplications,youwillwantuserinteractionswheretheUIcomponentstateischangedinreact,forexample,updatedateofbirthinaform,propsareread-onlybutthereisamuchrobustmechanismtohandleUIupdates.
![Page 499: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/499.jpg)
State
Stateissimilartoprops,butitisprivateandfullycontrolledbythecomponent.Aswesawearlierthatbothfunctionalandclasscomponentsareequivalentinreact,oneimportantdistinctionisthatthestateisavailableonlyinclasscomponents.Hence,forallpracticalpurposes,wewilluseclasscomponents.
Wecanchangeourexistinggreetingexampletousestate,andwheneverthestatechanges,wewillupdateourGreetcomponenttoreflectthechangedvalue.
First,wewillsetupthestateinsideourApp.js,asfollows:
classGreetextendsReact.Component{constructor(props){super(props);
this.state={greeting:"thisisdefaultgreetingtext"}
}render(){return<h1>{this.state.greeting},{this.props.name}</h1>}}
Thereareafewimportantthingstonoticeinthisexample.First,wearecallingclassconstructortoinitializethis.state.Wealsocallthebaseclassconstructor,super(),andpasspropstoit.Aftercallingsuper(),weinitializeourdefaultstatebysettingthis.statetoanobject.Forexample,weassignagreetingpropertywithavaluehere.Intherendermethod,wewillusethispropertyusing{this.state.greeting}.Havingsetupourinitialstate,wecanaddUIelementstoupdatethisstate.Let'saddaninputbox,andonchangeofthatinputbox,wewillupdateourstateandthegreetingelement.Considerthefollowinglinesofcode:
classGreetextendsReact.Component{constructor(props){super(props);this.state={greeting:"thisisdefaultgreetingtext"}}
updateGreeting(event){this.setState({greeting:event.target.value,})}render(){
![Page 500: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/500.jpg)
return(<div><inputtype="text"onChange={this.updateGreeting.bind(this)}/><h1>{this.state.greeting},{this.props.name}</h1></div>)}}
Here,weaddaninputboxandupdatethestateofthecomponentwhentheonChangemethodoftheinputboxisinvoked. WeuseacustomupdateGreeting()methodtoupdatethestatebycallingthis.setStateandupdatingtheproperty.Whenyourunthisexample,youwillnoticethatasyoutypesomethingonthetextbox,onlythegreetingelementisupdatedandnotthename.Takealookatthefollowingscreenshot:
Animportantfeatureofreactisthefactthatareactcomponentcanoutputorrenderotherreactcomponents.We'vegotaverysimplecomponenthere.Ithasastatewithavalueoftext.It'sgotanupdatemethodwhichwillupdatethatvalueoftextfromanevent.Whatwe'lldoiscreateanewcomponent.Thiswillbeastatelessfunctioncomponent.We'llcallitwidget.Itwilltakeinprops.We'llreturnthisJSXinputrighthere.Considerthefollowingcodesnippet:
render(){return(<div><Widgetupdate={this.updateGreeting.bind(this)}/>
<Widget update={this.updateGreeting.bind(this)} />
<Widgetupdate={this.updateGreeting.bind(this)}/><h1>{this.state.greeting},{this.props.name}</h1></div>)}
![Page 501: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/501.jpg)
}constWidget=(props)=><inputtype="text"onChange={props.update}/>
First,weextractourinputelementintoastatelessfunctioncomponentandcallitaWidget.Wepasspropstothiscomponent.Then,wechangeonChangetouseprops.update.Now,insideourrendermethod,weusetheWidgetcomponentandpassapropupdatethatbindstheupdateGreeting()method.NowthatWidgetisacomponent,wecanreuseitanywhereintheGreetcomponent.WearecreatingthreeinstancesoftheWidget,andwhenanyoftheWidgetisupdated,thegreetingtextisupdated,asshowninthefollowingscreenshot:
![Page 502: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/502.jpg)
Lifecycleevents
Whenyouhaveabunchofcomponentswithseveralstatechangesandevents,thehousekeepingbecomesimportant.Reactprovidesyouwithseveralcomponentlifecyclehookstohandlelifecycleeventsofcomponents.Understandingthecomponentlifecyclewillenableyoutoperformcertainactionswhenacomponentiscreatedordestroyed.Furthermore,itgivesyoutheopportunitytodecideifacomponentshouldbeupdatedinthefirstplace,andtoreacttopropsorstatechangesaccordingly.
Therearethreephasesthatthecomponentgoesthrough-mounting,updating,andunmouting.Foreachofthesestages,wehavehooks.Takealookatthefollowingdiagram:
Twomethodsarecalledwhenacomponentisinitiallyrendered,getDefaultPropsandgetInitialState,and, astheirnamessuggest,wecansetdefaultprops andinitialstateofacomponentinthesemethods.
ThecomponentWillMountiscalledbeforetherendermethodisexecuted.Wealreadyknowrendertobetheplacewherewereturnthecomponenttoberendered.Assoonastherendermethodfinishes,thecomponentDidMountmethodisinvoked.YoucanaccessDOMinthismethod,anditisrecommendedtoperformanyDOMinteractionsinthismethod.
Statechangesinvokeafewmethods.TheshouldComponentUpdatemethodisinvokedbeforetherendermethod,anditletsusdecideifweshouldallowrerenderingorskipit.Thismethodisnevercalledontheinitialrendering.ThecomponentWillUpdatemethod getscalledimmediatelyoncetheshouldComponentUpdatemethodreturnstrue.ThecomponentDidUpdatemethodisrenderedafterrenderfinishes.
![Page 503: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/503.jpg)
Anychangetothepropsobjecttriggerssimilarmethodsasastatechange.OneadditionalmethodcallediscomponentWillReceiveProps;itiscalledonlywhenthepropshavechanged,anditisnotinitialrendering.Youcanupdatestatebasedonnewandoldpropsinthismethod.
WhenacomponentisremovedfromDOM,componentWillUnmountiscalled.Thisisausefulmethodtoperformcleanups.
Greatthingaboutreactisthatwhenyoustartusingit,theframeworkfeels verynaturaltoyou.Thereareveryfewmovingpartsyouwillneedtolearn,andtheabstractionisjustright.
![Page 504: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/504.jpg)
SummaryThis chapter was aimed at some of the important new ideas that are gaining a lot of prominencelately.Bothreactiveprogrammingandreactcansignificantlyboostprogrammerproductivity.ReactisdefinitelyoneofthemostimportantemergingtechnologiesbackedbythelikesofFacebookandNetflix.
Thischapterwasintendedtogiveyouanintroductiontoboththesetechnologiesandhelpyoustartexploringtheminmoredetail.
![Page 505: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/505.jpg)
Appendix A. Reserved WordsThis appendix provides two lists of reserved keywords as defined in ECMAScript 5 (ES5). Thefirstoneisthecurrentlistofwords,andthesecondisthelistofwordsreservedforfutureimplementations.
There'salsoalistofwordsthatarenolongerreserved,althoughtheyusedtobeinES3.
Youcannotusereservedwordsasvariablenames:
varbreak=1;//syntaxerror
Ifyouusethesewordsasobjectproperties,youhavetoquotethem:
varo={break:1};//OKinmanybrowsers,errorinIEvaro={"break":1};//AlwaysOKalert(o.break);//errorinIEalert(o["break"]);//OK
![Page 506: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/506.jpg)
KeywordsThe list of words currently reserved in ES5 is as follows:
break
case
catch
continue
debugger
default
delete
do
else
finally
for
function
if
in
instanceof
new
return
switch
this
throw
try
typeof
var
void
while
with
![Page 507: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/507.jpg)
ES6 reserved wordsThe following keywords are reserved in ES6:
class
const
enum
export
extends
implements
import
interface
let
package
private
protected
public
static
super
yield
![Page 508: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/508.jpg)
Futurereservedwords
Thesekeywordsarenotusedcurrentlybuttheyarereservedforthefutureversions:
enum
await
![Page 509: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/509.jpg)
Previously reserved wordsThe following words are no longer reserved starting with ES5, but it's best to stay away fromthemforthesakeofolderbrowsers:
abstract
boolean
byte
char
double
final
float
goto
int
long
native
short
synchronized
throws
transient
volatile
![Page 510: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/510.jpg)
Appendix B. Built-in FunctionsThis appendix contains a list of the built-in functions (methods of the global object), discussed inChapter3,Functions:
Function Description
parseInt()
Takestwoparameters:aninputobjectandradix;thentriestoreturnanintegerrepresentationoftheinput.Doesn'thandleexponentsintheinput.Thedefaultradixis10(adecimalnumber).ReturnsNaNonfailure.Omittingtheradixmayleadtounexpectedresults(forexampleforinputssuchas08),soit'sbesttoalwaysspecifyit:
>parseInt('10e+3');10 >parseInt('FF');NaN>parseInt('FF',16);255
parseFloat()
Takesaparameterandtriestoreturnafloating-pointnumberrepresentationofit.Understandsexponentsintheinput:
>parseFloat('10e+3');10000>parseFloat('123.456test');123.456
isNaN()
Abbreviatedfrom"IsNotaNumber".Acceptsaparameterandreturnstrueiftheparameterisnotavalidnumber,falseotherwise.Attemptstoconverttheinputtoanumberfirst:
>isNaN(NaN);true>isNaN(123);false>isNaN(parseInt('FF'));true>isNaN(parseInt('FF',16));false
isFinite()
Returnstrueiftheinputisanumber(orcanbeconvertedtoanumber),butifitisnotanumberInfinityor-Infinity.Returnsfalseforinfinityornon-numericvalues:
>isFinite(1e+1000);false>isFinite(-Infinity);false>isFinite("123");true
encodeURIComponent()
ConvertstheinputintoaURL-encodedstring.FormoredetailsonhowURLencodingworks,refertotheWikipediaarticleathttp://en.wikipedia.org/wiki/Url_encode:
>encodeURIComponent('http://phpied.com/');"http%3A%2F%2Fphpied.com%2F">encodeURIComponent('somescript?key=v@lue');
![Page 511: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/511.jpg)
"some%20script%3Fkey%3Dv%40lue"
decodeURIComponent()
TakesanURL-encodedstringanddecodesit:
>decodeURIComponent('%20%40%20');"@"
encodeURI()
URL-encodestheinput,butassumesafullURLisgiven,soreturnsavalidURLbynotencodingtheprotocol(forexample,http://)andhostname(forexample,www.phpied.com):
> encodeURI('http://phpied.com/');"http://phpied.com/">encodeURI('somescript?key=v@lue');"some%20script?key=v@lue"
decodeURI()
OppositeofencodeURI():
>decodeURI("some%20script?key=v@lue");"somescript?key=v@lue"
eval()
AcceptsastringofJavaScriptcodeandexecutesit.Returnstheresultofthelastexpressionintheinputstring.
Tobeavoidedwherepossible:
>eval('1+2');3 >eval('parseInt("123")');123>eval('newArray(1,2,3)');[1,2,3]>eval('newArray(1,2,3);1+2;');3
![Page 512: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/512.jpg)
Appendix C. Built-in ObjectsThis appendix lists the built-in constructor functions outlined in the ECMAScript (ES) standard,togetherwiththepropertiesandmethodsoftheobjectscreatedbytheseconstructors.ES5-specificAPIsarelistedseparately.
![Page 513: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/513.jpg)
ObjectObject() is a constructor that creates objects, for example:
>varo=newObject();
Thisisthesameasusingtheobjectliteral:
>varo={};//recommended
Youcanpassanythingto theconstructoranditwilltrytoguesswhatitisanduseamoreappropriateconstructor.Forexample,passingastringtonewObject()willbethesameasusingthenewString()constructor.Thisisnotarecommendedpractice(it'sbettertobeexplicitthanletguessescreepin),butstillpossible:
>varo=newObject('something');>o.constructor;functionString(){[nativecode]}>varo=newObject(123);>o.constructor;functionNumber(){[nativecode]}
Allotherobjects,built-inorcustom,inheritfrom Object.Sothepropertiesandmethodslistedinthefollowingsectionsapplytoalltypesofobjects.
![Page 514: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/514.jpg)
MembersoftheObjectconstructor
FollowingarethemembersoftheObjectconstructor:
Property/method Description
Object.prototype
Theprototypeofallobjects(alsoanobjectitself).Anythingyouaddtothisprototypewillbeinheritedbyallotherobjects,sobecareful:
>vars=newString('noodles');>Object.prototype.custom=1;1>s.custom;1
![Page 515: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/515.jpg)
TheObject.prototypemembers
Insteadofsaying"membersoftheObjectscreatedbytheObjectconstructor",let'ssayheadings"Object.prototypemembers".ItisthesameforArray.prototypeandsoonfurtherinthisappendix:
Property/method Description
constructor
Pointsbacktotheconstructorfunctionusedtocreatetheobject,inthiscase,Object:
>Object.prototype.constructor===Object;true>varo=newObject();>o.constructor===Object;true
toString(radix)
Returnsastringrepresentationoftheobject.IftheobjecthappenstobeaNumberobject,theradixparameterdefinesthebaseofthereturnednumber.Thedefaultradixis10:
>varo={prop:1};>o.toString();"[objectObject]">varn=newNumber(255);>n.toString();"255">n.toString(16);"ff"
toLocaleString()
SameastoString(),butmatchingthecurrentlocale.Meanttobecustomizedbyobjects,suchasDate(),Number(),andArray()andprovidelocale-specificvalues,suchasdifferentdateformatting.InthecaseofObject()instancesaswithmostothercases,itjustcallstoString().
Inbrowsers,youcanfigureoutthelanguageusingthepropertylanguage(oruserLanguageinIE)ofthenavigatorBOMobject:
>navigator.language;"en-US"
valueOf()
Returnsaprimitiverepresentationofthis,ifapplicable.Forexample,NumberobjectsreturnaprimitivenumberandDateobjectsreturnatimestamp.Ifnosuitableprimitivemakessense,itsimplyreturnsthis:
>varo={};>typeofo.valueOf();"object">o.valueOf()===o;true>varn=newNumber(101);
> typeof n.valueOf();"number">n.valueOf()===n;false>vard=newDate();>typeofd.valueOf();"number">d.valueOf();1357840170137
![Page 516: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/516.jpg)
hasOwnProperty(prop)
Returnstrueifapropertyisanownpropertyoftheobject,orfalseifitwasinheritedfromtheprototypechain.Alsoreturnsfalseifthepropertydoesn'texist:
>varo={prop:1};>o.hasOwnProperty('prop');true>o.hasOwnProperty('toString');false>o.hasOwnProperty('fromString');false
isPrototypeOf(obj)
Returnstrueifanobjectisusedasaprototypeofanotherobject.Anyobjectfromtheprototypechaincanbetested,notonlythedirectcreator:
>vars=newString('');>Object.prototype.isPrototypeOf(s);true>String.prototype.isPrototypeOf(s);true>Array.prototype.isPrototypeOf(s);false
propertyIsEnumerable(prop)
Returnstrueifapropertyshowsupinafor...inloop:
>vara=[1,2,3];>a.propertyIsEnumerable('length');false>a.propertyIsEnumerable(0);true
![Page 517: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/517.jpg)
ECMAScript5additionstoobjects
InECMAScript3allobjectpropertiescanbechanged,added,ordeletedatanytime,exceptforafewbuilt-inproperties(forexample,Math.PI).InES5youhavetheabilitytodefinepropertiesthatcannotbechangedordeleted,aprivilegepreviouslyreservedforbuilt-ins.ES5introducestheconceptofpropertydescriptorsthatgiveyoutightercontroloverthepropertiesyoudefine.
Thinkofapropertydescriptorasanobjectthatspecifiesthefeaturesofaproperty.Thesyntaxtodescribethesefeaturesisaregularobjectliteral, sopropertydescriptorshavepropertiesandmethodsoftheirown,butlet'scallthemattributestoavoidconfusion.Theattributesare:
value-whatyougetwhenyouaccessthepropertywritable-canyouchangethispropertyenumerable-shoulditappearinfor...inloopsconfigurable-canyoudeleteitset()-afunctioncalledanytimeyouupdatethevalueget()-calledwhenyouaccessthevalueoftheproperty
Furtherthere'sadistinctionbetweendatadescriptors(youdefinethepropertiesenumerable,configurable,value,andwritable)andaccessordescriptors(youdefineenumerable,configurable,set(),andget()).Ifyoudefineset()orget(),thedescriptorisconsideredanaccessorandattemptingtodefinevalueorwritablewillraiseanerror.
DefiningaregularoldschoolES3-styleproperty:
varperson={};person.legs=2;
SameusinganES5datadescriptor:
varperson={};Object.defineProperty(person,"legs",{value:2,writable:true,configurable:true,enumerable:true
});
Thevalueofvalueifsettoundefinedbydefault,allothersarefalse.Soyouneedtosetthemtotrueexplicitlyifyouwanttobeabletochangethispropertylater.
OrthesamepropertyusinganES5accessordescriptor:
varperson={};Object.defineProperty(person,"legs",{set:function(v){this.value=v;},get:function(v){returnthis.value;},
![Page 518: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/518.jpg)
configurable:true,enumerable:true});person.legs=2;
Asyoucanseepropertydescriptorsarealotmorecode,soyouonlyusethemifyoureallywanttopreventsomeonefrommanglingyourproperty,andalsoyouforgetaboutbackwardscompatibilitywithES3browsersbecause,unlikeadditionstoArray.prototypeforexample,youcannot"shim"thisfeatureinoldbrowsers.
Andthepowerofthedescriptorsinaction(defininganonmalleableproperty):
>varperson={};>Object.defineProperty(person,'heads',{value:1});>person.heads=0;0>person.heads;1>deleteperson.heads;false>person.heads;
1
ThefollowingisalistofallES5additionstoObject:
Property/method Description
Object.getPrototypeOf(obj)
WhileinES3youhavetoguesswhatistheprototypeofagivenobjectisusingthemethodObject.prototype.isPrototypeOf(),inES5 youcandirectlyask"Whoisyourprototype?"
>Object.getPrototypeOf([])===Array.prototype;true
Object.create(obj,descr)
DiscussedinChapter7,Inheritance.Createsanewobject,setsitsprototypeanddefinespropertiesofthatobjectusingpropertydescriptors(discussedearlier):
>varparent={hi:'Hello'};>varo=Object.create(parent,{prop:{value:1}});>o.hi;"Hello"
Itevenletsyoucreateacompletelyblankobject,somethingyoucannotdoinES3:
> var o = Object.create(null);>typeofo.toString;"undefined"
Allowsyoutoinspecthowapropertywasdefined.Youcanevenpeekintothebuilt-ins and see all these previously hidden attributes:
>Object.getOwnProperty
![Page 519: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/519.jpg)
Object.getOwnPropertyDescriptor(obj,property)
Descriptor(Object.prototype,'toString');Objectconfigurable:trueenumerable:falsevalue:functiontoString(){[nativecode]}writable:true
Object.getOwnPropertyNames(obj)
Returnsanarrayofallownpropertynames(asstrings),enumerableornot.UseObject.keys()togetonlyenumerableones:
>Object.getOwnPropertyNames(Object.prototype);["constructor","toString","toLocaleString","valueOf",...
Object.defineProperty(obj,descriptor)
Definesapropertyofanobjectusingapropertydescriptor.Seethediscussionprecedingthistable.
Object.defineProperties(obj,descriptors)
SameasdefineProperty(),butletsyoudefinemultiplepropertiesatonce:
>varglass=Object.defineProperties({},{"color":{value:"transparent",writable:true
},"fullness":{value:"half",writable:false}});>glass.fullness;"half"
Object.preventExtensions(obj)
Object.isExtensible(obj)
preventExtensions()disallowsaddingfurtherpropertiestoanobjectandisExtensible()checkswhetheryoucanaddproperties:
>vardeadline={};>Object.isExtensible(deadline);true>deadline.date="yesterday";"yesterday">Object.preventExtensions(deadline);>Object.isExtensible(deadline);false>deadline.date="today";
"today">deadline.date;"today"
Attemptingtoaddpropertiestoanon-extensibleobjectisnotanerror,butsimplydoesn'twork:
>deadline.report=true;>deadline.report;undefined
![Page 520: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/520.jpg)
Object.seal(obj)
Object.isSealed(obj)
seal()doesthesameaspreventExtensions()andadditionallymakesallexistingpropertiesnon-configurable.
Thismeansyoucanchangethevalueofanexistingproperty,butyoucannotdeleteitorreconfigureit(usingdefineProperty()won'twork).Soyoucannot,forexample,makeanenumerablepropertynon-enumerable.
Object.freeze(obj)
Object.isFrozen(obj)
Everythingthatseal()doespluspreventschangingthevaluesofproperties:
>vardeadline=Object.freeze({date:"yesterday"});>deadline.date="tomorrow";>deadline.excuse="lame";
> deadline.date;"yesterday">deadline.excuse;undefined>Object.isSealed(deadline);true
Object.keys(obj)
Analternativetoafor...inloop.Returnsonlyownproperties(unlikefor...in).Thepropertiesneedtobeenumerableinordertoshowup(unlikeObject.getOwnPropertyNames()).Thereturnvalueisanarrayofstrings.
>Object.prototype.customProto=101;>Object.getOwnPropertyNames(
Object.prototype);
["constructor","toString",...,"customProto"]
>Object.keys(Object.prototype);
["customProto"]>varo={own:202};>o.customProto;101>Object.keys(o);"own"]
![Page 521: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/521.jpg)
ES6 addition to objectsES6 has a few interesting object definition and property syntax. This new syntax is to makeworkingwithobjectseasierandconcise.
![Page 522: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/522.jpg)
Propertyshorthand
ES6providesashortersyntaxforcommonobjectdefinition.
ES5:obj={x:x,y:y};
ES6:obj={x,y};
![Page 523: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/523.jpg)
Computedpropertynames
Itispossibletocompute propertynamesinthenewES6objectdefinitionsyntax:
let obj = {foo:"bar",["baz"+q()]:42}
Herethepropertynameiscomputedwhere"baz"isconcatenatedwiththeresultofthefunctioncall.
![Page 524: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/524.jpg)
Object.assign
TheObject.assign()methodisusedtocopythevaluesofallenumerableownpropertiesfromoneormoresourceobjectstoatargetobject:
var dest = { quux: 0 }varsrc1={foo:1,bar:2}varsrc2={foo:3,baz:4}Object.assign(dst,src1,src2)
![Page 525: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/525.jpg)
ArrayThe Array constructor creates array objects:
>vara=newArray(1,2,3);
Thisisthesameasthearrayliteral:
>vara=[1,2,3];//recommended
WhenyoupassonlyonenumericvaluetotheArrayconstructor,it'sassumedtobethearraylength:
>varun=newArray(3);>un.length;3
Yougetanarraywiththedesiredlengthandifyouaskforthevalueofeachofthearrayelements,you get undefined:
>un;[undefined,undefined,undefined]
Thereisasubtledifferencebetweenanarrayfullofelementsandarraywithnoelements,butjustlength:
>'0'ina;true>'0'inun;false
ThisdifferenceintheArray()constructor'sbehaviorwhenyouspecifyoneversusmoreparameterscanleadtounexpectedbehavior.Forexample,thefollowinguseofthearrayliteralisvalid:
>vara=[3.14];>a;[3.14]
However, passing the floating-point number to the Array constructor is an error:
>vara=newArray(3.14);RangeError:invalidarraylength
![Page 526: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/526.jpg)
TheArray.prototypemembers
ThefollowingarethelistofalltheelementsofanArray:
Property/method Description
length
Thenumberofelementsinthearray:
>[1,2,3,4].length;4
concat(i1,i2,i3,...)
Mergesarraystogether:
>[1,2].concat([3,5],[7,11]);[1,2,3,5,7,11]
join(separator)
Turnsanarrayintoastring.Theseparatorparameterisastringwithcommaasthedefaultvalue:
>[1,2,3].join();"1,2,3">[1,2,3].join('|');"1|2|3">[1,2,3].join('islessthan');"1islessthan2islessthan3"
pop()
Removesthelastelementofthearrayand returnsit:
>vara=['une','deux','trois'];>a.pop();"trois">a; ["une","deux"]
push(i1,i2,i3,...)
Appendselementstotheendofthearrayandreturnsthelengthofthemodifiedarray:
>vara=[];>a.push('zig','zag','zebra','zoo');4
reverse()
Reversestheelementsofthearrayandreturnsthemodifiedarray:
>vara=[1,2,3];>a.reverse();[3,2,1]>a; [3,2,1]
shift()
Likepop()butremovesthefirstelement,notthelast:
>vara=[1,2,3];>a.shift();1>a; [2,3]
![Page 527: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/527.jpg)
slice(start_index,end_index)
Extractsapieceofthearrayandreturnsit asanewarray,withoutmodifyingthesourcearray:
>vara=['apple','banana','js','css','orange'];>a.slice(2,4);["js","css"]>a; ["apple","banana","js","css","orange"]
sort(callback)
Sortsanarray.Optionallyacceptsacallbackfunctionforcustomsorting.Thecallbackfunctionreceivestwoarrayelementsasargumentsandshouldreturn0iftheyareequal,apositivenumberifthefirstisgreater,andanegativenumberifthesecondisgreater.
Anexampleofacustomsortingfunctionthatdoesapropernumericsort(sincethedefaultischaractersorting):
functioncustomSort(a,b){ if(a>b)return1; if(a<b)return-1; return0;}Exampleuseofsort():>vara=[101,99,1,5];>a.sort();[1, 101,5,99]>a.sort(customSort);[1,5,99,101]>[7,6,5,9].sort(customSort);[5,6,7,9]
splice(start,delete_count,i1,i2,i3,...)
Removesandaddselementsatthesametime.Thefirstparameteriswheretostartremoving,thesecondishowmanyitemstoremoveandtherestoftheparametersarenewelementstobeinsertedintheplaceoftheremovedones:
>vara=['apple','banana','js','css','orange'];>a.splice(2,2,'pear','pineapple');["js","css"]>a; ["apple","banana","pear","pineapple","orange"]
unshift(i1,i2,i3,...)
Likepush()butaddstheelementsatthebeginningofthearrayasopposedtotheend.Returnsthelengthofthemodifiedarray:
>vara=[1,2,3];>a.unshift('one','two');5>a; ["one","two",1,2,3]
![Page 528: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/528.jpg)
ECMAScript5additionstoArray
FollowingaretheECMAScript5additionstoArray:
Property/method Description
Array.isArray(obj)
Tellsifanobjectisanarraybecausetypeofisnotgoodenough:
>vararraylike={0:101,length:1};>typeofarraylike;"object">typeof[];"object"
Neitherisduck-typing(ifitwalkslikeaduckandquackslikeaduck,itmustbeaduck):
typeofarraylike.length;"number"
InES3youneedtheverbose:
>Object.prototype.toString.call([])==="[objectArray]";true>Object.prototype.toString.call(arraylike)==="[objectArray]";false
InES5yougettheshorter:
Array.isArray([]);trueArray.isArray(arraylike);false
Array.prototype.indexOf(needle,idx)
Searchesthearrayandreturnstheindexofthefirstmatch.Returns-1ifthere'snomatch.Optionallycansearchstartingfromaspecifiedindex:
>varar=['one','two','one','two'];>ar.indexOf('two');1>ar.indexOf('two',2);3>ar.indexOf('toot');-1
Array.prototype.lastIndexOf(needle,idx)
LikeindexOf()onlysearchesfromtheend:
>varar=['one','two','one','two'];>ar.lastIndexOf('two');3>ar.lastIndexOf('two',2);1>ar.indexOf('toot');-1
![Page 529: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/529.jpg)
Array.prototype.forEach(callback,this_obj)
Analternativetoaforloop.Youspecifyacallbackfunctionthatwillbecalledforeachelementofthe array.Thecallbackfunctiongetsthearguments:theelement,itsindexandthewholearray:
>varlog=console.log.bind(console);>varar=['itsy','bitsy','spider'];>ar.forEach(log);itsy0["itsy","bitsy","spider"]bitsy1["itsy","bitsy","spider"]spider2["itsy","bitsy","spider"]
Optionally,youcanspecifyasecondparameter:theobjecttobeboundtothisinsidethecallbackfunction.Sothisworkstoo:
>ar.forEach(console.log,console);
Array.prototype.every(callback,this_obj)
Youprovideacallbackfunctionthattestseachelementofthearray.YourcallbackisgiventhesameargumentsasforEach()anditmustreturntrueorfalsedependingonwhetherthegivenelementsatisfiesyourtest.
Ifallelementssatisfyyourtest,every()returnstrue.Ifatleastonedoesn't,every()returnsfalse:
> function hasEye(el, idx,ar){returnel.indexOf('i')!==-1;}>['itsy','bitsy','spider'].every(hasEye);true>['eency','weency','spider'].every(hasEye);false
Ifatsomepointduringtheloopitbecomesclearthattheresultwillbefalse,theloopstopsandreturnsfalse:
>[1,2,3].every(function(e){console.log(e);returnfalse;});1false
Array.prototype.some(callback,this_obj)
Likeevery(),onlyitreturnstrueifatleastoneelementsatisfiesyourtest:
>['itsy','bitsy','spider'].some(hasEye);true>['eency','weency','spider'].some(hasEye);true
![Page 530: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/530.jpg)
Array.prototype.filter(callback,this_obj)
Similartosome()andevery()butitreturnsanewarrayofallelementsthatsatisfyyourtest:
>['itsy','bitsy','spider'].filter(hasEye);["itsy","bitsy","spider"]>['eency','weency','spider'].filter(hasEye);["spider"]
Array.prototype.map(callback,this_obj)
SimilartoforEach()becauseitexecutesacallbackforeachelement,butadditionallyitconstructsanewarraywiththereturnedvaluesofyourcallbackandreturnsit.Let'scapitalizeallstringsinanarray:
>functionuc(element,index,array){returnelement.toUpperCase();}>['eency','weency','spider'].map(uc);["EENCY","WEENCY","SPIDER"]
Array.prototype.reduce(callback,start)
Executesyourcallbackforeachelementofthearray.Yourcallbackreturnsavalue.Thisvalueispassedbacktoyourcallbackwiththenextiteration.Thewholearrayiseventuallyreducedtoasinglevalue:
>functionsum(res,element,idx,arr){returnres+element;}>[1,2,3].reduce(sum);6
Optionallyyoucanpassastartvaluewhichwillbeusedbythefirstcallbackcall:
>[1,2,3].reduce(sum,100);106
Array.prototype.reduceRight(callback,start)
Likereduce()butloopsfromtheendofthearray:
>functionconcat(result_so_far,el){
return "" + result_so_far+el;}>[1,2,3].reduce(concat);"123">[1,2,3].reduceRight(concat);"321"
![Page 531: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/531.jpg)
ES6additiontoarrays
Followingaretheadditiontoarrays:
Array.from(arrayLike, mapFunc?,thisArg?)
TheArray.from()method'sbasicfunctionalityistoconverttwokindsofvaluestoarrays-arrayLikevaluesandIterablevalues:
constarrayLike={length:2,0:'a',1:'b'};constarr =Array.from(arrayLike);for(constxofarr){//OK,iterableconsole.log(x);}//Output://a//b
Array.of(...items)
Createsanarrayoutoftheitemspassedtothemethod
leta=Array.of(1,2,3,'foo');console.log(a);//[1,2,3,"foo"]
Array.prototype.entries()
Array.prototype.keys()
Array.prototype.values()
The result of these methods is a sequence of values. These methods returns aniteratorofkeys,valuesandentriesrespectively.
leta=Array.of(1,2,3,'foo');letk,v,e;for(kof a.keys()){
console.log(k); //0 1 2 3}for(vof a.values()){console.log(v);//123foo}for(eof a.entries()){console.log(e);}//[[0,1],[1,2],[2,3][3,'foo']]
Array.prototype.find(predicate,thisArg?)
Returnsthefirstarrayelementforwhichthecallbackfunctionreturnstrue.Ifthereisnosuchelement,itreturnsundefined:
[1,-2,3].find(x=>x<0)//-2
Array.prototype.findIndex(predicate,thisArg?)
Returnstheindexofthefirstelementforwhichthecallbackfunctionreturnstrue.Ifthereisnosuchelement,itreturns-1:
[1, -2, 3].find(x => x < 0)//1
Itfillsanarraywiththegivenvalue:
![Page 532: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/532.jpg)
Array.prototype.fill(value:any,start=0,end=this.length):This
constarr=['a','b','c'];arr.fill(7)[7,7,7]Youcanspecifystartandendranges.['a','b','c'].fill(7,1,2)['a',7,'c' ]
![Page 533: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/533.jpg)
FunctionJavaScript functions are objects. They can be defined using the Function constructor, like so:
varsum=newFunction('a','b','returna+b;');
Thisisa(generallynotrecommended)alternativetothefunctionliteral(alsoknownasfunctionexpression):
varsum=function(a,b){returna+b;};
Or,themorecommonfunctiondefinition:
functionsum(a,b){returna+b;}
![Page 534: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/534.jpg)
TheFunction.prototypemembers
FollowingarethelistofmembersoftheFunctionconstructor:
Property/Method Description
apply(this_obj,params_array)
Allowsyoutocallanotherfunctionwhileoverwritingtheotherfunction'sthisvalue.Thefirstparameterthatapply()acceptsistheobjecttobeboundtothisinsidethefunctionandthesecondisanarrayofargumentstobesenttothefunctionbeingcalled:
functionwhatIsIt(){returnthis.toString();}>varmyObj={};>whatIsIt.apply(myObj);"[objectObject]">whatIsIt.apply(window);
"[object Window]"
call(this_obj,p1,p2,p3,...) Sameasapply()butacceptsargumentsonebyone,asopposedtoasonearray.
length
Thenumberofparametersthefunctionexpects:
>parseInt.length;2
Ifyouforgetthedifferencebetweencall()andapply():
>Function.prototype.call.length;1>Function.prototype.apply.length;2
Thecall() property'slengthis1becauseallargumentsexceptthefirstoneareoptional.
![Page 535: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/535.jpg)
ECMAScript5additionstoaFunction
FollowingaretheECMAScript5additiontoaFunctionconstructor:
Property/method Description
Function.prototype.bind()
Whenyouwanttocallafunctionthatusesthisinternallyandyouwanttodefinewhatthisis.Themethodscall()andapply()invokethefunctionwhilebind()returnsanewfunction.Usefulwhenyouprovideamethodasacallbacktoamethodofanotherobjectandandyouwantthistobeanobjectofyourchoice:
>whatIsIt.apply(window); "[objectWindow]"
![Page 536: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/536.jpg)
ECMAScript6additionstoaFunction
FollowingaretheECMAScript6additiontoaFunctionconstructor:
ArrowFunctions
Anarrowfunctionexpressionhasashortersyntaxcomparedtofunctionexpressionsanddoesnot binditsownthis,arguments,super,ornew.target.Arrowfunctionsarealwaysanonymous.
()=>{...}//noparameterx=>{...}//oneparameter,anidentifier(x,y)=>{...}//severalparametersconstsquares=[1,2,3].map(x=>x*x);
StatementBodiesaremoreexpressiveandconciseclosuresyntax
arr.forEach(v=>{if(v%5===0)filtered:ist.push(v)})
![Page 537: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/537.jpg)
BooleanThe Boolean constructor creates Boolean objects (not to be confused with Boolean primitives).The Boolean objects are not that useful and are listed here for the sake of completeness.
>varb=newBoolean();>b.valueOf();false>b.toString();"false"
ABooleanobjectisnotthesameasaBooleanprimitivevalue.Asyouknow,allobjectsaretruthy:
>b===false;false>typeofb;"object"
Booleanobjectsdon'thaveanypropertiesotherthantheonesinheritedfromObject.
![Page 538: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/538.jpg)
NumberThis creates number objects:
>varn=newNumber(101);>typeofn;"object">n.valueOf();101
TheNumberobjectsarenotprimitiveobjects,butifyouuseanyNumber.prototypemethodonaprimitivenumber,theprimitivewillbeconvertedtoaNumberobjectbehindthescenesandthecodewillwork.
>varn=123;>typeofn;"number">n.toString();"123"
Usedwithoutnew,theNumberconstructorreturnsaprimitivenumber.
>Number("101");101>typeofNumber("101");"number">typeofnewNumber("101");"object"
![Page 539: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/539.jpg)
MembersoftheNumberconstructor
ConsiderthefollowingmembersoftheNumberconstructor:
Property/method Description
Number.MAX_VALUE
Aconstantproperty(cannotbechanged)thatcontainsthemaximumallowednumber:
>Number.MAX_VALUE; 1.7976931348623157e+308
Number.MIN_VALUE
ThesmallestnumberyoucanworkwithinJavaScript:
>Number.MIN_VALUE; 5e-324
Number.NaN
ContainstheNotANumbernumber.SameastheglobalNaN:
>Number.NaN; NaN
NaNisnotequaltoanythingincludingitself:
>Number.NaN===Number.NaN; false
Number.POSITIVE_INFINITY SameastheglobalInfinitynumber.
Number.NEGATIVE_INFINITY Sameas-Infinity.
![Page 540: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/540.jpg)
TheNumber.prototypemembers
FollowingarethemembersoftheNumberconstructor:
Property/method Description
toFixed(fractionDigits)
Returnsastringwiththefixed-pointrepresentationofthenumber.Roundsthereturnedvalue:
>varn=newNumber(Math.PI);>n.valueOf();3.141592653589793>n.toFixed(3);"3.142"
toExponential(fractionDigits)
Returnsastringwithexponentialnotationrepresentationofthenumberobject.Roundsthereturnedvalue:
>varn=newNumber(56789);>n.toExponential(2);"5.68e+4"
toPrecision(precision)
Stringrepresentationofanumberobject,eitherexponentialorfixed-point,dependingonthenumberobject:
>varn=newNumber(56789);>n.toPrecision(2);"5.7e+4">n.toPrecision(5);"56789">n.toPrecision(4);"5.679e+4">varn=newNumber(Math.PI);>n.toPrecision(4);"3.142"
![Page 541: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/541.jpg)
StringThe String() constructor creates string objects. Primitive strings are turned into objects behindthe scenes if you call a method on them as if they were objects. Omitting new gives you primitivestrings.
Creatingastringobjectandastringprimitive:
>vars_obj=newString('potatoes');>vars_prim='potatoes';>typeofs_obj;"object">typeofs_prim;"string"
Theobjectandtheprimitivearenotequalwhencomparedbytypewith===,buttheyarewhencomparedwith==whichdoestypecoercion:
>s_obj===s_prim;false>s_obj==s_prim;true
lengthisapropertyofthestringobjects:
>s_obj.length;8
Ifyouaccesslengthonaprimitivestring,theprimitiveisconvertedtoanobjectbehindthescenesandtheoperation issuccessful:
>s_prim.length;8
Stringliteralsworkfinetoo:
>"giraffe".length;7
![Page 542: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/542.jpg)
MembersoftheStringconstructor
FollowingarethemembersoftheStringconstructor:
Property/method Description
String.fromCharCode(code1,code2,code3,...)
ReturnsastringcreatedusingtheUnicodevaluesoftheinput:
>String.fromCharCode(115,99,114,105,112,116);"script"
![Page 543: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/543.jpg)
TheString.prototypemembers
ConsiderthefollowingString.prototypemembers:
Property/method Description
length
Thenumberofcharactersinthestring:
> newString('four').length;4
charAt(position)
Returnsthecharacteratthespecifiedposition.Positionsstartat0:
> "script".charAt(0);"s"
SinceES5,it'salsopossibletousearraynotationforthesamepurpose.(Thisfeaturehasbeenlongsupported in many browsers before ES5, but not IE):
> "script"[0];"s"
charCodeAt(position)
Returnsthenumericcode(Unicode)ofthecharacteratthespecifiedposition:
> "script".charCodeAt(0);115
concat(str1,str2,....)
Returnsanewstringgluedfromtheinputpieces:
> "".concat('zig','-','zag');"zig-zag"
indexOf(needle,start)
Iftheneedlematchesapartofthestring,thepositionofthematchisreturned.Theoptionalsecondparameterdefineswherethesearchshouldstartfrom.Returns-1ifnomatchisfound:
> "javascript".indexOf('scr');4 > "javascript".indexOf('scr',5);-1
lastIndexOf(needle,start)
Same as indexOf() but starts the search from the end of the string. The last occurrence of a:
> "javascript".lastIndexOf('a');3
localeCompare(needle)
Comparestwostringsinthecurrentlocale.Returns0ifthetwostringsareequal,1iftheneedlegetssortedbeforethestringobject,-1otherwise:
> "script".localeCompare('crypt');1 > "script".localeCompare('sscript');-1> "script".localeCompare('script');0
![Page 544: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/544.jpg)
match(regexp)
Acceptsaregularexpressionobjectandreturnsanarrayofmatches:
> "R2-D2andC-3PO".match(/[0-9]/g);["2","2","3"]
replace(needle,replacement)
Allowsyoutoreplacethematchingresultsofaregexppattern.Thereplacementcanalsobeacallbackfunction.Capturinggroupsareavailableas$1,$2,...$9:
> "R2-D2".replace(/2/g,'-two');"R-two-D-two"> "R2-D2".replace(/(2)/g,'$1$1');"R22-D22"
search(regexp)
Returns the position of the first regular expression match:
> "C-3PO".search(/[0-9]/);2
slice(start,end)
Returnsthepartofastringidentifiedbythestartandendpositions.Ifstartisnegative,thestartpositionislength+start,similarlyiftheendparameterisnegative,theendpositionislength+end:
> "R2-D2andC-3PO".slice(4,13);"2andC-3"> "R2-D2andC-3PO".slice(4,-1);"2andC-3P"
split(separator,limit)
Turnsastringintoanarray.Thesecondparameter,limit,isoptional.Aswithreplace(),search(),andmatch(),theseparatorisaregularexpressionbutcanalsobeastring:
> "1,2,3,4".split(/,/);["1","2","3","4"]> "1,2,3,4".split(',',2);["1","2"]
substring(start,end)
Similartoslice().Whenstartorendarenegativeorinvalid,theyareconsidered0.Iftheyaregreaterthanthestringlength,theyareconsideredtobethelength.Ifendisgreaterthanstart,theirvaluesareswapped.
> "R2-D2andC-3PO".substring(4,13);"2 and C-3"
> "R2-D2andC-3PO".substring(13,4);"2andC-3"
toLowerCase()
toLocaleLowerCase()
Transformsthestringtolowercase:
> "Java".toLowerCase();"java"
toUpperCase()
toLocaleUpperCase()
Transformsthestringtouppercase:
> "Script".toUpperCase();"SCRIPT"
![Page 545: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/545.jpg)
ECMAScript5additionstoString
FollowingaretheECMAScript5additionstoString:
Property/method Description
String.prototype.trim()
Insteadofusingaregularexpressiontoremovewhitespacebeforeandafterastring(asinES3),youhaveatrim()methodinES5.
>"\tbeard\n".trim(); "beard" OrinES3:
> " \t beard \n".replace(/\s/g, ""); "beard"
![Page 546: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/546.jpg)
ECMAScript6additionstoString
FollowingarethelistofalltheECMAScript6additionstoString:
TemplateLiteralsareusedtointerpolatesingleormulti-linestrings.
Templateliteralsareenclosedbytheback-tick(``)(graveaccent)characterinsteadofdoubleorsinglequotes.Templateliteralscancontainplaceholders.TheseareindicatedbytheDollarsignandcurlybraces(${expression}).Theexpressionsintheplaceholdersandthetextbetweenthemgetpassedtoafunction.Thedefaultfunctionjustconcatenatesthepartsintoasinglestring.
vara=5;varb=10;console.log(`Fifteenis${a+b}`);
String.prototype.repeat-thismethodallowsyoutorepeatastringnnumberoftimes"".repeat(4*depth)"foo".repeat(3)
String.prototype.startsWith
String.prototype.endsWith
String.prototype.includes
Thesearenewstringsearchingmethods
"hello".startsWith("ello",1)//true"hello".endsWith("hell",4)//true"hello".includes("ell")//true"hello".includes("ell",1)//true"hello".includes("ell",2)//false
![Page 547: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/547.jpg)
DateThe Date constructor can be used with several types of input:
Youcanpassvaluesforyear,month,dateof themonth,hour,minute,second,andmillisecond,likeso:
>newDate(2015,0,1,13,30,35,505);ThuJan01201513:30:35GMT-0800(PST)
Youcanskipanyoftheinputparameters,inwhichcasetheyareassumedtobe0.Notethatmonthvaluesarefrom0(January)to11(December),hoursarefrom0to23,minutesandseconds0to59,andmilliseconds0to999.Youcanpassatimestamp:
>newDate(1420147835505);ThuJan01201513:30:35GMT-0800(PST)
Ifyoudon'tpassanything,thecurrentdate/timeisassumed:
>newDate();FriJan11201312:20:45GMT-0800(PST)
Ifyoupassastring, it'sparsedinanattempttoextractapossibledatevalue:
>newDate('May4,2015');MonMay04201500:00:00GMT-0700(PDT)
Omittingnewgivesyouastringversionofthecurrentdate:
>Date()===newDate().toString();true
![Page 548: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/548.jpg)
MembersoftheDateconstructor
FollowingarethemembersoftheDateconstructor:
Property/method Description
Date.parse(string)
SimilartopassingastringtonewDate()constructor,thismethodparsestheinputstringinattempttoextractavaliddatevalue.Returnsatimestamponsuccess,NaNonfailure:
>Date.parse('May5, 2015');1430809200000>Date.parse('4th');
NaN
Date.UTC(year,month,date,hours,minutes,seconds,ms)
ReturnsatimestampbutinUTC(CoordinatedUniversalTime),notinlocaltime.
>Date.UTC(2015,0,1,13,30, 35,505);1420119035505
![Page 549: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/549.jpg)
TheDate.prototypemembers
FollowingarethelistofDate.prototypemembers:
Property/method Description/example
toUTCString()
SameastoString()butinuniversaltime.Here'showPacificStandard(PST)localtimediffersfromUTC:
>vard=newDate(2015,0,1);>d.toString();"ThuJan01201500:00:00GMT-0800(PST)">d.toUTCString();"Thu,01Jan201508:00:00GMT"
toDateString()
ReturnsonlythedateportionoftoString():
>newDate(2015,0,1).toDateString();"ThuJan012010"
toTimeString()
ReturnsonlythetimeportionoftoString():
>newDate(2015,0,1).toTimeString();"00:00:00GMT-0800(PST)"
toLocaleString()
toLocaleDateString()
toLocaleTimeString()
EquivalenttotoString(),toDateString(),andtoTimeString()respectively,butinafriendlierformat, according to the current user's locale:
>newDate(2015,0,1).toString();"ThuJan01201500:00:00GMT-0800(PST)">newDate(2015,0,1).toLocaleString();"1/1/201512:00:00AM"
getTime()
setTime(time)
Getorsetthetime(usingatimestamp)ofadateobject.Thefollowingexamplecreatesadateandmovesitonedayforward:
>vard=newDate(2015,0,1);>d.getTime();1420099200000>d.setTime(d.getTime()+ 1000*60*60*24);1420185600000
> d.toLocaleString();"FriJan02201500:00:00 GMT-0800(PST)"
getFullYear()
getUTCFullYear()
setFullYear(year,month,date)
setUTCFullYear(year,month,date)
GetorsetafullyearusinglocalorUTCtime.ThereisalsogetYear()butitisnotY2Kcompliant,souse getFullYear() instead:
>vard=newDate(2015,0,1);>d.getYear();115>d.getFullYear();2015>d.setFullYear(2020);1577865600000>d;
![Page 550: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/550.jpg)
WedJan01202000:00:00GMT-0800 (PST)
getMonth()
getUTCMonth()
setMonth(month,date)
setUTCMonth(month,date)
Getorsetmonth,startingfrom0(January):
>vard=newDate(2015,0,1);>d.getMonth();0>d.setMonth(11);1448956800000>d.toLocaleDateString();"12/1/2015"
getDate()
getUTCDate()
setDate(date)
setUTCDate(date)
Getorsetdateofthemonth.
>vard=newDate(2015,0,1);>d.toLocaleDateString();"1/1/2015">d.getDate();1>d.setDate(31);1422691200000>d.toLocaleDateString();"1/31/2015"
getHours()
getUTCHours()
setHours(hour,min,sec,ms)
setUTCHours(hour,min,sec,ms)
getMinutes()
getUTCMinutes()
setMinutes(min,sec,ms)
setUTCMinutes(min,sec,ms)
getSeconds()
getUTCSeconds()
setSeconds(sec,ms)
setUTCSeconds(sec,ms)
getMilliseconds()
getUTCMilliseconds()
setMilliseconds(ms)
setUTCMilliseconds(ms)
Get/Sethour,minutes,seconds,milliseconds,allstartingfrom0:
>vard=newDate(2015,0,1);> d.getHours() + ':' + d.getMinutes();
"0:0">d.setMinutes(59);1420102740000>d.getHours()+':'+d.getMinutes();"0:59"
Returnsthedifferencebetweenlocalanduniversal(UTC)time,measuredinminutes.ForexamplethedifferencebetweenPST(PacificStandardTime)andUTC:
>newDate().getTimezoneOffset();
![Page 551: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/551.jpg)
getTimezoneOffset() 480>420/60;//hours8
getDay()
getUTCDay()
Returns the day of the week, starting from 0 (Sunday):
>vard=newDate(2015,0,1);>d.toDateString();"ThuJan012015">d.getDay();4>vard=newDate(2015,0,4);>d.toDateString();"SatJan042015">d.getDay();0
![Page 552: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/552.jpg)
ECMAScript5additionstoDate
FollowingaretheadditionstotheDateconstructor:
Property/method Description
Date.now()
Aconvenientwaytogetthecurrenttimestamp:
>Date.now()===newDate().getTime();true
Date.prototype.toISOString()
YetanothertoString():
>vard=newDate(2015,0,1);>d.toString();"ThuJan01201500:00:00GMT-0800(PST)">d.toUTCString();"Thu,01Jan201508:00:00GMT">d.toISOString();"2015-01-01T00:00:00.000Z"
Date.prototype.toJSON()
UsedbyJSON.stringify()(refertotheendofthisappendix)andreturnsthesameastoISOString():
>vard=newDate();>d.toJSON()===d.toISOString();true
![Page 553: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/553.jpg)
MathMath is a different from the other built-in objects because it cannot be used as a constructor tocreate objects. It's just a collection of static functions and constants. Some examples to illustratethedifferenceareasfollows:
>typeofDate.prototype;"object">typeofMath.prototype;"undefined">typeofString;"function">typeofMath;"object"
![Page 554: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/554.jpg)
MembersoftheMathobject
FollowingarethemembersoftheMathobject:
Property/method Description
Math.E
Math.LN10
Math.LN2
Math.LOG2E
Math.LOG10E
Math.PI
Math.SQRT1_2
Math.SQRT2
Thesearesomeusefulmathconstants,allread-only.Herearetheirvalues:
>Math.E;2.718281828459045>Math.LN10;2.302585092994046>Math.LN2;0.6931471805599453
> Math.LOG2E;1.4426950408889634>Math.LOG10E;0.4342944819032518>Math.PI;3.141592653589793>Math.SQRT1_2;0.7071067811865476>Math.SQRT2;1.4142135623730951
Math.acos(x)
Math.asin(x)
Math.atan(x)
Math.atan2(y,x)
Math.cos(x)
Math.sin(x)
Math.tan(x)
Trigonometricfunctions
Math.round(x)
Math.floor(x)
Math.ceil(x)
round()givesyouthenearestinteger,ceil()roundsup,andfloor()roundsdown:
>Math.round(5.5);6>Math.floor(5.5);5>Math.ceil(5.1);
6
Math.max(num1,num2,num3,...)
Math.min(num1,num2,num3,...)
max()returnsthelargestandmin()returnsthesmallestofthenumberspassedtothemasarguments.IfatleastoneoftheinputparametersisNaN,theresultisalsoNaN:
>Math.max(4.5,101,Math.PI);101>Math.min(4.5,101,Math.PI);3.141592653589793
Absolutevalue:
>Math.abs(-101);
![Page 555: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/555.jpg)
Math.abs(x) 101>Math.abs(101);101
Math.exp(x)
Exponentialfunction:Math.Etothepowerofx:
>Math.exp(1)===Math.E;true
Math.log(x)
Naturallogarithmofx:
>Math.log(10)===Math.LN10;true
Math.sqrt(x)
Squarerootofx:
>Math.sqrt(9);3>Math.sqrt(2)===Math.SQRT2;true
Math.pow(x,y)
xtothepowerofy:
>Math.pow(3,2);9
Math.random()
Randomnumberbetween0and1(including0).
>Math.random();0.8279076443185321
For an random integer in a range,saybetween10and100:>Math.round(Math.random()*90+10);79
![Page 556: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/556.jpg)
RegExpYou can create a regular expression object using the RegExp() constructor. You pass theexpression pattern as the first parameter and the pattern modifiers as the second:
>varre=newRegExp('[dn]o+dle','gmi');
Thismatches"noodle","doodle","doooodle",andsoon.It'sequivalenttousingtheregularexpressionliteral:
>varre=('/[dn]o+dle/gmi');//recommended
Chapter4,ObjectsandAppendixD,RegularExpressionscontainmoreinformationonregularexpressionsandpatterns.
![Page 557: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/557.jpg)
TheRegExp.prototypemembers
FollowingaretheRegExp.prototypemembers:
Property/method Description
global Read-onlytrueifthegmodifierwassetwhencreatingtheregexpobject.
ignoreCase Read-only.trueiftheimodifierwassetwhencreatingtheregexpobject.
multiline Read-only.trueifthemmodifierwassetwhencreatingtheregexpobject
lastIndex
Containsthepositioninthestringwherethenextmatchshouldstart.test()andexec()setthispositionafterasuccessful match.Onlyrelevantwhentheg(global)modifierwasused:
>varre=/[dn]o+dle/g;>re.lastIndex;0>re.exec("noodledoodle");["noodle"]>re.lastIndex;6>re.exec("noodledoodle");["doodle"]>re.lastIndex;13>re.exec("noodledoodle");null>re.lastIndex;0
source
Read-only.Returnstheregularexpressionpattern(withoutthemodifiers):
>varre=/[nd]o+dle/gmi;>re.source;"[nd]o+dle"
exec(string)
Matchestheinputstringwiththeregularexpression.Onasuccessfulmatchreturnsanarraycontainingthematchandanycapturinggroups.Withthegmodifier,itmatchesthefirstoccurrenceandsetsthelastIndexproperty. Returns null when there's no match:
>varre=/([dn])(o+)dle/g;>re.exec("noodledoodle");["noodle","n","oo"]>re.exec("noodledoodle");["doodle","d","oo"]
Thearraysreturnedbyexec()havetwoadditionalproperties:index(ofthematch)andinput(theinputstringbeingsearched).
test(string)
Sameasexec()butonlyreturnstrueorfalse:
>/noo/.test('Noodle');false>/noo/i.test('Noodle');true
![Page 558: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/558.jpg)
![Page 559: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/559.jpg)
Error objectsError objects are created either by the environment (the browser) or by your code:
>vare=newError('jaavcsritpis_not_howyouspellit');>typeofe;"object"
OtherthantheErrorconstructor,sixadditionalonesexistandtheyallinheritError:
EvalErrorRangeErrorReferenceErrorSyntaxErrorTypeErrorURIError
![Page 560: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/560.jpg)
TheError.prototypemembers
FollowingaretheError.prototypemembers:
Property Description
name
Thenameoftheerrorconstructorusedtocreatetheobject:
>vare=newEvalError('Oops');>e.name;"EvalError"
message
Additionalerrorinformation:
>vare=newError('Oops...again');>e.message;"Oops...again"
![Page 561: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/561.jpg)
JSONThe JSON object is new to ES5. It's not a constructor (similarly to Math) and has only twomethods: parse() and stringify(). For ES3 browsers that don't support JSON natively, youcan use the "shim" from http://json.org.
JSONstandsforJavaScriptObjectNotation.It'salightweightdatainterchangeformat.It'sasubsetofJavaScriptthatonlysupportsprimitives,objectliterals,andarrayliterals.
![Page 562: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/562.jpg)
MembersoftheJSONobject
FollowingarethemembersoftheJSONobject:
Method Description
parse(text,callback)
TakesaJSON-encodedstringandreturnsanobject:
>vardata='{"hello":1,"hi":[1,2,3]}';>varo=JSON.parse(data);>o.hello;1>o.hi;[1,2,3]
Theoptionalcallbackletsyouprovideyourownfunctionthatcaninspectandmodifytheresult.Thecallbacktakeskeyandvalueargumentsandcanmodifythevalueordeleteit(byreturningundefined).
>functioncallback(key,value){console.log(key,value);if(key==='hello'){return'bonjour';}if(key==='hi'){
return undefined;}returnvalue;}>varo=JSON.parse(data,callback);hello1011223hi[1,2,3]Object{hello:"bonjour"}>o.hello;"bonjour">'hi'ino;false
stringify(value,callback,white)
Takesanyvalue(mostcommonlyanobjectoranarray)andencodesittoaJSONstring.
>varo={hello:1,hi:2,when:newDate(2015,0,1)};>JSON.stringify(o);"{"hello":1,"hi":2,"when":"2015-01-01T08:00:00.000Z"}"
Thesecondparameterletsyouprovideacallback(orawhitelistarray)tocustomizethereturnvalue.Thewhitelistcontainsthekeysyou'reinterestedin:
JSON.stringify(o,['hello','hi']);"{"hello":1,"hi":2}"
Thelastparameterhelpsyougetahuman-readableversion.Youspecifythenumberofspacesasastringoranumber:
>JSON.stringify(o,null,4);
![Page 563: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/563.jpg)
"{"hello":1,"hi":2,"when":"2015-01-01T08:00:00.000Z"}"
![Page 564: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/564.jpg)
Appendix D. Regular ExpressionsWhen you use regular expressions (discussed in Chapter 4, Objects), you can match literalstrings,forexample:
>"sometext".match(/me/);["me"]
However,thetruepowerofregularexpressionscomesfrommatchingpatterns,notliteralstrings.Thefollowingtabledescribesthedifferentsyntaxyoucanuseinyourpatterns,andprovidessomeexamplesoftheiruse:
Pattern Description
[abc]
Matchesaclassofcharacters:
>"sometext".match(/[otx]/g);["o","t","x","t"]
[a-z]
Aclassofcharactersdefinedasarange.Forexample,[a-d]isthesameas[abcd],[a-z]matchesalllowercasecharacters,[a-zA-Z0-9_]matchesallcharacters,numbers,andtheunderscorecharacter:
>"SomeText".match(/[a-z]/g);["o","m","e","e","x","t"]>"SomeText".match(/[a-zA-Z]/g);
["S", "o", "m", "e", "T", "e", "x", "t"]
[^abc]
Matcheseverythingthatisnotmatchedbytheclassofcharacters:
>"SomeText".match(/[^a-z]/g);["S","","T"]
a|b
Matchesaorb.ThepipecharactermeansOR,anditcanbeusedmorethanonce:
>"SomeText".match(/t|T/g);["T","t"]>"SomeText".match(/t|T|Some/g);["Some","T","t"]
a(?=b)
Matchesaonlyiffollowedbyb:
>"SomeText".match(/Some(?=Tex)/g);null>"SomeText".match(/Some(?=Tex)/g);["Some"]
a(?!b)
Matchesaonlywhennotfollowedbyb:
>"SomeText".match(/Some(?!Tex)/g);null>"SomeText".match(/Some(?!Tex)/g);["Some"]
![Page 565: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/565.jpg)
\
Escapecharacterusedtohelpyoumatchthespecialcharactersusedinpatternsasliterals:
>"R2-D2".match(/[2-3]/g);["2","2"] >"R2-D2".match(/[2\-3]/g);["2","-","2"]
\n
\r
\f
\t
\v
Newline
Carriagereturn
Formfeed
Tab
Verticaltab
\s
Whitespace,oranyofthepreviousfiveescapesequences:
>"R2\nD2".match(/\s/g);["\n", " "]
\S
Oppositeoftheabove;matcheseverythingbutwhitespace.Sameas[ \̂s]:
>"R2\nD2".match(/\S/g);["R","2","D","2"]
\w
Anyletter,number,orunderscore.Sameas[A-Za-z0-9_]:
>"S0m3text!".match(/\w/g);["S","0","m","3","t","e","x","t"]
\W
Oppositeof\w:
>"S0m3text!".match(/\W/g);["","!"]
\d
Matchesanumber,sameas[0-9]:
>"R2-D2andC-3PO".match(/\d/g);["2","2","3"]
\D
Oppositeof\d;matchesnon-numbers,sameas[^0-9]or[ \̂d]:
>"R2-D2andC-3PO".match(/\D/g);["R","-","D","","a","n","d","","C", "-","P","O"]
\b
Matchesawordboundarysuchasspaceorpunctuation.
MatchingRorDfollowedby2:
> "R2D2 and C-3PO".match(/[RD]2/g);["R2","D2"]
Sameasabovebutonlyattheendofaword:
![Page 566: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/566.jpg)
>"R2D2and C-3PO".match(/[RD]2\b/g);["D2"]
Samepatternbuttheinputhasadash,whichisalsoanendofaword:
>"R2-D2andC-3PO".match(/[RD]2\b/g);["R2","D2"]
\B
Theoppositeof\b:
>"R2-D2andC-3PO".match(/[RD]2\B/g);null>"R2D2and C-3PO".match(/[RD]2\B/g);["R2"]
[\b] Matchesthebackspacecharacter.
\0 Thenullcharacter.
\u0000
MatchesaUnicodecharacter,representedbyafour-digithexadecimalnumber:
>"стоян".match(/\u0441\u0442\u043E/);["сто"]
\x00
Matchesacharactercoderepresentedbyatwo-digithexadecimalnumber:
>"\x64";"d">"dude".match(/\x64/g);["d","d"]
^
Thebeginningofthestringtobematched.Ifyousetthemmodifier(multi-line),itmatchesthebeginningofeachline:
>"regular\nregular\nexpression".match(/r/g);["r","r","r","r","r"]>"regular\nregular\nexpression".match(/^r/g);["r"]>"regular\nregular\nexpression".match(/^r/mg);["r","r"]
$
Matchestheendoftheinputor,whenusingthemultilinemodifier,theendofeachline:
>"regular\nregular\nexpression".match(/r$/g);null>"regular\nregular\nexpression".match(/r$/mg);["r","r"]
.
Matchesanysinglecharacterexceptforthenewlineandthelinefeed:
>"regular".match(/r./g);["re"]>"regular".match(/r.../g);["regu"]
![Page 567: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/567.jpg)
*
Matchestheprecedingpatternifitoccurszeroormoretimes.Forexample,/.*/willmatchanythingincludingnothing(anempty input):
>"".match(/.*/);[""]>"anything".match(/.*/);["anything"]>"anything".match(/n.*h/);["nyth"]
Keepinmindthatthepatternis"greedy",meaningitwillmatchasmuchaspossible:
>"anything within".match(/n.*h/g);["nythingwith"]
?
Matchestheprecedingpatternifitoccurszerooronetimes:
>"anything".match(/ny?/g);["ny","n"]
+
Matchestheprecedingpatternifitoccursatleastonce(ormoretimes):
>"anything".match(/ny+/g);["ny"]>"R2-D2andC-3PO".match(/[a-z]/gi);["R","D","a","n","d","C","P","O"]>"R2-D2andC-3PO".match(/[a-z]+/gi);["R","D","and","C","PO"]
{n}
Matchestheprecedingpatternifitoccursexactlyntimes:
>"regularexpression".match(/s/g);["s","s"] >"regularexpression".match(/s{2}/g);["ss"]>"regularexpression".match(/\b\w{3}/g);["reg","exp"]
{min,max}
Matchestheprecedingpatternifitoccursbetweenminandmaxnumberoftimes.Youcanomitmax,whichwillmeannomaximum,butonlyaminimum.Youcannotomitmin.
Anexamplewheretheinputis"doodle"withthe"o"repeated10times:
>"doooooooooodle".match(/o/g);["o","o","o","o","o","o","o","o","o","o"]>"doooooooooodle".match(/o/g).length;10>"doooooooooodle".match(/o{2}/g);["oo","oo","oo","oo","oo"]>"doooooooooodle".match(/o{2,}/g);["oooooooooo"]>"doooooooooodle".match(/o{2,6}/g);["oooooo","oooo"]
Whenthepatternisinparentheses,itisrememberedsothatitcanbeusedforreplacements.Thesearealsoknownascapturingpatterns.
Thecapturedmatchesareavailableas$1,$2,...$9
Matchingall"r"occurrencesandrepeatingthem:
![Page 568: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/568.jpg)
(pattern) >"regularexpression".replace(/(r)/g,'$1$1');"rregularrexprression"
Matching"re"andturningitto"er":
>"regularexpression".replace(/(r)(e)/g,'$2$1');"ergularexperssion"
(?:pattern)
Non-capturingpattern,notrememberedandnotavailablein$1,$2...
Here'sanexampleofhow"re"ismatched,butthe"r"isnotrememberedandthesecondpatternbecomes$1:
>"regularexpression".replace(/(?:r)(e)/g,'$1$1');"eegularexpeession"
Makesureyoupayattentionwhenaspecialcharactercanhavetwomeanings,asisthecasewith^,?,and\b.
![Page 569: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/569.jpg)
Appendix E. Answers to Exercise QuestionsThis appendix lists possible answers to the exercises at the end of the chapters. Possible answersmeaningtheyarenottheonlyones,sodon'tworryifyoursolutionisdifferent.
Aswiththerestofthebook,youshouldtrytheminyourconsoleandplayaroundabit.
Thefirstandthelastchaptersdon'thavetheExercisessection,solet'sstartwithChapter2,PrimitiveDataTypes,Arrays,Loops,andConditions.
![Page 570: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/570.jpg)
Chapter 2, Primitive Data Types, Arrays,Loops,andConditionsLetstryandsolvethefollowingexercises:
![Page 571: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/571.jpg)
Exercises1. Theresultwillbeasfollows:
>vara;typeofa;"undefined"
Whenyoudeclareavariablebutdonotinitializeitwithavalue,itautomaticallygetstheundefinedvalue.Youcanalsocheck:
>a===undefined;true
Thevalueofvwillbe:
>vars='1s';s++;NaN
Adding 1 to the string '1s' returns the string '1s1', which is Not A Number, but the ++operator should return a number; so it returns the special NaN number.
Theprogramisasfollows:
>!!"false";true
Thetrickypartofthequestionisthat"false"isastringandallstringsaretruewhencasttoBooleans(excepttheemptystring"").Ifthequestionwasn'taboutthestring"false"buttheBooleanfalseinstead,thedoublenegation!!returnsthesameBoolean:
>!!false;false
Asyou'dexpect,singlenegationreturnstheopposite:
>!false;true>!true;false
YoucantestwithanystringanditwillcasttoaBooleantrue,excepttheemptystring:
>!!"hello";true>!!"0";true>!!"";false
Theoutputafterexecutingundefinedisasfollows:
![Page 572: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/572.jpg)
>!!undefined;false
Hereundefinedis oneofthefalsyvaluesanditcaststofalse.Youcantrywithanyoftheotherfalsyvalues,suchtheemptystring""inthepreviousexample,NaN,or0.
> typeof -Infinity;"number"
Thenumbertypeincludesallnumbers,NaN,positiveandnegativeInfinity.
Theoutputafterexecutingthefollowingis:
>10%"0";NaN
Thestring"0"iscasttothenumber0.Divisionby0isInfinity,whichhasnoremainder.
Theoutputafterexecutingthefollowingis:
>undefined==null;true
Comparison with == operator doesn't check the types, but converts the operands; in this caseboth are falsy values. Strict comparison checks the types too:
>undefined===null;false
Thefollowingisthecodelineanditsoutput:
>false==="";false
Strictcomparisonbetweendifferenttypes(inthiscaseBooleanandstring)isdoomedtofail,nomatterwhat thevaluesare.
Thefollowingisthecodelineanditsoutput:
>typeof"2E+2";"string"
Anythinginquotesisastring,eventhough:
>2E+2;200>typeof2E+2;"number"
Thefollowingisthecodelineanditsoutput:
![Page 573: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/573.jpg)
>a=3e+3;a++;3000
3e+3is3withthreezeroes,meaning3000.Then++isapost-increment,meaningitreturnstheoldvalueandthenitincrementsitandassignsittoa.That'swhyyougetthereturnvalue3000intheconsole,althoughaisnow3001:
> a;3001
2. Thevalueofvafterexecutingthefollowingis:
>varv=v||10;>v;10
Ifvhasneverbeendeclared,it'sundefinedsothisisthesameas:
>varv=undefined||10;>v;10
However,ifvhasalreadybeendefinedandinitializedwithanon-falsyvalue,you'llgetthepreviousvalue.
>varv=100;>varv=v||10;>v;100
Theseconduseofvardoesn't"reset"thevariable.
Ifvwasalreadyafalsyvalue(nota100),thecheckv||10willreturn10.
>varv=0;> var v = v || 10;
>v;10
3. Forprintingmultiplicationtables,performthefollowing:
for(vari=1;i<=12;i++){for(varj=1;j<=12;j++){console.log(i+'*'+j+'='+i*j);}}
Or:
vari=1,j=1;while(i<=12){
while (j <= 12) {
![Page 574: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/574.jpg)
console.log(i+'*'+j+'='+i*j);j++;}i++;j=1;}
![Page 575: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/575.jpg)
Chapter 3, FunctionsLets do the following exercises:
![Page 576: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/576.jpg)
Exercises1. ToconvertHexcolorstoRGB,performthefollowing:
functiongetRGB(hex){return"rgb("+parseInt(hex[1]+hex[2],16)+","+parseInt(hex[3]+hex[4],16)+","+parseInt(hex[5]+hex[6],16)+")";}Testing:>getRGB("#00ff00");"rgb(0,255,0)">getRGB("#badfad");"rgb(186,223,173)"
One problemwith this solution is that array access to strings like hex[0] is not inECMAScript 3, although many browsers have supported it for a long time and is nowdescribedinES5.
However,Butatthispointinthebook,therewasasyetnodiscussionofobjectsandmethods.OtherwiseanES3-compatiblesolutionwouldbetouseoneofthestringmethods,suchascharAt(),substring(),orslice().Youcanalsouseanarraytoavoidtoomuchstringconcatenation:
function getRGB2(hex) {varresult=[];result.push(parseInt(hex.slice(1,3),16));result.push(parseInt(hex.slice(3,5),16));result.push(parseInt(hex.slice(5),16));return"rgb("+result.join(",")+")";}
Bonusexercise:Rewritetheprecedingfunctionusingaloopsoyoudon'thavetotypeparseInt()threetimes,butjustonce.
2. Theresultisasfollows:
>parseInt(1e1);10Here,you'reparsingsomethingthatisalreadyaninteger:>parseInt(10);10>1e1;10
Here,theparsingofastringgivesuponthefirstnon-integervalue.parseInt()doesn'tunderstandexponentialliterals,itexpectsintegernotation:
>parseInt('1e1');1
![Page 577: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/577.jpg)
Thisisparsingthestring'1e1'whileexpectingittobeindecimalnotation,includingexponential:
>parseFloat('1e1');10
Thefollowingisthecodelineanditsoutput:
>isFinite(0/10);true
Because0/10is0and0isfinite.
Thefollowingisthecodelineanditsoutput:
>isFinite(20/0);false
Becausedivisionby0isInfinity:
>20/0;Infinity
Thefollowingisthecodelineanditsoutput:
>isNaN(parseInt(NaN));true
ParsingthespecialNaNvalueisNaN.3. Whatistheresultof:
vara=1;functionf(){functionn(){alert(a);}vara=2;n();}f();
Thissnippetalerts2eventhoughn()wasdefinedbeforetheassignment,a=2.Insidethefunctionn()youseethevariableathatisinthesamescope,andyouaccessitsmostrecentvalueatthetimeinvocationoff()(andhencen()).Duetohoistingf()actsasifitwas:
functionf(){vara;functionn(){alert(a);}a=2;
![Page 578: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/578.jpg)
n();}
Moreinterestingly,considerthiscode:
vara=1;functionf(){functionn(){alert(a);
}n();vara=2;n();}f();
Italertsundefinedandthen2.Youmightexpectthefirstalerttosay1,butagainduetovariablehoisting,thedeclaration(notinitialization)ofaismovedtothetopofthefunction.Asiff()was:
var a = 1;functionf(){vara;//aisnowundefinedfunctionn(){alert(a);}n();//alertundefineda=2;n();//alert2}f();
Thelocala"shadows"theglobala,evenifit'satthebottom.4. Whyallthesealert"Boo!"
ThefollowingistheresultofExample1:
varf=alert;eval('f("Boo!")');
ThefollowingistheresultofExample2.Youcanassignafunctiontoadifferentvariable.Sof()pointstoalert().Evaluatingthisstringislikedoing:
>f("Boo");
Thefollowingistheoutputafterweexecute eval():
vare;varf=alert;eval('e=f')('Boo!');
![Page 579: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/579.jpg)
ThefollowingistheoutputofExample3.eval()returnstheresultontheevaluation.Inthiscaseit'sanassignmente=fthatalsoreturnsthenewvalueofe.Likethefollowing:
>vara=1;>varb;>varc=(b=a);>c;1
Soeval('e=f')givesyouapointertoalert()thatisexecutedimmediatelywith"Boo!".
Theimmediate(self-invoking)anonymousfunctionreturnsapointertothefunctionalert(),whichisalsoimmediatelyinvokedwithaparameter"Boo!":
(function(){returnalert;})()('Boo!');
![Page 580: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/580.jpg)
Chapter 4, ObjectsLets solve the following exercises:
![Page 581: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/581.jpg)
Exercises1. Whathappenshere?Whatisthisandwhat'so?
functionF(){functionC(){returnthis;}returnC();}varo=newF();
Here, this === window because C() was called without new.
Alsoo===windowbecausenewF()returnstheobjectreturnedbyC(),whichisthis,andthisiswindow.
YoucanmakethecalltoC()aconstructorcall:
function F() {functionC(){returnthis;}returnnewC();}varo=newF();
Here,thisistheobjectcreatedbytheC()constructor.Soiso:
>o.constructor.name;"C"
ItbecomesmoreinterestingwithES5'sstrictmode.Inthestrictmode,non-constructorinvocationsresultinthisbeingundefined,nottheglobalobject.With"usestrict"insideF()orC()constructor'sbody,thiswouldbeundefinedinC().Therefore,returnC()cannotreturnthenon-objectundefined(becauseallconstructorinvocationsreturnsomesortofobject)andreturnsFinstances' this(whichisintheclosurescope).Tryit:
functionF(){"usestrict";this.name="IamF()";functionC(){console.log(this);//undefinedreturnthis;}
return C();}
Testing:
![Page 582: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/582.jpg)
>varo=newF();>o.name;"IamF()"
2. Whathappenswheninvokingthisconstructorwithnew?
functionC(){this.a=1;returnfalse;}Andtesting:>typeofnewC();"object">newC().a;1
newC()isanobject,notBoolean,becauseconstructorinvocationsalwaysproduceanobject.It'sthethisobjectyougetunlessyoureturnsomeotherobjectinyourconstructor.Returningnon-objectsdoesn'tworkandyoustillgetthis.
3. Whatdoesthisdo?
>varc=[1,2,[1,2]];>c.sort();>c;[1,Array[2],2]
Thisisbecausesort()comparesstrings.[1,2].toString()is"1,2",soitcomesafter"1"andbefore"2".
Thesamethingwithjoin():
>c.join('--');>c;"1--1,2--2"
4. PretendString()doesn'texistandcreateMyString()mimickingString().Treattheinputprimitivestringsasarrays(arrayaccessofficiallysupportedinES5).
Here'sasampleimplementationwithjustthemethodstheexerciseaskedfor.Feelfreetocontinuewiththerestofthemethods.RefertoAppendixC,Built-inObjectsforthefulllist.
functionMyString(input){varindex=0;//casttostringthis._value=''+input;//setallnumericpropertiesforarrayaccesswhile(input[index]!==undefined){this[index]=input[index];index++;
![Page 583: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/583.jpg)
}//rememberthelengththis.length=index;}MyString.prototype={constructor:MyString,valueOf:functionvalueOf(){returnthis._value;},toString:functiontoString(){returnthis.valueOf();},charAt:functioncharAt(index){returnthis[parseInt(index,10)||0];},concat:functionconcat(){varprim=this.valueOf();for(vari=0,len=arguments.length;i<len;i++){prim+=arguments[i];
}returnprim;},slice:functionslice(from,to){varresult='',original=this.valueOf();if(from===undefined){returnoriginal;}if(from>this.length){returnresult;}if(from<0){from=this.length-from;}if(to===undefined||to>this.length){to=this.length;}if(to<0){to=this.length+to;}//endofvalidation,actualslicingloopnowfor(vari=from;i<to;i++){result+=original[i];}
return result;},split:functionsplit(re){varindex=0,result=[],original=this.valueOf(),match,
![Page 584: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/584.jpg)
pattern='',modifiers='g';if(reinstanceofRegExp){//splitwithregexpbutalwaysset"g"pattern=re.source;modifiers+=re.multiline?'m':'';modifiers+=re.ignoreCase?'i':'';}else{//notaregexp,probablyastring,we'llconvertitpattern=re;}re=RegExp(pattern,modifiers);while(match=re.exec(original)){result.push(this.slice(index,match.index));index=match.index+newMyString(match[0]).length;}result.push(this.slice(index));returnresult;}
};
Testing:
>vars=newMyString('hello');>s.length;5>s[0];"h">s.toString();"hello">s.valueOf();"hello"
> s.charAt(1);"e">s.charAt('2');"l">s.charAt('e');"h">s.concat('world!');"helloworld!">s.slice(1,3);"el">s.slice(0,-1);"hell">s.split('e');["h","llo"]>s.split('l');["he","","o"]
Feelfreetoplaysplittingwitharegularexpression.5. UpdateMyString()withareverse()method:
![Page 585: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/585.jpg)
>MyString.prototype.reverse=functionreverse(){returnthis.valueOf().split("").reverse().join("");};>newMyString("pudding").reverse();"gniddup"
6. ImagineArray()isgoneandtheworldneedsyoutoimplementMyArray().Hereareahandfulofmethodstogetyoustarted:
functionMyArray(length){//singlenumericargumentmeanslengthif(typeoflength==='number'&&arguments[1]===undefined){this.length=length;returnthis;}//usualcasethis.length=arguments.length;for(vari=0,len=arguments.length;i<len;i++){this[i]=arguments[i];}returnthis;//laterinthebookyou'lllearnhowtosupport
// a non-constructor invocation too}MyArray.prototype={constructor:MyArray,join:functionjoin(glue){varresult='';if(glue===undefined){glue=',';}for(vari=0;i<this.length-1;i++){result+=this[i]===undefined?'':this[i];result+=glue;}result+=this[i]===undefined?'':this[i];returnresult;},toString:functiontoString(){returnthis.join();},push:functionpush(){for(vari=0,len=arguments.length;i<len;i++){this[this.length+i]=arguments[i];}this.length+=arguments.length;
return this.length;},pop:functionpop(){
![Page 586: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/586.jpg)
varpoppd=this[this.length-1];deletethis[this.length-1];this.length--;returnpoppd;}};
Testing:
> var a = new MyArray(1, 2, 3, "test");>a.toString();"1,2,3,test">a.length;4>a[a.length-1];"test">a.push('boo');5>a.toString();"1,2,3,test,boo">a.pop();"boo">a.toString();"1,2,3,test">a.join(',');"1,2,3,test">a.join('isn't');"1isn't2isn't3isn'ttest"
Ifyoufoundthisexerciseamusing,don'tstopwithjoin();goonwithasmanymethodsaspossible.
7. CreateMyMathobjectthatalsohasrand(),min([]),max([]).
ThepointhereisthatMathisnotaconstructor,butanobjectthathassome"static"propertiesandmethods.Belowaresomemethodstogetyoustarted.
Let's also use an immediate function to keep some private utility functions. You can also takethisapproachwithMyStringabove,wherethis._valuecouldbereallyprivate.
varMyMath=(function(){functionisArray(ar){returnObject.prototype.toString.call(ar)==='[objectArray]';}functionsort(numbers){//notusingnumbers.sort()directlybecause//`arguments`isnotanarrayanddoesn'thavesort()returnArray.prototype.sort.call(numbers,function(a,b){
![Page 587: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/587.jpg)
if(a===b){return0;}return1*(a>b)-0.5;//returns0.5or-0.5});}return{PI:3.141592653589793,E:2.718281828459045,LN10:2.302585092994046,LN2:0.6931471805599453,//...moreconstantsmax:functionmax(){//allowunlimitednumberofarguments//oranarrayofnumbersasfirstargumentvarnumbers=arguments;if(isArray(numbers[0])){numbers=numbers[0];}//wecanbelazy:
// let Array sort the numbers and pick the lastreturnsort(numbers)[numbers.length-1];},min:functionmin(){//differentapproachtohandlingarguments://callthesamefunctionagainif(isArray(numbers)){returnthis.min.apply(this,numbers[0]);}//Differentapproachtopickingthemin://sortingthearrayisanoverkill,it'stoomuch//worksincewedon'tworryaboutsortingbutonly//aboutthesmallestnumber.//Solet'sloop:varmin=numbers[0];for(vari=1;i<numbers.length;i++){if(min>numbers[i]){min=numbers[i];}}returnmin;},rand:functionrand(min,max,inclusive){if(inclusive){
return Math.round(Math.random() * (max - min) + min);//testboundariesforrandomnumber//between10and100*inclusive*://Math.round(0.000000*90+10);//10//Math.round(0.000001*90+10);//10//Math.round(0.999999*90+10);//100
![Page 588: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/588.jpg)
}returnMath.floor(Math.random()*(max-min-1)+min+1);//testboundariesforrandomnumber//between10and100*non-inclusive*://Math.floor(0.000000*(89)+(11));//11//Math.floor(0.000001*(89)+(11));//11//Math.floor(0.999999*(89)+(11));//99}};})();
AfteryouhavefinishedthebookandknowaboutES5youcantryusingdefineProperty()fortightercontrolandcloserreplicationofthebuilt-ins.
![Page 589: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/589.jpg)
Chapter 5, PrototypeLets try and solve the following exercise:
![Page 590: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/590.jpg)
Exercises1. CreateanobjectcalledshapethathasatypepropertyandagetType()method:
varshape={type:'shape',getType:function(){returnthis.type;}};
2. ThefollowingistheprogramforaTriangle()constructor:
functionTriangle(a,b,c){this.a = a;
this.b=b;this.c=c;}Triangle.prototype=shape;Triangle.prototype.constructor=Triangle;Triangle.prototype.type='triangle';
3. ToaddthegetPerimeter()method,usethefollowingcode:
Triangle.prototype.getPerimeter=function(){returnthis.a+this.b+this.c;};
4. Testthefollowingcode:
>vart=newTriangle(1,2,3);>t.constructor===Triangle;true>shape.isPrototypeOf(t);true>t.getPerimeter();6>t.getType();"triangle"
5. Loopovertshowingonlyownpropertiesandmethods:
for(variint){if(t.hasOwnProperty(i)){console.log(i,'=',t[i]);}}
6. Randomizearrayelementsusingthefollowingcodesnippet:
Array.prototype.shuffle=function(){returnthis.sort(function(){returnMath.random()-0.5;
![Page 591: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/591.jpg)
});};
Testing:
>[1,2,3,4,5,6,7,8,9].shuffle();[4,2,3,1,5,6,8,9,7]>[1,2,3,4,5,6,7,8,9].shuffle();[2,7,1,3,4,5,8,9,6]
> [1, 2, 3, 4, 5, 6, 7, 8, 9].shuffle();[4,2,1,3,5,6,8,9,7]
![Page 592: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/592.jpg)
Chapter 6, InheritanceLets solve the following exercise:
![Page 593: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/593.jpg)
Exercises1. Multipleinheritancebymixingintotheprototype,forexample:
varmy=objectMulti(obj,another_obj,a_third,{additional:"properties"});Apossiblesolution:functionobjectMulti(){varConstr,i,prop,mixme;//constructorthatsetsownpropertiesvarConstr=function(props){for(varpropinprops){this[prop]=props[prop];}};//mixintotheprototype
for (var i = 0; i < arguments.length - 1; i++) {varmixme=arguments[i];for(varpropinmixme){Constr.prototype[prop]=mixme[prop];}}returnnewConstr(arguments[arguments.length-1]);}
Testing:
>varobj_a={a:1};> var obj_b = {a: 2, b: 2};
>varobj_c={c:3};>varmy=objectMulti(obj_a,obj_b,obj_c,{hello:"world"});>my.a;2
Propertyais2becauseobj_boverwrotethepropertywiththesamenamefromobj_a(lastonewins):
>my.b;2>my.c;3>my.hello;
"world">my.hasOwnProperty('a');false>my.hasOwnProperty('hello');true
![Page 594: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/594.jpg)
2. Practicewiththecanvasexampleathttp://www.phpied.com/files/canvas/.
Drawafewtrianglesusingthefollowingcodesnippet:
newTriangle(newPoint(100,155),newPoint(30,50),newPoint(220,00)).draw();newTriangle(newPoint(10,15),newPoint(300,50),newPoint(20,400)).draw();
Drawafewsquaresusingthefollowingcodesnippet:
newSquare(newPoint(150,150),300).draw();newSquare(newPoint(222,222),222).draw();
Drawafewrectanglesusingthefollowingcodesnippet:
newRectangle(newPoint(100,10),200,400).draw();newRectangle(newPoint(400,200),200,100).draw();
3. ToaddRhombus,Kite,Pentagon,Trapezoid,andCircle(reimplementsdraw()),usethefollowingcode:
functionKite(center,diag_a,diag_b,height){this.points=[newPoint(center.x-diag_a/2,center.y),newPoint(center.x,center.y+(diag_b-height)),newPoint(center.x+diag_a/2,center.y),newPoint(center.x,center.y-height)];this.getArea=function(){returndiag_a*diag_b/2;};}functionRhombus(center,diag_a,diag_b){Kite.call(this,center,diag_a,diag_b,diag_b/2);}functionTrapezoid(p1,side_a,p2,side_b){
this.points = [p1, p2, new Point(p2.x + side_b, p2.y),newPoint(p1.x+side_a,p1.y)];this.getArea=function(){varheight=p2.y-p1.y;returnheight*(side_a+side_b)/2;};}
![Page 595: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/595.jpg)
//regularpentagon,alledgeshavethesamelengthfunctionPentagon(center,edge){varr=edge/(2*Math.sin(Math.PI/5)),x=center.x,y=center.y;this.points=[newPoint(x+r,y),newPoint(x+r*Math.cos(2*Math.PI/5),y-r*Math.sin(2*Math.PI/5)),newPoint(x-r*Math.cos(Math.PI/5),y-r*Math.sin(Math.PI/5)),newPoint(x-r*Math.cos(Math.PI/5),y+r*Math.sin(Math.PI/5)),newPoint(x+r*Math.cos(2*Math.PI/5),y+r*Math.sin(2*Math.PI/5))];this.getArea=function(){return1.72*edge*edge;};
}functionCircle(center,radius){this.getArea=function(){returnMath.pow(radius,2)*Math.PI;};this.getPerimeter=function(){return2*radius*Math.PI;};this.draw=function(){varctx=this.context;ctx.beginPath();ctx.arc(center.x,center.y,radius,0,2*Math.PI);ctx.stroke();};}(function(){vars=newShape();Kite.prototype=s;Rhombus.prototype=s;Trapezoid.prototype=s;Pentagon.prototype=s;
Circle.prototype = s;}());
Testing:
newKite(newPoint(300,300),200,300,100).draw();newRhombus(newPoint(200,200),350,200).draw();
![Page 596: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/596.jpg)
newTrapezoid(newPoint(100,100),100,newPoint(50,250),400).draw();newPentagon(newPoint(400,400),100).draw();newCircle(newPoint(500,300),270).draw();
Theresultoftestingnewshapes4. Thinkofanotherwaytodotheinheritancepart.Useubersokidscanhaveaccesstotheirparents.Also,getparentstobeawareoftheirchildren.
KeepinmindthatnotallchildreninheritShape;forexample,RhombusinheritsKiteandSquareinheritsRectangle.Youendupwithsomethinglikethis:
//inherit(Child,Parent)inherit(Rectangle,Shape);
![Page 597: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/597.jpg)
inherit(Square,Rectangle);
Intheinheritancepatternfromthechapterandthepreviousexercise,allchildrenweresharingthesameprototype,forexample:
vars=newShape();Kite.prototype=s;Rhombus.prototype=s;
Whilethisisconvenient,italsomeansnoonecantouchtheprototypebecauseitwillaffecteveryoneelse'sprototype.Thedrawbackisthatallcustommethodsneedtoownproperties,forexamplethis.getArea.
It'sagoodideatohavemethodssharedamonginstancesanddefined intheprototype,insteadofrecreatingthemforeveryobject.ThefollowingexamplemovesthecustomgetArea()methodstotheprototype.
Intheinheritancefunction,you'llseethechildrenonlyinherittheparent'sprototype.Soownpropertiessuchasthis.lineswillnotbeset.Therefore,youneedtohaveeachchildconstructorcallitsuberinordertogettheownproperties,forexample:
Child.prototype.uber.call(this,args...)
Anothernice-to-havefeatureiscarryingovertheprototypepropertiesalreadyaddedtothechild.Thisallowsthechildtoinheritfirstandthenaddmorecustomizationsortheotherway around as well, which is just a little more convenient.
functioninherit(Child,Parent){//rememberprototypevarextensions=Child.prototype;//inheritancewithanintermediateF()varF=function(){};F.prototype=Parent.prototype;Child.prototype=newF();//resetconstructorChild.prototype.constructor=Child;//rememberparentChild.prototype.uber=Parent;//keeptrackofwhoinheritstheParent
if (!Parent.children) {Parent.children=[];}Parent.children.push(Child);//carryoverstuffprevisoulyaddedtotheprototype//becausetheprototypeisnowoverwrittencompletelyfor(variinextensions){if(extensions.hasOwnProperty(i)){
![Page 598: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/598.jpg)
Child.prototype[i]=extensions[i];}}}
EverythingaboutShape(),Line(),andPoint()staysthesame.Thechangesareinthechildrenonly:
functionTriangle(a,b,c){Triangle.prototype.uber.call(this);
this.points = [a, b, c];}Triangle.prototype.getArea=function(){varp=this.getPerimeter(),s=p/2;returnMath.sqrt(s*(s-this.lines[0].length)*(s-this.lines[1].length)*(s-this.lines[2].length));};functionRectangle(p,side_a,side_b){//callingparentShape()Rectangle.prototype.uber.call(this);this.points=[p,newPoint(p.x+side_a,p.y),newPoint(p.x+side_a,p.y+side_b),newPoint(p.x,p.y+side_b)];}Rectangle.prototype.getArea=function(){//Previsoulywehadaccesstoside_aandside_b//insidetheconstructorclosure.Nomore.//option1:addownpropertiesthis.side_aandthis.side_b
// option 2: use what we already have:varlines=this.getLines();returnlines[0].length*lines[1].length;};functionSquare(p,side){this.uber.call(this,p,side,side);//thiscallisshorterthanSquare.prototype.uber.call()//butmaybackfireincaseyouinherit//fromSquareandcalluber//tryit:-)}
Inheritance:
inherit(Triangle,Shape);inherit(Rectangle,Shape);
![Page 599: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/599.jpg)
inherit(Square,Rectangle);
Testing:
>varsq=newSquare(newPoint(0,0),100);>sq.draw();>sq.getArea();10000
Testingthatinstanceofiscorrect:
>sq.constructor===Square;true>sqinstanceofSquare;true>sqinstanceofRectangle;true>sqinstanceofShape;
true
Thechildrenarrays:
>Shape.children[1]===Rectangle;true>Rectangle.children[0]===Triangle;false>Rectangle.children[0]===Square;
true>Square.children;undefined
Anduberlooksoktoo:
>sq.uber===Rectangle;true
CallingisPrototypeOf()alsoreturnsexpectedresults:
Shape.prototype.isPrototypeOf(sq);trueRectangle.prototype.isPrototypeOf(sq);trueTriangle.prototype.isPrototypeOf(sq);false
Thefullcodeisavailableathttp://www.phpied.com/files/canvas/index2.html,togetherwiththeadditionalKite(),Circle(),andsoonfromthepreviousexercise.
![Page 600: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/600.jpg)
Chapter 7, The Browser EnvironmentLets practice the following exercise:
![Page 601: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/601.jpg)
Exercises1. Thetitleclockprogramisasfollows:
setInterval(function(){document.title=newDate().toTimeString();},1000);
2. Toanimateresizingofa200x200popupto400x400,usethefollowingcode:
varw=window.open('http://phpied.com','my','width=200,height=200');vari=setInterval((function(){varsize=200;returnfunction(){size+=5;w.resizeTo(size,size);if(size===400){clearInterval(i);}
};}()),100);
Every100ms(1/10thofasecond)thepop-upsizeincreasesbyfivepixels.Youkeepareferencetotheintervalisoyoucanclearitoncedone.Thevariablesizetracksthepop-upsize(andwhynotkeepitprivateinsideaclosure).
3. Theearthquakeprogramisasfollows:
vari=setInterval((function(){varstart=+newDate();//Date.now()inES5returnfunction(){w.moveTo(Math.round(Math.random()*100),Math.round(Math.random()*100));if(newDate()-start>5000){clearInterval(i);}};}()),20);
Tryallofthem,butusingrequestAnimationFrame()insteadofsetInterval().4. AdifferentwalkDOM()withacallbackisasfollows:
functionwalkDOM(n,cb){cb(n);vari,children=n.childNodes,len=children.length,child;for(i=0;i<len;i++){
![Page 602: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/602.jpg)
child=n.childNodes[i];if(child.hasChildNodes()){walkDOM(child,cb);}}}
Testing:
> walkDOM(document.documentElement,console.dir.bind(console));htmlheadtitlebodyh1...
5. Toremovecontentandcleanupfunctions,usethefollowingcode:
//helperfunctionisFunction(f){returnObject.prototype.toString.call(f)==="[objectFunction]";}functionremoveDom(node){vari,len,attr;//firstdrilldowninspectingthechildren//andonlyafterthatremovethecurrentnodewhile(node.firstChild){removeDom(node.firstChild);}//notallnodeshaveattributes,e.g.textnodesdon'tlen=node.attributes?node.attributes.length:0;
//cleanuploop//e.g.node===<body>,//node.attributes[0].name==="onload"//node.onload===function()...//node.onloadisnotenumerablesowecan'tuse//afor-inloopandhavetogotheattributesroutefor(i=0;i<len;i++){attr=node[node.attributes[i].name];if(isFunction(attr)){//console.log(node,attr);attr=null;}}node.parentNode.removeChild(node);}
![Page 603: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/603.jpg)
Testing:
>removeDom(document.body);
6. Toincludescriptsdynamically,usethefollowingcode:
functioninclude(url){vars=document.createElement('script');s.src=url;document.getElementsByTagName('head')[0].appendChild(s);}
Testing:
>include("http://www.phpied.com/files/jinc/1.js");>include("http://www.phpied.com/files/jinc/2.js");
7. Events:Theeventutilityprogramisasfollows:
varmyevent=(function(){//wrapsomeprivatestuffinaclosurevaradd,remove,toStr=Object.prototype.toString;//helperfunctiontoArray(a){//alreadyanarrayif(toStr.call(a)==='[objectArray]'){returna;}
// duck-typing HTML collections, arguments etcvarresult,i,len;if('length'ina){for(result=[],i=0,len=a.length;i<len;i++){result[i]=a[i];}returnresult;}//primitivesandnon-array-likeobjects//becomethefirstandsinglearrayelementreturn[a];}//defineadd()andremove()depending//onthebrowser'scapabilitiesif(document.addEventListener){add=function(node,ev,cb){node.addEventListener(ev,cb,false);};remove=function(node,ev,cb){
![Page 604: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/604.jpg)
node.removeEventListener(ev,cb,false);};}elseif(document.attachEvent){add=function(node,ev,cb){node.attachEvent('on'+ev,cb);};remove=function(node,ev,cb){node.detachEvent('on'+ev,cb);};}else{add=function(node,ev,cb){node['on'+ev]=cb;};remove=function(node,ev){node['on'+ev]=null;};}//publicAPIreturn{
addListener: function (element, event_name, callback) {//elementcouldalsobeanarrayofelementselement=toArray(element);for(vari=0;i<element.length;i++){add(element[i],event_name,callback);}},removeListener:function(element,event_name,callback){//sameasadd(),onlypracticingadifferentloopvari=0,els=toArray(element),len=els.length;for(;i<len;i++){remove(els[i],event_name,callback);}},getEvent:function(event){returnevent||window.event;},getTarget:function(event){vare=this.getEvent(event);returne.target||e.srcElement;},
stopPropagation: function (event) {vare=this.getEvent(event);if(e.stopPropagation){e.stopPropagation();}else{e.cancelBubble=true;}
![Page 605: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/605.jpg)
},preventDefault:function(event){vare=this.getEvent(event);if(e.preventDefault){e.preventDefault();}else{e.returnValue=false;}}};}());
Testing:Gotoanypagewithlinks,executethefollowing,andthenclickanylink:
functionmyCallback(e){e=myevent.getEvent(e);alert(myevent.getTarget(e).href);myevent.stopPropagation(e);myevent.preventDefault(e);}myevent.addListener(document.links,'click',myCallback);
8. Moveadivaroundwiththekeyboardusing thefollowingcode:
//addadivtothebottomofthepagevardiv=document.createElement('div');div.style.cssText='width:100px;height:100px;background:red;position:absolute;';document.body.appendChild(div);//remembercoordinates
var x = div.offsetLeft;vary=div.offsetTop;myevent.addListener(document.body,'keydown',function(e){//preventscrollingmyevent.preventDefault(e);switch(e.keyCode){case37://leftx--;break;case38://upy--;break;case39://rightx++;break;case40://downy++;break;
![Page 606: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/606.jpg)
default://notinterested}//movediv.style.left=x+'px';div.style.top=y+'px';});
9. YourownAjaxutility:
varajax={getXHR:function(){varids=['MSXML2.XMLHTTP.3.0','MSXML2.XMLHTTP','Microsoft.XMLHTTP'];varxhr;if(typeofXMLHttpRequest==='function'){xhr=newXMLHttpRequest();}else{//IE:trytofindanActiveXobjecttousefor(vari=0;i<ids.length;i++){try{xhr=newActiveXObject(ids[i]);
break;}catch(e){}}}returnxhr;},request:function(url,method,cb,post_body){varxhr=this.getXHR();xhr.onreadystatechange=(function(myxhr){returnfunction(){if(myxhr.readyState===4&&myxhr.status===200){cb(myxhr);}};}(xhr));xhr.open(method.toUpperCase(),url,true);xhr.send(post_body||'');}};
Whentesting,rememberthatsameoriginrestrictionsapply,soyouhavetobeonthesamedomain.Youcangotohttp://www.phpied.com/files/jinc/,whichisadirectorylistingandthentestintheconsole:
functionmyCallback(xhr){alert(xhr.responseText);}ajax.request('1.css','get',myCallback);
![Page 607: Object-Oriented JavaScript - Third Edition · 2017. 4. 20. · ES6 object literals Object properties and attributes ES6 object methods Copy properties using Object.assign Compare](https://reader036.vdocuments.net/reader036/viewer/2022071517/613a16a90051793c8c00d869/html5/thumbnails/607.jpg)
ajax.request('1.css','post',myCallback,'first=John&last=Smith');
Theresultofthetwoisthesame,butifyoulookintotheNetworktaboftheWebInspector,youcanseethatthesecondisindeedaPOSTrequestwithabody.