table of contents · checking (something that typescript and flow aim to improve) interpreted:...

171

Upload: others

Post on 26-Jun-2020

1 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a
Page 2: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TableofContentsPreface

IntroductiontoJavaScript

ECMAScript

ES6

ES2016

ES2017

ES2018

Codingstyle

LexicalStructure

Variables

Types

Expressions

Prototypalinheritance

Classes

Exceptions

Semicolons

Quotes

TemplateLiterals

Functions

ArrowFunctions

Closures

Arrays

Loops

Events

TheEventLoop

Asynchronousprogrammingandcallbacks

Promises

AsyncandAwait

LoopsandScope

Timers

2

Page 3: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

this

StrictMode

Immediately-invokedFunctionExpressions(IIFE)

Mathoperators

TheMathobject

ESModules

CommonJS

Glossary

3

Page 4: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Preface

TheJavaScriptHandbookfollowsthe80/20rule:learnin20%ofthetimethe80%ofatopic.

Ifindthisapproachgivesawell-roundedoverview.ThisbookdoesnottrytocovereverythingunderthesunrelatedtoJavaScript.Ifyouthinksomespecifictopicshouldbeincluded,tellme.

YoucanreachmeonTwitter@flaviocopes.

Ihopethecontentsofthisbookwillhelpyouachievewhatyouwant:learnthebasicsofJavaScript.

ThisbookiswrittenbyFlavio.Ipublishwebdevelopmenttutorialseverydayonmywebsiteflaviocopes.com.

Enjoy!

Preface

4

Page 5: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

IntroductiontoJavaScriptJavaScriptisoneofthemostpopularprogramminglanguagesintheworld,andnowwidelyusedalsooutsideofthebrowser.TheriseofNode.jsinthelastfewyearsunlockedbackenddevelopment,oncethedomainofJava,Ruby,Python,PHP,andmoretraditionalserver-sidelanguages.Learnallaboutit!

IntroductionJavaScriptisoneofthemostpopularprogramminglanguagesintheworld.

Created20yearsago,it'sgoneaverylongwaysinceitshumblebeginnings.

Beingthefirst-andtheonly-scriptinglanguagethatwassupportednativelybywebbrowsers,itsimplystuck.

Inthebeginnings,itwasnotnearlypowerfulasitistoday,anditwasmainlyusedforfancyanimationsandthemarvelknownatthetimeasDHTML.

Withthegrowingneedsthatthewebplatformdemands,JavaScripthadtheresponsibilitytogrowaswell,toaccommodatetheneedsofoneofthemostwidelyusedecosystemsoftheworld.

Manythingswereintroducedintheplatform,withbrowserAPIs,butthelanguagegrewquitealotaswell.

JavaScriptisnowwidelyusedalsooutsideofthebrowser.TheriseofNode.jsinthelastfewyearsunlockedbackenddevelopment,oncethedomainofJava,Ruby,PythonandPHPandmoretraditionalserver-sidelanguages.

JavaScriptisnowalsothelanguagepoweringdatabasesandmanymoreapplications,andit'sevenpossibletodevelopembeddedapplications,mobileapps,TVsetsappsandmuchmore.Whatstartedasatinylanguageinsidethebrowserisnowthemostpopularlanguageintheworld.

AbasicdefinitionofJavaScriptJavaScriptisaprogramminglanguagethatis:

highlevel:itprovidesabstractionsthatallowyoutoignorethedetailsofthemachinewhereit'srunningon.Itmanagesmemoryautomaticallywithagarbagecollector,soyou

IntroductiontoJavaScript

5

Page 6: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

canfocusonthecodeinsteadofmanagingmemorylocations,andprovidesmanyconstructswhichallowyoutodealwithhighlypowerfulvariablesandobjects.dynamic:opposedtostaticprogramminglanguages,adynamiclanguageexecutesatruntimemanyofthethingsthatastaticlanguagedoesatcompiletime.Thishasprosandcons,anditgivesuspowerfulfeatureslikedynamictyping,latebinding,reflection,functionalprogramming,objectruntimealteration,closuresandmuchmore.dynamicallytyped:avariabledoesnotenforceatype.Youcanreassignanytypetoavariable,forexampleassigninganintegertoavariablethatholdsastring.weaklytyped:asopposedtostrongtyping,weakly(orloosely)typedlanguagesdonotenforcethetypeofanobject,allowingmoreflexibilitybutdenyingustypesafetyandtypechecking(somethingthatTypeScriptandFlowaimtoimprove)interpreted:it'scommonlyknownasaninterpretedlanguage,whichmeansthatitdoesnotneedacompilationstagebeforeaprogramcanrun,asopposedtoC,JavaorGoforexample.Inpractice,browsersdocompileJavaScriptbeforeexecutingit,forperformancereasons,butthisistransparenttoyou:thereisnoadditionalstepinvolved.multi-paradigm:thelanguagedoesnotenforceanyparticularprogrammingparadigm,unlikeJavaforexamplewhichforcestheuseofobjectorientedprogramming,orCthatforcesimperativeprogramming.YoucanwriteJavaScriptusinganobject-orientedparadigm,usingprototypesandthenew(asofES6)classessyntax.YoucanwriteJavaScriptinfunctionalprogrammingstyle,withitsfirstclassfunctions,oreveninanimperativestyle(C-like).

Incaseyou'rewondering,JavaScripthasnothingtodowithJava,it'sapoornamechoicebutwehavetolivewithit.

JavaScriptversionsLetmeintroducethetermECMAScripthere.WehaveacompleteguidededicatedtoECMAScriptwhereyoucandiveintoitmore,buttostartwith,youjustneedtoknowthatECMAScript(alsocalledES)isthenameoftheJavaScriptstandard.

JavaScriptisanimplementationofthatstandard.That'swhyyou'llhearaboutES6,ES2015,ES2016,ES2017,ES2018andsoon.

Foraverylongtime,theversionofJavaScriptthatallbrowserranwasECMAScript3.Version4wascanceledduetofeaturecreep(theyweretryingtoaddtoomanythingsatonce),whileES5wasahugeversionforJS.

ES2015,alsocalledES6,washugeaswell.

Sincethen,theonesinchargedecidedtoreleaseoneversionperyear,toavoidhavingtoomuchtimeidlebetweenreleases,andhaveafasterfeedbackloop.

IntroductiontoJavaScript

6

Page 7: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Currently,thelatestapprovedJavaScriptversionisES2017.

IntroductiontoJavaScript

7

Page 8: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ECMAScriptECMAScriptisthestandarduponwhichJavaScriptisbased,andit'softenabbreviatedtoES.DiscovereverythingaboutECMAScript,andthelastfeaturesaddedinES6,7,8

WheneveryoureadaboutJavaScriptyou'llinevitablyseeoneoftheseterms:

ES3ES5ES6ES7ES8ES2015ES2016ES2017ECMAScript2017ECMAScript2016

ECMAScript

8

Page 9: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ECMAScript2015

Whatdotheymean?

Theyareallreferringtoastandard,calledECMAScript.

ECMAScriptisthestandarduponwhichJavaScriptisbased,andit'softenabbreviatedtoES.

BesideJavaScript,otherlanguagesimplement(ed)ECMAScript,including:

ActionScript(theFlashscriptinglanguage),whichislosingpopularitysinceFlashwillbeofficiallydiscontinuedin2020JScript(theMicrosoftscriptingdialect),sinceatthetimeJavaScriptwassupportedonlybyNetscapeandthebrowserwarswereattheirpeak,MicrosofthadtobuilditsownversionforInternetExplorer

butofcourseJavaScriptisthemostpopularandwidelyusedimplementationofES.

Whythisweirdname? EcmaInternationalisaSwissstandardsassociationwhoisinchargeofdefininginternationalstandards.

WhenJavaScriptwascreated,itwaspresentedbyNetscapeandSunMicrosystemstoEcmaandtheygaveitthenameECMA-262aliasECMAScript.

ThispressreleasebyNetscapeandSunMicrosystems(themakerofJava)mighthelpfigureoutthenamechoice,whichmightincludelegalandbrandingissuesbyMicrosoftwhichwasinthecommittee,accordingtoWikipedia.

AfterIE9,MicrosoftstoppedstoppedbrandingitsESsupportinbrowsersasJScriptandstartedcallingitJavaScript(atleast,Icouldnotfindreferencestoitanymore)

Soasof201x,theonlypopularlanguagesupportingtheECMAScriptspecisJavaScript.

CurrentECMAScriptversionThecurrentECMAScriptversionisES2017,AKAES8

ItwasreleasedinJune2017.

Whenisthenextversioncomingout?HistoricallyJavaScripteditionshavebeenstandardizedduringthesummer,sowecanexpectECMAScript2019(namedES2019orES10)tobereleasedinsummer2019,butthisisjustspeculation.

ECMAScript

9

Page 10: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

WhatisTC39TC39isthecommitteethatevolvesJavaScript.

ThemembersofTC39arecompaniesinvolvedinJavaScriptandbrowservendors,includingMozilla,Google,Facebook,Apple,Microsoft,Intel,PayPal,SalesForceandothers.

Everystandardversionproposalmustgothroughvariousstages,whichareexplainedhere.

ESVersionsIfounditpuzzlingwhysometimesanESversionisreferencedbyeditionnumberandsometimesbyyear,andIamconfusedbytheyearbychancebeing-1onthenumber,whichaddstothegeneralconfusionaroundJS/ES

BeforeES2015,ECMAScriptspecificationswerecommonlycalledbytheiredition.SoES5istheofficialnamefortheECMAScriptspecificationupdatepublishedin2009.

Whydoesthishappen?DuringtheprocessthatledtoES2015,thenamewaschangedfromES6toES2015,butsincethiswasdonelate,peoplestillreferenceditasES6,andthecommunityhasnotlefttheeditionnamingbehind-theworldisstillcallingESreleasesbyeditionnumber.

Thistableshouldclearthingsabit:

Edition Officialname Datepublished

ES9 ES2018 June2018

ES8 ES2017 June2017

ES7 ES2016 June2016

ES6 ES2015 June2015

ES5.1 ES5.1 June2011

ES5 ES5 December2009

ES4 ES4 Abandoned

ES3 ES3 December1999

ES2 ES2 June1998

ES1 ES1 June1997

ESNext

ECMAScript

10

Page 11: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES.NextisanamethatalwaysindicatesthenextversionofJavaScript.

Soatthetimeofwriting,ES9hasbeenreleased,andES.NextisES10

ECMAScript

11

Page 12: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES6ECMAScriptisthestandarduponwhichJavaScriptisbased,andit'softenabbreviatedtoES.DiscovereverythingaboutECMAScript,andthelastfeaturesaddedinES6,akaES2015

ECMAScript2015,alsoknownasES6,isafundamentalversionoftheECMAScriptstandard.

Published4yearsafterthelateststandardrevision,ECMAScript5.1,italsomarkedtheswitchfromeditionnumbertoyearnumber.

SoitshouldnotbenamedasES6(althougheveryonecallsitassuch)butES2015instead.

ES5was10yearsinthemaking,from1999to2009,andassuchitwasalsoafundamentalandveryimportantrevisionofthelanguage,butnowmuchtimehaspassedthatit'snotworthdiscussinghowpre-ES5codeworked.

SincethislongtimepassedbetweenES5.1andES6,thereleaseisfullofimportantnewfeaturesandmajorchangesinsuggestedbestpracticesindevelopingJavaScriptprograms.TounderstandhowfundamentalES2015is,justkeepinmindthatwiththisversion,thespecificationdocumentwentfrom250pagesto~600.

ThemostimportantchangesinES2015include

ArrowfunctionsPromisesGeneratorsletand constClassesModulesMultilinestringsTemplateliteralsDefaultparametersThespreadoperator|DestructuringassignmentsEnhancedobjectliteralsThefor..ofloopMapandSet

Eachofthemhasadedicatedsectioninthisarticle.

ArrowFunctions

ES6

12

Page 13: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ArrowfunctionssincetheirintroductionchangedhowmostJavaScriptcodelooks(andworks).

Visually,it'sasimpleandwelcomechange,from:

constfoo=functionfoo(){

//...

}

to

constfoo=()=>{

//...

}

Andifthefunctionbodyisaone-liner,just:

constfoo=()=>doSomething()

Also,ifyouhaveasingleparameter,youcouldwrite:

constfoo=param=>doSomething(param)

Thisisnotabreakingchange,regular functionswillcontinuetoworkjustasbefore.

Anew thisscopeThe thisscopewitharrowfunctionsisinheritedfromthecontext.

Withregular functions thisalwaysreferstothenearestfunction,whilewitharrowfunctionsthisproblemisremoved,andyouwon'tneedtowrite varthat=thiseveragain.

PromisesPromises(checkthefullguidetopromises)allowustoeliminatethefamous"callbackhell",althoughtheyintroduceabitmorecomplexity(whichhasbeensolvedinES2017with async,ahigherlevelconstruct).

PromiseshavebeenusedbyJavaScriptdeveloperswellbeforeES2015,withmanydifferentlibrariesimplementations(e.g.jQuery,q,deferred.js,vow...),andthestandardputacommongroundacrossdifferences.

Byusingpromisesyoucanrewritethiscode

ES6

13

Page 14: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

setTimeout(function(){

console.log('Ipromisedtorunafter1s')

setTimeout(function(){

console.log('Ipromisedtorunafter2s')

},1000)

},1000)

as

constwait=()=>newPromise((resolve,reject)=>{

setTimeout(resolve,1000)

})

wait().then(()=>{

console.log('Ipromisedtorunafter1s')

returnwait()

})

.then(()=>console.log('Ipromisedtorunafter2s'))

GeneratorsGeneratorsareaspecialkindoffunctionwiththeabilitytopauseitself,andresumelater,allowingothercodetoruninthemeantime.

Thecodedecidesthatithastowait,soitletsothercode"inthequeue"torun,andkeepstherighttoresumeitsoperations"whenthethingit'swaitingfor"isdone.

Allthisisdonewithasingle,simplekeyword: yield.Whenageneratorcontainsthatkeyword,theexecutionishalted.

Ageneratorcancontainmany yieldkeywords,thushaltingitselfmultipletimes,andit'sidentifiedbythe *functionkeyword,whichisnottobeconfusedwiththepointerdereferenceoperatorusedinlowerlevelprogramminglanguagessuchasC,C++orGo.

GeneratorsenablewholenewparadigmsofprogramminginJavaScript,allowing:

2-waycommunicationwhileageneratorisrunninglong-livedwhileloopswhichdonotfreezeyourprogram

Hereisanexampleofageneratorwhichexplainshowitallworks.

function*calculator(input){

vardoubleThat=2*(yield(input/2))

varanother=yield(doubleThat)

return(input*doubleThat*another)

}

ES6

14

Page 15: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Weinitializeitwith

constcalc=calculator(10)

Thenwestarttheiteratoronourgenerator:

calc.next()

Thisfirstiterationstartstheiterator.Thecodereturnsthisobject:

{

done:false

value:5

}

Whathappensis:thecoderunsthefunction,with input=10asitwaspassedinthegeneratorconstructor.Itrunsuntilitreachesthe yield,andreturnsthecontentof yield:input/2=5.Sowegotavalueof5,andtheindicationthattheiterationisnotdone(thefunctionisjustpaused).

Intheseconditerationwepassthevalue 7:

calc.next(7)

andwhatwegotbackis:

{

done:false

value:14

}

7wasplacedasthevalueof doubleThat.Important:youmightreadlike input/2wastheargument,butthat'sjustthereturnvalueofthefirstiteration.Wenowskipthat,andusethenewinputvalue, 7,andmultiplyitby2.

Wethenreachthesecondyield,andthatreturns doubleThat,sothereturnedvalueis 14.

Inthenext,andlast,iteration,wepassin100

calc.next(100)

andinreturnwegot

ES6

15

Page 16: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

{

done:true

value:14000

}

Astheiterationisdone(nomoreyieldkeywordsfound)andwejustreturn (input*doubleThat*another)whichamountsto 10*14*100.

letand constvaristraditionallyfunctionscoped.

letisanewvariabledeclarationwhichisblockscoped.

Thismeansthatdeclaring letvariablesinaforloop,insideaniforinaplainblockisnotgoingtoletthatvariable"escape"theblock,while varsarehoisteduptothefunctiondefinition.

constisjustlike let,butimmutable.

InJavaScriptmovingforward,you'llseelittletono vardeclarationsanymore,just letandconst.

constinparticular,maybesurprisingly,isverywidelyusednowadayswithimmutabilitybeingverypopular.

ClassesTraditionallyJavaScriptistheonlymainstreamlanguagewithprototype-basedinheritance.ProgrammersswitchingtoJSfromclass-basedlanguagefounditpuzzling,butES2015introducedclasses,whicharejustsyntacticsugarovertheinnerworking,butchangedalothowwebuildJavaScriptprograms.

Nowinheritanceisveryeasyandresemblesotherobject-orientedprogramminglanguages:

classPerson{

constructor(name){

this.name=name

}

hello(){

return'Hello,Iam'+this.name+'.'

}

}

ES6

16

Page 17: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

classActorextendsPerson{

hello(){

returnsuper.hello()+'Iamanactor.'

}

}

vartomCruise=newActor('TomCruise')

tomCruise.hello()

(theaboveprogramprints"Hello,IamTomCruise.Iamanactor.")

Classesdonothaveexplicitclassvariabledeclarations,butyoumustinitializeanyvariableintheconstructor.

Constructor

Classeshaveaspecialmethodcalled constructorwhichiscalledwhenaclassisinitializedvia new.

Super

Theparentclasscanbereferencedusing super().

Gettersandsetters

Agetterforapropertycanbedeclaredas

classPerson{

getfullName(){

return`${this.firstName}${this.lastName}`

}

}

Settersarewritteninthesameway:

classPerson{

setage(years){

this.theAge=years

}

}

Modules

ES6

17

Page 18: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

BeforeES2015,therewereatleast3majormodulescompetingstandards,whichfragmentedthecommunity:

AMDRequireJSCommonJS

ES2015standardizedtheseintoacommonformat.

Importingmodules

Importingisdoneviathe import...from...construct:

import*from'mymodule'

importReactfrom'react'

import{React,Component}from'react'

importReactasMyLibraryfrom'react'

Exportingmodules

Youcanwritemodulesandexportanythingtoothermodulesusingthe exportkeyword:

exportvarfoo=2

exportfunctionbar(){/*...*/}

TemplateLiteralsTemplateliteralsareanewsyntaxtocreatestrings:

constaString=`Astring`

Theyprovideawaytoembedexpressionsintostrings,effectivelyinterpolatingthevalues,byusingthe ${a_variable}syntax:

constvar='test'

conststring=`something${var}`//somethingtest

Youcanperformmorecomplexexpressionsaswell:

conststring=`something${1+2+3}`

conststring2=`something${foo()?'x':'y'}`

ES6

18

Page 19: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

andstringscanspanovermultiplelines:

conststring3=`Hey

this

string

isawesome!`

Comparehowweusedtodomultilinestringspre-ES2015:

varstr='One\n'+

'Two\n'+

'Three'

Seethispostforanin-depthguideontemplateliterals

DefaultparametersFunctionsnowsupportdefaultparameters:

constfoo=function(index=0,testing=true){/*...*/}

foo()

ThespreadoperatorYoucanexpandanarray,anobjectorastringusingthespreadoperator ....

Let'sstartwithanarrayexample.Given

consta=[1,2,3]

youcancreateanewarrayusing

constb=[...a,4,5,6]

Youcanalsocreateacopyofanarrayusing

constc=[...a]

Thisworksforobjectsaswell.Cloneanobjectwith:

ES6

19

Page 20: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

constnewObj={...oldObj}

Usingstrings,thespreadoperatorcreatesanarraywitheachcharinthestring:

consthey='hey'

constarrayized=[...hey]//['h','e','y']

Thisoperatorhassomeprettyusefulapplications.Themostimportantoneistheabilitytouseanarrayasfunctionargumentinaverysimpleway:

constf=(foo,bar)=>{}

consta=[1,2]

f(...a)

(inthepastyoucoulddothisusing f.apply(null,a)butthat'snotasniceandreadable)

DestructuringassignmentsGivenanobject,youcanextractjustsomevaluesandputthemintonamedvariables:

constperson={

firstName:'Tom',

lastName:'Cruise',

actor:true,

age:54,//madeup

}

const{firstName:name,age}=person

nameand agecontainthedesiredvalues.

Thesyntaxalsoworksonarrays:

consta=[1,2,3,4,5]

[first,second,,,fifth]=a

EnhancedObjectLiteralsInES2015ObjectLiteralsgainedsuperpowers.

Simplersyntaxtoincludevariables

ES6

20

Page 21: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Insteadofdoing

constsomething='y'

constx={

something:something

}

youcando

constsomething='y'

constx={

something

}

Prototype

Aprototypecanbespecifiedwith

constanObject={y:'y'}

constx={

__proto__:anObject

}

super()

constanObject={y:'y',test:()=>'zoo'}

constx={

__proto__:anObject,

test(){

returnsuper.test()+'x'

}

}

x.test()//zoox

Dynamicproperties

constx={

['a'+'_'+'b']:'z'

}

x.a_b//z

For-ofloop

ES6

21

Page 22: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES5backin2009introduced forEach()loops.Whilenice,theyofferednowaytobreak,likeforloopsalwaysdid.

ES2015introducedthe for-ofloop,whichcombinestheconcisenessof forEachwiththeabilitytobreak:

//iterateoverthevalue

for(constvof['a','b','c']){

console.log(v);

}

//gettheindexaswell,using`entries()`

for(const[i,v]of['a','b','c'].entries()){

console.log(i,v);

}

MapandSetMapandSet(andtheirrespectivegarbagecollectedWeakMapandWeakSet)aretheofficialimplementationsoftwoverypopulardatastructures.

ES6

22

Page 23: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES2016ECMAScriptisthestandarduponwhichJavaScriptisbased,andit'softenabbreviatedtoES.DiscovereverythingaboutECMAScript,andthelastfeaturesaddedinES2016,akaES7

ES7,officiallyknownasECMAScript2016,wasfinalizedinJune2016.

ComparedtoES6,ES7isatinyreleaseforJavaScript,containingjusttwofeatures:

Array.prototype.includesExponentiationOperator

Array.prototype.includes()Thisfeatureintroducesamorereadablesyntaxforcheckingifanarraycontainsanelement.

WithES6andlower,tocheckifanarraycontainedanelementyouhadtouse indexOf,whichcheckstheindexinthearray,andreturns -1iftheelementisnotthere.

Since -1isevaluatedasatruevalue,youcouldnotdoforexample

if(![1,2].indexOf(3)){

console.log('Notfound')

}

WiththisfeatureintroducedinES7wecando

if(![1,2].includes(3)){

console.log('Notfound')

}

ExponentiationOperatorTheexponentiationoperator **istheequivalentof Math.pow(),butbroughtintothelanguageinsteadofbeingalibraryfunction.

Math.pow(4,2)==4**2

ThisfeatureisaniceadditionformathintensiveJSapplications.

ES2016

23

Page 24: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

The **operatorisstandardizedacrossmanylanguagesincludingPython,Ruby,MATLAB,Lua,Perlandmanyothers.

ES2016

24

Page 25: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES2017ECMAScriptisthestandarduponwhichJavaScriptisbased,andit'softenabbreviatedtoES.DiscovereverythingaboutECMAScript,andthelastfeaturesaddedinES2017,akaES8

ECMAScript2017,edition8oftheECMA-262Standard(alsocommonlycalledES2017orES8),wasfinalizedinJune2017.

ComparedtoES6,ES8isatinyreleaseforJavaScript,butstillitintroducesveryusefulfeatures:

StringpaddingObject.valuesObject.entriesObject.getOwnPropertyDescriptors()TrailingcommasinfunctionparameterlistsandcallsAsyncfunctionsSharedmemoryandatomics

StringpaddingThepurposeofstringpaddingistoaddcharacterstoastring,soitreachesaspecificlength.

ES2017introducestwo Stringmethods: padStart()and padEnd().

padStart(targetLength[,padString])

padEnd(targetLength[,padString])

Sampleusage:

padStart()

'test'.padStart(4) 'test'

'test'.padStart(5) '_test'

'test'.padStart(8) '____test'

'test'.padStart(8,'abcd') 'abcdtest'

padEnd()

'test'.padEnd(4) 'test'

ES2017

25

Page 26: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

'test'.padEnd(5) 'test_'

'test'.padEnd(8) 'test____'

'test'.padEnd(8,'abcd') 'testabcd'

(inthetable,_=space)

Object.values()Thismethodreturnsanarraycontainingalltheobjectownpropertyvalues.

Usage:

constperson={name:'Fred',age:87}

Object.values(person)//['Fred',87]

Object.values()alsoworkswitharrays:

constpeople=['Fred','Tony']

Object.values(people)//['Fred','Tony']

Object.entries()Thismethodreturnsanarraycontainingalltheobjectownproperties,asanarrayof [key,value]pairs.

Usage:

constperson={name:'Fred',age:87}

Object.entries(person)//[['name','Fred'],['age',87]]

Object.entries()alsoworkswitharrays:

constpeople=['Fred','Tony']

Object.entries(people)//[['0','Fred'],['1','Tony']]

getOwnPropertyDescriptors()Thismethodreturnsallown(non-inherited)propertiesdescriptorsofanobject.

AnyobjectinJavaScripthasasetofproperties,andeachofthesepropertieshasadescriptor.

ES2017

26

Page 27: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Adescriptorisasetofattributesofaproperty,andit'scomposedbyasubsetofthefollowing:

value:thevalueofthepropertywritable:truethepropertycanbechangedget:agetterfunctionfortheproperty,calledwhenthepropertyisreadset:asetterfunctionfortheproperty,calledwhenthepropertyissettoavalueconfigurable:iffalse,thepropertycannotberemovednoranyattributecanbechanged,exceptitsvalueenumerable:trueifthepropertyisenumerable

Object.getOwnPropertyDescriptors(obj)acceptsanobject,andreturnsanobjectwiththesetofdescriptors.

Inwhatwayisthisuseful?

ES2015gaveus Object.assign(),whichcopiesallenumerableownpropertiesfromoneormoreobjects,andreturnanewobject.

Howeverthereisaproblemwiththat,becauseitdoesnotcorrectlycopiespropertieswithnon-defaultattributes.

Ifanobjectforexamplehasjustasetter,it'snotcorrectlycopiedtoanewobject,usingObject.assign().

Forexamplewith

constperson1={

setname(newName){

console.log(newName)

}

}

Thiswon'twork:

constperson2={}

Object.assign(person2,person1)

Butthiswillwork:

constperson3={}

Object.defineProperties(person3,Object.getOwnPropertyDescriptors(person1))

Asyoucanseewithasimpleconsoletest:

person1.name='x'

ES2017

27

Page 28: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

;('x')

person2.name='x'

person3.name='x'

;('x')

person2missesthesetter,itwasnotcopiedover.

ThesamelimitationgoesforshallowcloningobjectswithObject.create().

TrailingcommasThisfeatureallowstohavetrailingcommasinfunctiondeclarations,andinfunctionscalls:

constdoSomething=(var1,var2)=>{

//...

}

doSomething('test2','test2')

Thischangewillencouragedeveloperstostoptheugly"commaatthestartoftheline"habit.

AsyncfunctionsCheckthededicatedpostaboutasync/await

ES2017introducedtheconceptofasyncfunctions,andit'sthemostimportantchangeintroducedinthisECMAScriptedition.

Asyncfunctionsareacombinationofpromisesandgeneratorstoreducetheboilerplatearoundpromises,andthe"don'tbreakthechain"limitationofchainingpromises.

Whytheyareuseful

It'sahigherlevelabstractionoverpromises.

WhenPromiseswereintroducedinES2015,theyweremeanttosolveaproblemwithasynchronouscode,andtheydid,butoverthe2yearsthatseparatedES2015andES2017,itwasclearthatpromisescouldnotbethefinalsolution.Promiseswereintroducedtosolvethefamouscallbackhellproblem,buttheyintroducedcomplexityontheirown,andsyntaxcomplexity.Theyweregoodprimitivesaroundwhichabettersyntaxcouldbeexposedtothedevelopers:enterasyncfunctions.

ES2017

28

Page 29: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Aquickexample

Codemakinguseofasynchronousfunctionscanbewrittenas

functiondoSomethingAsync(){

returnnewPromise(resolve=>{

setTimeout(()=>resolve('Ididsomething'),3000)

})

}

asyncfunctiondoSomething(){

console.log(awaitdoSomethingAsync())

}

console.log('Before')

doSomething()

console.log('After')

Theabovecodewillprintthefollowingtothebrowserconsole:

Before

After

Ididsomething//after3s

Multipleasyncfunctionsinseries

Asyncfunctionscanbechainedveryeasily,andthesyntaxismuchmorereadablethanwithplainpromises:

functionpromiseToDoSomething(){

returnnewPromise(resolve=>{

setTimeout(()=>resolve('Ididsomething'),10000)

})

}

asyncfunctionwatchOverSomeoneDoingSomething(){

constsomething=awaitpromiseToDoSomething()

returnsomething+'andIwatched'

}

asyncfunctionwatchOverSomeoneWatchingSomeoneDoingSomething(){

constsomething=awaitwatchOverSomeoneDoingSomething()

returnsomething+'andIwatchedaswell'

}

watchOverSomeoneWatchingSomeoneDoingSomething().then(res=>{

console.log(res)

})

ES2017

29

Page 30: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

SharedMemoryandAtomicsWebWorkersareusedtocreatemultithreadedprogramsinthebrowser.

Theyofferamessagingprotocolviaevents.SinceES2017,youcancreateasharedmemoryarraybetweenwebworkersandtheircreator,usinga SharedArrayBuffer.

Sinceit'sunknownhowmuchtimewritingtoasharedmemoryportiontakestopropagate,Atomicsareawaytoenforcethatwhenreadingavalue,anykindofwritingoperationiscompleted.

Anymoredetailonthiscanbefoundinthespecproposal,whichhassincebeenimplemented.

ES2017

30

Page 31: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES2018ECMAScriptisthestandarduponwhichJavaScriptisbased,andit'softenabbreviatedtoES.DiscovereverythingaboutECMAScript,andthelastfeaturesaddedinES2018,akaES9

ES2018isthelatestversionoftheECMAScriptstandard.

Whatarethenewthingsintroducedinit?

Rest/SpreadPropertiesES6introducedtheconceptofarestelementwhenworkingwitharraydestructuring:

constnumbers=[1,2,3,4,5]

[first,second,...others]=numbers

andspreadelements:

constnumbers=[1,2,3,4,5]

constsum=(a,b,c,d,e)=>a+b+c+d+e

constsum=sum(...numbers)

ES2018introducesthesamebutforobjects.

Restproperties:

const{first,second,...others}={first:1,second:2,third:3,fourth:4,fifth:5

}

first//1

second//2

others//{third:3,fourth:4,fifth:5}

Spreadpropertiesallowtocreateanewobjectbycombiningthepropertiesoftheobjectpassedafterthespreadoperator:

constitems={first,second,...others}

items//{first:1,second:2,third:3,fourth:4,fifth:5}

Asynchronousiteration

ES2018

31

Page 32: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thenewconstruct for-await-ofallowsyoutouseanasynciterableobjectastheloopiteration:

forawait(constlineofreadLines(filePath)){

console.log(line)

}

Sincethisuses await,youcanuseitonlyinside asyncfunctions,likeanormal await(seeasync/await)

Promise.prototype.finally()Whenapromiseisfulfilled,successfullyitcallsthe then()methods,oneafteranother.

Ifsomethingfailsduringthis,the then()methodsarejumpedandthe catch()methodisexecuted.

finally()allowyoutorunsomecoderegardlessofthesuccessfulornotsuccessfulexecutionofthepromise:

fetch('file.json')

.then(data=>data.json())

.catch(error=>console.error(error))

.finally(()=>console.log('finished'))

RegularExpressionimprovements

RegExplookbehindassertions:matchastringdependingonwhatprecedesit

Thisisalookahead:youuse ?=tomatchastringthat'sfollowedbyaspecificsubstring:

/Roger(?=Waters)/

/Roger(?=Waters)/.test('Rogerismydog')//false

/Roger(?=Waters)/.test('RogerismydogandRogerWatersisafamousmusician')//true

?!performstheinverseoperation,matchingifastringisnotfollowedbyaspecificsubstring:

/Roger(?!Waters)/

/Roger(?!Waters)/.test('Rogerismydog')//true

/Roger(?!Waters)/.test('RogerWatersisafamousmusician')//false

ES2018

32

Page 33: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Lookaheadsusethe ?=symbol.Theywerealreadyavailable.

Lookbehinds,anewfeature,uses ?<=.

/(?<=Roger)Waters/

/(?<=Roger)Waters/.test('PinkWatersismydog')//false

/(?<=Roger)Waters/.test('RogerismydogandRogerWatersisafamousmusician')//true

Alookbehindisnegatedusing ?<!:

/(?<!Roger)Waters/

/(?<!Roger)Waters/.test('PinkWatersismydog')//true

/(?<!Roger)Waters/.test('RogerismydogandRogerWatersisafamousmusician')//false

Unicodepropertyescapes \p{…}and \P{…}

Inaregularexpressionpatternyoucanuse \dtomatchanydigit, \stomatchanycharacterthat'snotawhitespace, \wtomatchanyalphanumericcharacter,andsoon.

ThisnewfeatureextendsthisconcepttoallUnicodecharactersintroducing \p{}andisnegation \P{}.

Anyunicodecharacterhasasetofproperties.Forexample Scriptdeterminesthelanguagefamily, ASCIIisabooleanthat'strueforASCIIcharacters,andsoon.Youcanputthispropertyinthegraphparentheses,andtheregexwillcheckforthattobetrue:

/^\p{ASCII}+$/u.test('abc')//✅

/^\p{ASCII}+$/u.test('ABC@')//✅

/^\p{ASCII}+$/u.test('ABC ')//❌

ASCII_Hex_Digitisanotherbooleanproperty,thatchecksifthestringonlycontainsvalidhexadecimaldigits:

/^\p{ASCII_Hex_Digit}+$/u.test('0123456789ABCDEF')//✅

/^\p{ASCII_Hex_Digit}+$/u.test('h')//❌

Therearemanyotherbooleanproperties,whichyoujustcheckbyaddingtheirnameinthegraphparentheses,including Uppercase, Lowercase, White_Space, Alphabetic, Emojiandmore:

/^\p{Lowercase}$/u.test('h')//✅

/^\p{Uppercase}$/u.test('H')//✅

ES2018

33

Page 34: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

/^\p{Emoji}+$/u.test('H')//❌

/^\p{Emoji}+$/u.test(' ')//✅

Inadditiontothosebinaryproperties,youcancheckanyoftheunicodecharacterpropertiestomatchaspecificvalue.Inthisexample,Icheckifthestringiswritteninthegreekorlatinalphabet:

/^\p{Script=Greek}+$/u.test('ελληνικά')//✅

/^\p{Script=Latin}+$/u.test('hey')//✅

Readmoreaboutallthepropertiesyoucanusedirectlyontheproposal.

Namedcapturinggroups

InES2018acapturinggroupcanbeassignedtoaname,ratherthanjustbeingassignedaslotintheresultarray:

constre=/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/

constresult=re.exec('2015-01-02')

//result.groups.year==='2015';

//result.groups.month==='01';

//result.groups.day==='02';

The sflagforregularexpressions

The sflag,shortforsingleline,causesthe .tomatchnewlinecharactersaswell.Withoutit,thedotmatchesregularcharactersbutnotthenewline:

/hi.welcome/.test('hi\nwelcome')//false

/hi.welcome/s.test('hi\nwelcome')//true

ES2018

34

Page 35: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

CodingstyleThisJavaScriptCodingStyleisthesetofconventionsIuseeverydaywhenusingJavaScript.It'salivedocument,withthemainsetofrulesIfollow

Acodingstyleisanagreementwithyourselfandyourteam,tokeepconsistencyonaproject.

Anifyoudon'thaveateam,it'sanagreementwithyou,toalwayskeepyourcodeuptoyourstandards.

Havingfixedrulesonyourcodewritingformathelpsalotinordertohaveamorereadableandmanagedcode.

PopularStyleGuidesThereareaquiteafewofthemaround,herearethe2mostcommononesintheJavaScriptworld:

TheGoogleJavaScriptStyleGuideTheAirBnbJavaScriptStyleGuide

It'suptoyoutofollowoneofthose,orcreateyourownstyleguide.

BeconsistentwiththeprojectyouworkonEvenifyoupreferasetofstyles,whenworkingonaprojectyoushouldusethatprojectstyle.

AnOpenSourceprojectonGitHubmightfollowasetofrules,anotherprojectyouworkonwithateammightfollowanentirelydifferentone.

Prettierisanawesometoolthatenforcescodeformatting,useit.

MyownpreferencesMyowntakeonJavaScriptstyleis:

AlwaysusethelatestESversion.UseBabelifoldbrowsersupportisnecessary.

Indentation:usespacesinsteadoftabs,indentusing2spaces.

Semicolons:don'tusesemicolons.

Codingstyle

35

Page 36: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Linelength:trytocutlinesat80chars,ifpossible.

InlineComments:useinlinecommentsinyourcode.Useblockcommentsonlytodocument.

Nodeadcode:Don'tleaveoldcodecommented,"justincase"itwillbeusefullater.Keeponlythecodeyouneednow,versioncontrol/yournotesappismeantforthis.

Onlycommentwhenuseful:Don'taddcommentsthatdon'thelpunderstandwhatthecodeisdoing.Ifthecodeisself-explainingthroughtheuseofgoodvariableandfunctionnaming,andJSDocfunctioncomments,don'taddacomment.

Variabledeclarations:alwaysdeclarevariablestoavoidpollutingtheglobalobject.Neveruse var.Defaultto const,onlyuse letifyoureassignthevariable.

Constants:declareallconstantsinCAPS.Use _toseparatewordsina VARIABLE_NAME.

Functions:usearrowfunctionsunlessyouhaveaspecificreasontouseregularfunctions,likeinobjectmethodsorconstructors,duetohow thisworks.Declarethemasconst,anduseimplicitreturnsifpossible.

consttest=(a,b)=>a+b

constanother=a=>a+2

Feelfreetousenestedfunctionstohidehelperfunctionstotherestofthecode.

Names:functionnames,variablenamesandmethodnamesalwaysstartwithalowercaseletter(unlessyouidentifythemasprivate,readbelow),andarecamelCased.Onlyconstructorfunctionsandclassnamesshouldstartcapitalized.Ifyouuseaframeworkthatrequiresspecificconventions,changeyourhabitsaccordingly.Filenamesshouldallbelowercase,withwordsseparatedby -.

Statement-specificformatsandrules:

if

if(condition){

statements

}

if(condition){

statements

}else{

statements

}

if(condition){

statements

}elseif(condition){

Codingstyle

36

Page 37: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

statements

}else{

statements

}

for

Alwaysinitializethelengthintheinitializationtocacheit,don'tinsertitinthecondition.

Avoidusing forinexceptwithusedinconjunctionwith .hasOwnProperty().Prefer forof(seeJavaScriptLoops)

for(initialization;condition;update){

statements

}

while

while(condition){

statements

}

do

do{

statements

}while(condition);

switch

switch(expression){

caseexpression:

statements

default:

statements

}

try

try{

statements

}catch(variable){

statements

}

try{

statements

}catch(variable){

Codingstyle

37

Page 38: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

statements

}finally{

statements

}

Whitespace:usewhitespacewiselytoimprovereadability:putawhitespaceafterakeywordfollowedbya (;before&afterabinaryoperation( +, -, /, *, &&..);insidetheforstatement,aftereach ;toseparateeachpartofthestatement;aftereach ,.

Newlines:usenewlinestoseparateblocksofcodethatperformlogicallyrelatedoperations.

Quotesfavorsinglequotes 'insteadofdoublequotes ".DoublequotesareastandardinHTMLattributes,sousingsinglequoteshelpsremoveproblemswhendealingwithHTMLstrings.Usetemplateliteralswhenappropriateinsteadofvariableinterpolation.

Codingstyle

38

Page 39: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

LexicalStructureAdeepdiveintothebuildingblocksofJavaScript:unicode,semicolons,whitespace,casesensitivity,comments,literals,identifiersandreservedwords

UnicodeJavaScriptiswritteninUnicode.ThismeansyoucanuseEmojisasvariablenames,butmoreimportantly,youcanwriteidentifiersinanylanguage,forexampleJapaneseorChinese,withsomerules.

SemicolonsJavaScripthasaveryC-likesyntax,andyoumightseelotsofcodesamplesthatfeaturesemicolonsattheendofeachline.

Semicolonsaren'tmandatory,andJavaScriptdoesnothaveanyproblemincodethatdoesnotusethem,andlatelymanydevelopers,especiallythosecomingfromlanguagesthatdonothavesemicolons,startedavoidingusingthem.

Youjustneedtoavoiddoingstrangethingsliketypingstatementsonmultiplelines

return

variable

orstartingalinewithparentheses( [or ()andyou'llbesafe99.9%ofthetimes(andyourlinterwillwarnyou).

Itgoestopersonalpreference,andlatelyIhavedecidedtoneveradduselesssemicolons,soonthissiteyou'llneverseethem.

WhitespaceJavaScriptdoesnotconsiderwhitespacemeaningful.Spacesandlinebreakscanbeaddedinanyfashionyoumightlike,eventhoughthisisintheory.

Inpractice,youwillmostlikelykeepawelldefinedstyleandadheretowhatpeoplecommonlyuse,andenforcethisusingalinterorastyletoolsuchasPrettier.

LexicalStructure

39

Page 40: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ForexampleIliketoalways2characterstoindent.

CasesensitiveJavaScriptiscasesensitive.Avariablenamed somethingisdifferentfrom Something.

Thesamegoesforanyidentifier.

CommentsYoucanusetwokindofcommentsinJavaScript:

/**/

//

Thefirstcanspanovermultiplelinesandneedstobeclosed.

Thesecondcommentseverythingthat'sonitsright,onthecurrentline.

LiteralsandIdentifiersWedefineasliteralavaluethatiswritteninthesourcecode,forexampleanumber,astring,abooleanoralsomoreadvancedconstructs,likeObjectLiteralsorArrayLiterals:

5

'Test'

true

['a','b']

{color:'red',shape:'Rectangle'}

Anidentifierisasequenceofcharactersthatcanbeusedtoidentifyavariable,afunction,anobject.Itcanstartwithaletter,thedollarsign $oranunderscore _,anditcancontaindigits.UsingUnicode,alettercanbeanyallowedchar,forexampleanemoji .

Test

test

TEST

_test

Test1

$test

LexicalStructure

40

Page 41: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ThedollarsigniscommonlyusedtoreferenceDOMelements.

ReservedwordsYoucan'tuseasidentifiersanyofthefollowingwords:

break

do

instanceof

typeof

case

else

new

var

catch

finally

return

void

continue

for

switch

while

debugger

function

this

with

default

if

throw

delete

in

try

class

enum

extends

super

const

export

import

implements

let

private

public

interface

package

protected

static

yield

becausetheyarereservedbythelanguage.

LexicalStructure

41

Page 42: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

LexicalStructure

42

Page 43: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

VariablesAvariableisaliteralassignedtoanidentifier,soyoucanreferenceanduseitlaterintheprogram.LearnhowtodeclareonewithJavaScript

IntroductiontoJavaScriptVariablesAvariableisaliteralassignedtoanidentifier,soyoucanreferenceanduseitlaterintheprogram.

VariablesinJavaScriptdonothaveanytypeattached.Onceyouassignaspecificliteraltypetoavariable,youcanlaterreassignthevariabletohostanyothertype,withouttypeerrorsoranyissue.

ThisiswhyJavaScriptissometimesreferencedas"untyped".

Avariablemustbedeclaredbeforeyoucanuseit.Thereare3waystodoit,using var, letor const,andthose3waysdifferinhowyoucaninteractwiththevariablelateron.

Using varUntilES2015, varwastheonlyconstructavailablefordefiningvariables.

vara=0

Ifyouforgettoadd varyouwillbeassigningavaluetoanundeclaredvariable,andtheresultsmightvary.

Inmodernenvironments,withstrictmodeenabled,youwillgetanerror.Inolderenvironments(orwithstrictmodedisabled)thiswillsimplyinitializethevariableandassignittotheglobalobject.

Ifyoudon'tinitializethevariablewhenyoudeclareit,itwillhavethe undefinedvalueuntilyouassignavaluetoit.

vara//typeofa==='undefined'

Youcanredeclarethevariablemanytimes,overridingit:

vara=1

Variables

43

Page 44: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

vara=2

Youcanalsodeclaremultiplevariablesatonceinthesamestatement:

vara=1,b=2

Thescopeistheportionofcodewherethevariableisvisible.

Avariableinitializedwith varoutsideofanyfunctionisassignedtotheglobalobject,hasaglobalscopeandisvisibleeverywhere.Avariableinitializedwith varinsideafunctionisassignedtothatfunction,it'slocalandisvisibleonlyinsideit,justlikeafunctionparameter.

Anyvariabledefinedintoafunctionwiththesamenameofaglobalvariabletakesprecedenceovertheglobalvariable,shadowingit.

It'simportanttounderstandthatablock(identifiedbyapairofcurlybraces)doesnotdefineanewscope.Anewscopeisonlycreatedwhenafunctioniscreated,because varhasnotblockscope,butfunctionscope.

Insideafunction,anyvariabledefinedinitisvisiblethroughoutallthefunctioncode,evenifthevariableisdeclaredattheendofthefunctionitcanstillbereferencedinthebeginning,becauseJavaScriptbeforeexecutingthecodeactuallymovesallvariablesontop(somethingthatiscalledhoisting).Toavoidconfusion,alwaysdeclarevariablesatthebeginningofafunction.

Using letletisanewfeatureintroducedinES2015andit'sessentiallyablockscopedversionofvar.Itsscopeislimitedtotheblock,statementorexpressionwhereit'sdefined,andallthecontainedinnerblocks.

ModernJavaScriptdevelopersmightchoosetoonlyuse letandcompletelydiscardtheuseof var.

If letseemsanobscureterm,justread letcolor='red'asletthecolorberedandallhasmuchmoresense

Defining letoutsideofanyfunction-contraryto var-doesnotcreateaglobalvariable.

Using const

Variables

44

Page 45: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Variablesdeclaredwith varor letcanbechangedlateronintheprogram,andreassigned.Aoncea constisinitialized,itsvaluecanneverbechangedagain,anditcan'tbereassignedtoadifferentvalue.

consta='test'

Wecan'tassignadifferentliteraltothe aconst.Wecanhowevermutate aifit'sanobjectthatprovidesmethodsthatmutateitscontents.

constdoesnotprovideimmutability,justmakessurethatthereferencecan'tbechanged.

consthasblockscope,sameas let.

ModernJavaScriptdevelopersmightchoosetoalwaysuse constforvariablesthatdon'tneedtobereassignedlaterintheprogram.

Why?Becauseweshouldalwaysusethesimplestconstructavailabletoavoidmakingerrorsdowntheroad.

Variables

45

Page 46: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TypesYoumightsometimesreadthatJSisuntyped,butthat'sincorrect.It'struethatyoucanassignallsortsofdifferenttypestoavariable,butJavaScripthastypes.Inparticular,itprovidesprimitivetypes,andobjecttypes.

PrimitivetypesPrimitivetypesare

NumbersStringsBooleans

Andtwospecialtypes:

nullundefined

Let'sseethemindetailinthenextsections.

NumbersInternally,JavaScripthasjustonetypefornumbers:everynumberisafloat.

Anumericliteralisanumberrepresentedinthesourcecode,amddependingonhowit'swritten,itcanbeanintegerliteralorafloatingpointliteral.

Integers:

10

5354576767321

0xCC//hex

Floats:

3.14

.1234

5.2e4//5.2*10^4

Strings

Types

46

Page 47: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Astringtypeisasequenceofcharacters.It'sdefinedinthesourcecodeasastringliteral,whichisenclosedinquotesordoublequotes

'Astring'

"Anotherstring"

Stringscanspanacrossmultiplelinesbyusingthebackslash

"A\

string"

Astringcancontainescapesequencesthatcanbeinterpretedwhenthestringisprinted,like\ntocreateanewline.Thebackslashisalsousefulwhenyouneedtoenterforexampleaquoteinastringenclosedinquotes,topreventthechartobeinterpretedasaclosingquote:

'I\'madeveloper'

Stringscanbejoinedusingthe+operator:

"A"+"string"

Templatestrings

IntroducedinES2015,templatestringsarestringliteralsthatallowamorepowerfulwaytodefinestrings.

`astring`

Youcanperformstringsubstitution,embeddingtheresultofanyJSexpression:

`astringwith${something}`

`astringwith${something+somethingElse}`

`astringwith${obj.something()}`

Youcanhavemultilinestringseasily:

`astring

with

${something}`

Booleans

Types

47

Page 48: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

JavaScriptdefinestworeservedwordsforbooleans:trueandfalse.Manycomparisionoperations == === < >(andsoon)returneitheroneortheother.

if, whilestatementsandothercontrolstructuresusebooleanstodeterminetheflowoftheprogram.

Theydon'tjustaccepttrueorfalse,butalsoaccepttruthyandfalsyvalues.

Falsyvalues,valuesinterpretedasfalse,are

0

-0

NaN

undefined

null

''//emptystring

Alltherestisconsideredatruthyvalue.

nullnullisaspecialvaluethatindicatestheabsenceofavalue.

It'sacommonconceptinotherlanguagesaswell,canbeknownas nilor NoneinPythonforexample.

undefinedundefinedindicatesthatavariablehasnotbeeninitializedandthevalueisabsent.

It'scommonlyreturnedbyfunctionswithno returnvalue.Whenafunctionacceptsaparameterbutthat'snotsetbythecaller,it'sundefined.

Todetectifavalueis undefined,youusetheconstruct:

typeofvariable==='undefined'

ObjecttypesAnythingthat'snotaprimitivetypeisanobjecttype.

Types

48

Page 49: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Functions,arraysandwhatwecallobjectsareobjecttypes.Theyarespecialontheirown,buttheyinheritmanypropertiesofobjects,likehavingpropertiesandalsohavingmethodsthatcanactonthoseproperties.

Types

49

Page 50: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ExpressionsExpressionsareunitsofcodethatcanbeevaluatedandresolvetoavalue.ExpressionsinJScanbedividedincategories.

ArithmeticexpressionsUnderthiscategorygoallexpressionsthatevaluatetoanumber:

1/2

i++

i-=2

i*2

StringexpressionsExpressionsthatevaluatetoastring:

'A'+'string'

'A'+='string'

PrimaryexpressionsUnderthiscategorygovariablereferences,literalsandconstants:

2

0.02

'something'

true

false

this//thecurrentobject

undefined

i//whereiisavariableoraconstant

butalsosomelanguagekeywords:

function

class

function*//thegeneratorfunction

yield//thegeneratorpauser/resumer

yield*//delegatetoanothergeneratororiterator

Expressions

50

Page 51: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

asyncfunction*//asyncfunctionexpression

await//asyncfunctionpause/resume/waitforcompletion

/pattern/i//regex

()//grouping

Arrayandobjectinitializersexpressions

[]//arrayliteral

{}//objectliteral

[1,2,3]

{a:1,b:2}

{a:{b:1}}

LogicalexpressionsLogicalexpressionsmakeuseoflogicaloperatorsandresolvetoabooleanvalue:

a&&b

a||b

!a

Left-hand-sideexpressions

new//createaninstanceofaconstructor

super//callstheparentconstructor

...obj//expressionusingthespreadoperator

Propertyaccessexpressions

object.property//referenceaproperty(ormethod)ofanobject

object[property]

object['property']

Objectcreationexpressions

newobject()

newa(1)

newMyRectangle('name',2,{a:4})

Expressions

51

Page 52: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Functiondefinitionexpressions

function(){}

function(a,b){returna*b}

(a,b)=>a*b

a=>a*2

()=>{return2}

InvocationexpressionsThesyntaxforcallingafunctionormethod

a.x(2)

window.resize()

Expressions

52

Page 53: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

PrototypalinheritanceJavaScriptisquiteuniqueinthepopularprogramminglanguageslandscapebecauseofitsusageofprototypalinheritance.Let'sfindoutwhatthatmeans

JavaScriptisquiteuniqueinthepopularprogramminglanguageslandscapebecauseofitsusageofprototypalinheritance.

Whilemostobject-orientedlanguagesuseaclass-basedinheritancemodel,JavaScriptisbasedontheprototypeinheritancemodel.

Whatdoesthismean?

EverysingleJavaScriptobjecthasaproperty,called prototype,whichpointstoadifferentobject.

Thisdifferentobjectistheobjectprototype.

Ourobjectusesthatobjectprototypetoinheritpropertiesandmethods.

Sayyouhaveanobjectcreatedusingtheobjectliteralsyntax:

constcar={}

oronecreatedwiththe newObjectsyntax:

constcar=newObject()

inanycase,theprototypeof caris Object:

Ifyouinitializeanarray,whichisanobject:

constlist=[]

//or

constlist=newArray()

theprototypeis Array.

Youcanverifythisbycheckingthe __proto__getter:

car.__proto__==Object.prototype//true

car.__proto__==newObject().__proto__//true

list.__proto__==Object.prototype//false

list.__proto__==Array.prototype//true

list.__proto__==newArray().__proto__//true

Prototypalinheritance

53

Page 54: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Iusethe __proto__propertyhere,whichisnon-standardbutwidelyimplementedinbrowsers.Amorereliablewaytogetaprototypeistouse Object.getPrototypeOf(newObject())

Allthepropertiesandmethodsoftheprototypeareavailabletotheobjectthathasthatprototype:

Object.prototypeisthebaseprototypeofalltheobjects:

Array.prototype.__proto__==Object.prototype

Ifyouwonderwhat'stheprototypeoftheObject.prototype,thereisnoprototype.It'saspecialsnowflake❄ .

Theaboveexampleyousawisanexampleoftheprototypechainatwork.

IcanmakeanobjectthatextendsArrayandanyobjectIinstantiateusingit,willhaveArrayandObjectinitsprototypechainandinheritpropertiesandmethodsfromalltheancestors.

Inadditiontousingthe newoperatortocreateanobject,orusingtheliteralssyntaxforobjectsandarrays,youcaninstantiateanobjectusing Object.create().

Thefirstargumentpassedistheobjectusedasprototype:

Prototypalinheritance

54

Page 55: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

constcar=Object.create({})

constlist=Object.create(Array)

Youcanchecktheprototypeofanobjectusingthe isPrototypeOf()method:

Array.isPrototypeOf(list)//true

Payattentionbecauseyoucaninstantiateanarrayusing

constlist=Object.create(Array.prototype)

andinthiscase Array.isPrototypeOf(list)isfalse,whileArray.prototype.isPrototypeOf(list)istrue.

Prototypalinheritance

55

Page 56: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ClassesIn2015theECMAScript6(ES6)standardintroducedclasses.Learnallaboutthem

In2015theECMAScript6(ES6)standardintroducedclasses.

Beforethat,JavaScriptonlyhadaquiteuniquewaytoimplementinheritance.Itsprototypalinheritance,whileinmyopiniongreat,wasdifferentfromanyotherpopularprogramminglanguage.

PeoplecomingfromJavaorPythonorotherlanguageshadahardtimeunderstandingtheintricaciesofprototypalinheritance,sotheECMAScriptcommitteedecidedtointroduceasyntacticsugarontopofthem,andresemblehowclasses-basedinheritanceworksinotherpopularimplementations.

Thisisimportant:JavaScriptunderthehoodsisstillthesame,andyoucanaccessanobjectprototypeintheusualway.

AclassdefinitionThisishowaclasslooks.

classPerson{

constructor(name){

this.name=name

}

hello(){

return'Hello,Iam'+this.name+'.'

}

}

Aclasshasanidentifier,whichwecanusetocreatenewobjectsusing newClassIdentifier().

Whentheobjectisinitialized,the constructormethodiscalled,withanyparameterspassed.

Aclassalsohasasmanymethodsasitneeds.Inthiscase helloisamethodandcanbecalledonallobjectsderivedfromthisclass:

constflavio=newPerson('Flavio')

flavio.hello()

Classes

56

Page 57: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ClassesinheritanceAclasscanextendanotherclass,andobjectsinitializedusingthatclassinheritallthemethodsofbothclasses.

Iftheinheritedclasshasamethodwiththesamenameasoneoftheclasseshigherinthehierarchy,theclosestmethodtakesprecedence:

classProgrammerextendsPerson{

hello(){

returnsuper.hello()+'Iamaprogrammer.'

}

}

constflavio=newProgrammer('Flavio')

flavio.hello()

(theaboveprogramprints"Hello,IamFlavio.Iamaprogrammer.")

Classesdonothaveexplicitclassvariabledeclarations,butyoumustinitializeanyvariableintheconstructor.

Insideaclass,youcanreferencetheparentclasscalling super().

StaticmethodsNormallymethodsaredefinedontheinstance,notontheclass.

Staticmethodsareexecutedontheclassinstead:

classPerson{

staticgenericHello(){

return'Hello'

}

}

Person.genericHello()//Hello

PrivatemethodsJavaScriptdoesnothaveabuilt-inwaytodefineprivateorprotectedmethods.

Thereareworkarounds,butIwon'tdescribethemhere.

Classes

57

Page 58: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

GettersandsettersYoucanaddmethodsprefixedwith getor settocreateagetterandsetter,whicharetwodifferentpiecesofcodethatareexecutebasedonwhatyouaredoing:accessingthevariable,ormodifyingitsvalue.

classPerson{

constructor(name){

this.name=name

}

setname(value){

this.name=value

}

getname(){

returnthis.name

}

}

Ifyouonlyhaveagetter,thepropertycannotbeset,andanyattemptatdoingsowillbeignored:

classPerson{

constructor(name){

this.name=name

}

getname(){

returnthis.name

}

}

Ifyouonlyhaveasetter,youcanchangethevaluebutnotaccessitfromtheoutside:

classPerson{

constructor(name){

this.name=name

}

setname(value){

this.name=value

}

}

Classes

58

Page 59: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Classes

59

Page 60: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ExceptionsWhenthecoderunsintoanunexpectedproblem,theJavaScriptidiomaticwaytohandlethissituationisthroughexceptions

Whenthecoderunsintoanunexpectedproblem,theJavaScriptidiomaticwaytohandlethissituationisthroughexceptions.

CreatingexceptionsAnexceptioniscreatedusingthe throwkeyword:

throwvalue

where valuecanbeanyJavaScriptvalueincludingastring,anumberoranobject.

AssoonasJavaScriptexecutesthisline,thenormalprogramflowishaltedandthecontrolisheldbacktothenearestexceptionhandler.

HandlingexceptionsAnexceptionhandlerisa try/ catchstatement.

Anyexceptionraisedinthelinesofcodeincludedinthe tryblockishandledinthecorresponding catchblock:

try{

//linesofcode

}catch(e){

}

einthisexampleistheexceptionvalue.

Youcanaddmultiplehandlers,thatcancatchdifferentkindsoferrors.

finally

Exceptions

60

Page 61: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TocompletethisstatementJavaScripthasanotherstatementcalled finally,whichcontainscodethatisexecutedregardlessoftheprogramflow,iftheexceptionwashandledornot,iftherewasanexceptionoriftherewasn't:

try{

//linesofcode

}catch(e){

}finally{

}

Youcanuse finallywithouta catchblock,toserveasawaytocleanupanyresourceyoumighthaveopenedinthe tryblock,likefilesornetworkrequests:

try{

//linesofcode

}finally{

}

Nested tryblockstryblockscanbenested,andanexceptionisalwayshandledinthenearestcatchblock:

try{

//linesofcode

try{

//otherlinesofcode

}finally{

//otherlinesofcode

}

}catch(e){

}

Ifanexceptionisraisedintheinner try,it'shandledintheouter catchblock.

Exceptions

61

Page 62: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

SemicolonsJavaScriptsemicolonsareoptional.Ipersonallylikeavoidingusingsemicolonsinmycode,butmanypeoplepreferthem.

SemicolonsinJavaScriptdividethecommunity.Someprefertousethemalways,nomatterwhat.Othersliketoavoidthem.

Afterusingsemicolonsforyears,inthefallof2017Idecidedtotryavoidingthemasneeded,andIdidsetupPrettiertoautomaticallyremovesemicolonsfrommycode,unlessthereisaparticularcodeconstructthatrequiresthem.

NowIfinditnaturaltoavoidsemicolons,Ithinkthecodelooksbetterandit'scleanertoread.

ThisisallpossiblebecauseJavaScriptdoesnotstrictlyrequiresemicolons.Whenthereisaplacewhereasemicolonwasneeded,itaddsitbehindthescenes.

TheprocessthatdoesthisiscalledAutomaticSemicolonInsertion.

It'simportanttoknowtherulesthatpowersemicolons,toavoidwritingcodethatwillgeneratebugsbecausedoesnotbehavelikeyouexpect.

TherulesofJavaScriptAutomaticSemicolonInsertionTheJavaScriptparserwillautomaticallyaddasemicolonwhen,duringtheparsingofthesourcecode,itfindstheseparticularsituations:

1. whenthenextlinestartswithcodethatbreaksthecurrentone(codecanspawnonmultiplelines)

2. whenthenextlinestartswitha },closingthecurrentblock3. whentheendofthesourcecodefileisreached4. whenthereisa returnstatementonitsownline5. whenthereisa breakstatementonitsownline6. whenthereisa throwstatementonitsownline7. whenthereisa continuestatementonitsownline

ExamplesofcodethatdoesnotdowhatyouthinkBasedonthoserules,herearesomeexamples.

Semicolons

62

Page 63: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Takethis:

consthey='hey'

constyou='hey'

constheyYou=hey+''+you

['h','e','y'].forEach((letter)=>console.log(letter))

You'llgettheerror UncaughtTypeError:Cannotreadproperty'forEach'ofundefinedbecausebasedonrule 1JavaScripttriestointerpretthecodeas

consthey='hey';

constyou='hey';

constheyYou=hey+''+you['h','e','y'].forEach((letter)=>console.log(letter))

Suchpieceofcode:

(1+2).toString()

prints "3".

consta=1

constb=2

constc=a+b

(a+b).toString()

insteadraisesa TypeError:bisnotafunctionexception,becauseJavaScripttriestointerpretitas

consta=1

constb=2

constc=a+b(a+b).toString()

Anotherexamplebasedonrule4:

(()=>{

return

{

color:'white'

}

})()

Semicolons

63

Page 64: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

You'dexpectthereturnvalueofthisimmediately-invokedfunctiontobeanobjectthatcontainsthe colorproperty,butit'snot.Instead,it's undefined,becauseJavaScriptinsertsasemicolonafter return.

Insteadyoushouldputtheopeningbracketrightafter return:

(()=>{

return{

color:'white'

}

})()

You'dthinkthiscodeshows'0'inanalert:

1+1

-1+1===0?alert(0):alert(2)

butitshows2instead,becauseJavaScriptperrule1interpretsitas:

1+1-1+1===0?alert(0):alert(2)

ConclusionBecareful.Somepeopleareveryopinionatedonsemicolons.Idon'tcarehonestly,thetoolgivesustheoptionnottouseit,sowecanavoidsemicolons.

I'mnotsuggestinganything,otherthanpickingyourowndecision.

Wejustneedtopayabitofattention,evenifmostofthetimesthosebasicscenariosnevershowupinyourcode.

Picksomerules:

becarefulwith returnstatements.Ifyoureturnsomething,additonthesamelineasthereturn(samefor break, throw, continue)neverstartalinewithparentheses,thosemightbeconcatenatedwiththepreviouslinetoformafunctioncall,orarrayelementreference

Andultimately,alwaystestyourcodetomakesureitdoeswhatyouwant

Semicolons

64

Page 65: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Semicolons

65

Page 66: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

QuotesAnoverviewofthequotesallowedinJavaScriptandtheiruniquefeatures

JavaScriptallowsyoutouse3typesofquotes:

singlequotesdoublequotesbackticks

Thefirst2areessentiallythesame:

consttest='test'

constbike="bike"

There'slittletonodifferenceinusingoneortheother.Theonlydifferenceliesinhavingtoescapethequotecharacteryouusetodelimitthestring:

consttest='test'

consttest='te\'st'

consttest='te"st'

consttest="te\"st"

consttest="te'st"

Therearevariousstyleguidesthatrecommendalwaysusingonestylevstheother.

Ipersonallyprefersinglequotesallthetime,andusedoublequotesonlyinHTML.

BackticksarearecentadditiontoJavaScript,sincetheywereintroducedwithES6in2015.

Theyhaveauniquefeature:theyallowmultilinestrings.

Multilinestringsarealsopossibleusingregularstrings,usingescapecharacters:

constmultilineString='Astring\nonmultiplelines'

Usingbackticks,youcanavoidusinganescapecharacter:

constmultilineString=`Astring

onmultiplelines`

Notjustthat.Youcaninterpolatevariablesusingthe ${}syntax:

constmultilineString=`Astring

Quotes

66

Page 67: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

on${1+1}lines`

ThosearecalledTemplateLiterals.

Quotes

67

Page 68: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TemplateLiteralsIntroducedinES2015,akaES6,TemplateLiteralsofferanewwaytodeclarestrings,butalsosomenewinterestingconstructswhicharealreadywidelypopular.

IntroductiontoTemplateLiteralsTemplateLiteralsareanewES2015/ES6featurethatallowyoutoworkwithstringsinanovelwaycomparedtoES5andbelow.

Thesyntaxatafirstglanceisverysimple,justusebackticksinsteadofsingleordoublequotes:

consta_string=`something`

Theyareuniquebecausetheyprovidealotoffeaturesthatnormalstringsbuiltwithquotes,inparticular:

theyofferagreatsyntaxtodefinemultilinestringstheyprovideaneasywaytointerpolatevariablesandexpressionsinstringstheyallowtocreateDSLswithtemplatetags

Let'sdiveintoeachoftheseindetail.

MultilinestringsPre-ES6,tocreateastringspannedovertwolinesyouhadtousethe \characterattheendofaline:

conststring='firstpart\

secondpart'

Thisallowstocreateastringon2lines,butit'srenderedonjustoneline:

firstpartsecondpart

Torenderthestringonmultiplelinesaswell,youexplicitlyneedtoadd \nattheendofeachline,likethis:

conststring='firstline\n\

TemplateLiterals

68

Page 69: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

secondline'

or

conststring='firstline\n'+

'secondline'

Templateliteralsmakemultilinestringsmuchsimpler.

Onceatemplateliteralisopenedwiththebacktick,youjustpressentertocreateanewline,withnospecialcharacters,andit'srenderedas-is:

conststring=`Hey

this

string

isawesome!`

Keepinmindthatspaceismeaningful,sodoingthis:

conststring=`First

Second`

isgoingtocreateastringlikethis:

First

Second

aneasywaytofixthisproblemisbyhavinganemptyfirstline,andappendingthetrim()methodrightaftertheclosingbacktick,whichwilleliminateanyspacebeforethefirstcharacter:

conststring=`

First

Second`.trim()

InterpolationTemplateliteralsprovideaneasywaytointerpolatevariablesandexpressionsintostrings.

Youdosobyusingthe ${...}syntax:

constvar='test'

TemplateLiterals

69

Page 70: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

conststring=`something${var}`//somethingtest

insidethe ${}youcanaddanything,evenexpressions:

conststring=`something${1+2+3}`

conststring2=`something${foo()?'x':'y'}`

TemplatetagsTaggedtemplatesisonefeaturesthatmightsoundlessusefulatfirstforyou,butit'sactuallyusedbylotsofpopularlibrariesaround,likeStyledComponentsorApollo,theGraphQLclient/serverlib,soit'sessentialtounderstandhowitworks.

InStyledComponentstemplatetagsareusedtodefineCSSstrings:

constButton=styled.button`

font-size:1.5em;

background-color:black;

color:white;

`;

InApollotemplatetagsareusedtodefineaGraphQLqueryschema:

constquery=gql`

query{

...

}

`

The styled.buttonand gqltemplatetagshighlightedinthoseexamplesarejustfunctions:

functiongql(literals,...expressions){

}

thisfunctionreturnsastring,whichcanbetheresultofanykindofcomputation.

literalsisanarraycontainingthetemplateliteralcontenttokenizedbytheexpressionsinterpolations.

expressionscontainsalltheinterpolations.

Ifwetakeanexampleabove:

TemplateLiterals

70

Page 71: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

conststring=`something${1+2+3}`

literalsisanarraywithtwoitems.Thefirstis something,thestringuntilthefirstinterpolation,andthesecondisanemptystring,thespacebetwenetheendofthefirstinterpolation(weonlyhaveone)andtheendofthestring.

expressionsinthiscaseisanarraywithasingleitem, 6.

Amorecomplexexampleis:

conststring=`something

another${'x'}

newline${1+2+3}

test`

inthiscase literalsisanarraywherethefirstitemis:

`something

another`

thesecondis:

`

newline`

andthethirdis:

`

test`

expressionsinthiscaseisanarraywithtwoitems, xand 6.

Thefunctionthatispassedthosevaluescandoanythingwiththem,andthisisthepowerofthiskindfeature.

Themostsimpleexampleisreplicatingwhatthestringinterpolationdoes,bysimplyjoiningliteralsand expressions:

constinterpolated=interpolate`Ipaid${10}€`

andthisishow interpolateworks:

functioninterpolate(literals,...expressions){

letstring=``

TemplateLiterals

71

Page 72: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

for(const[i,val]ofexpressions){

string+=literals[i]+val

}

string+=literals[literals.length-1]

returnstring

}

TemplateLiterals

72

Page 73: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

FunctionsLearnallaboutfunctions,fromthegeneraloverviewtothetinydetailsthatwillimprovehowyouusethem

IntroductionEverythinginJavaScripthappensinfunctions.

Afunctionisablockofcode,selfcontained,thatcanbedefinedonceandrunanytimesyouwant.

Afunctioncanoptionallyacceptparameters,andreturnsonevalue.

FunctionsinJavaScriptareobjects,aspecialkindofobjects:functionobjects.Theirsuperpowerliesinthefactthattheycanbeinvoked.

Inaddition,functionsaresaidtobefirstclassfunctionsbecausetheycanbeassignedtoavalue,andtheycanbepassedasargumentsandusedasareturnvalue.

Syntax

Functions

73

Page 74: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Let'sstartwiththe"old",pre-ES6/ES2015syntax.Here'safunctiondeclaration:

functiondosomething(foo){

//dosomething

}

(now,inpostES6/ES2015world,referredasaregularfunction)

Functionscanbeassignedtovariables(thisiscalledafunctionexpression):

constdosomething=function(foo){

//dosomething

}

Namedfunctionexpressionsaresimilar,butplaynicerwiththestackcalltrace,whichisusefulwhenanerroroccurs-itholdsthenameofthefunction:

constdosomething=functiondosomething(foo){

//dosomething

}

ES6/ES2015introducedarrowfunctions,whichareespeciallynicetousewhenworkingwithinlinefunctions,asparametersorcallbacks:

constdosomething=foo=>{

//dosomething

}

Arrowfunctionshaveanimportantdifferencefromtheotherfunctiondefinitionsabove,we'llseewhichonelaterasit'sanadvancedtopic.

ParametersAfunctioncanhaveoneormoreparameters.

constdosomething=()=>{

//dosomething

}

constdosomethingElse=foo=>{

//dosomething

}

constdosomethingElseAgain=(foo,bar)=>{

//dosomething

Functions

74

Page 75: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

}

StartingwithES6/ES2015,functionscanhavedefaultvaluesfortheparameters:

constdosomething=(foo=1,bar='hey')=>{

//dosomething

}

Thisallowsyoutocallafunctionwithoutfillingalltheparameters:

dosomething(3)

dosomething()

ES2018introducedtrailingcommasforparameters,afeaturethathelpsreducingbugsduetomissingcommaswhenmovingaroundparameters(e.g.movingthelastinthemiddle):

constdosomething=(foo=1,bar='hey')=>{

//dosomething

}

dosomething(2,'ho!')

Youcanwrapallyourargumentsinanarray,andusethespreadoperatorwhencallingthefunction:

constdosomething=(foo=1,bar='hey')=>{

//dosomething

}

constargs=[2,'ho!']

dosomething(...args)

Withmanyparameters,rememberingtheordercanbedifficult.Usingobjects,destructuringallowstokeeptheparameternames:

constdosomething=({foo=1,bar='hey'})=>{

//dosomething

console.log(foo)//2

console.log(bar)//'ho!'

}

constargs={foo:2,bar:'ho!'}

dosomething(args)

Returnvalues

Functions

75

Page 76: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Everyfunctionreturnsavalue,whichbydefaultis undefined.

Anyfunctionisterminatedwhenitslinesofcodeend,orwhentheexecutionflowfindsareturnkeyword.

WhenJavaScriptencountersthiskeyworditexitsthefunctionexecutionandgivescontrolbacktoitscaller.

Ifyoupassavalue,thatvalueisreturnedastheresultofthefunction:

constdosomething=()=>{

return'test'

}

constresult=dosomething()//result==='test'

Youcanonlyreturnonevalue.

Tosimulatereturningmultiplevalues,youcanreturnanobjectliteral,oranarray,anduseadestructuringassignmentwhencallingthefunction.

Usingarrays:

Functions

76

Page 77: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Usingobjects:

NestedfunctionsFunctionscanbedefinedinsideotherfunctions:

constdosomething=()=>{

constdosomethingelse=()=>{}

dosomethingelse()

return'test'

}

Functions

77

Page 78: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thenestedfunctionisscopedtotheoutsidefunction,andcannotbecalledfromtheoutside.

ObjectMethodsWhenusedasobjectproperties,functionsarecalledmethods:

constcar={

brand:'Ford',

model:'Fiesta',

start:function(){

console.log(`Started`)

}

}

car.start()

thisinArrowFunctionsThere'sanimportantbehaviorofArrowFunctionsvsregularFunctionswhenusedasobjectmethods.Considerthisexample:

constcar={

brand:'Ford',

model:'Fiesta',

start:function(){

console.log(`Started${this.brand}${this.model}`)

},

stop:()=>{

console.log(`Stopped${this.brand}${this.model}`)

}

}

The stop()methoddoesnotworkasyouwouldexpect.

Functions

78

Page 79: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thisisbecausethehandlingof thisisdifferentinthetwofunctionsdeclarationsstyle. thisinthearrowfunctionreferstotheenclosingfunctioncontext,whichinthiscaseisthe windowobject:

this,whichreferstothehostobjectusing function()

Functions

79

Page 80: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thisimpliesthatarrowfunctionsarenotsuitabletobeusedforobjectmethodsandconstructors(arrowfunctionconstructorswillactuallyraisea TypeErrorwhencalled).

IIFE,ImmediatelyInvocatedFunctionExpressionsAnIIFEisafunctionthat'simmediatelyexecutedrightafteritsdeclaration:

;(functiondosomething(){

console.log('executed')

})()

Youcanassigntheresulttoavariable:

constsomething=(functiondosomething(){

return'something'

})()

Theyareveryhandy,asyoudon'tneedtoseparatelycallthefunctionafteritsdefinition.

FunctionHoistingJavaScriptbeforeexecutingyourcodereordersitaccordingtosomerules.

Functionsinparticulararemovedatthetopoftheirscope.Thisiswhyit'slegaltowrite

dosomething()

functiondosomething(){

console.log('didsomething')

}

Internally,JavaScriptmovesthefunctionbeforeitscall,alongwithalltheotherfunctionsfoundinthesamescope:

Functions

80

Page 81: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

functiondosomething(){

console.log('didsomething')

}

dosomething()

Now,ifyouusenamedfunctionexpressions,sinceyou'reusingvariablessomethingdifferenthappens.Thevariabledeclarationishoisted,butnotthevalue,sonotthefunction.

dosomething()

constdosomething=functiondosomething(){

console.log('didsomething')

}

Notgoingtowork:

Thisisbecausewhathappensinternallyis:

constdosomething

dosomething()

dosomething=functiondosomething(){

console.log('didsomething')

}

Thesamehappensfor letdeclarations. vardeclarationsdonotworkeither,butwithadifferenterror:

Functions

81

Page 82: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thisisbecause vardeclarationsarehoistedandinitializedwith undefinedasavalue,whileconstand letarehoistedbutnotinitialized.

Functions

82

Page 83: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ArrowFunctionsArrowFunctionsareoneofthemostimpactfulchangesinES6/ES2015,andtheyarewidelyusednowadays.Theyslightlydifferfromregularfunctions.Findouthow

ArrowfunctionswereintroducedinES6/ECMAScript2015,andsincetheirintroductiontheychangedforeverhowJavaScriptcodelooks(andworks).

Inmyopinionthischangewassowelcomingthatyounowrarelyseeinmoderncodebasestheusageofthe functionkeyword.

Visually,it’sasimpleandwelcomechange,whichallowsyoutowritefunctionswithashortersyntax,from:

constmyFunction=functionfoo(){

//...

}

to

constmyFunction=()=>{

//...

}

Ifthefunctionbodycontainsjustasinglestatement,youcanomittheparenthesesandwriteallonasingleline:

constmyFunction=()=>doSomething()

Parametersarepassedintheparentheses:

constmyFunction=(param1,param2)=>doSomething(param1,param2)

Ifyouhaveone(andjustone)parameter,youcouldomittheparenthesescompletely:

constmyFunction=param=>doSomething(param)

Thankstothisshortsyntax,arrowfunctionsencouragetheuseofsmallfunctions.

Implicitreturn

ArrowFunctions

83

Page 84: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Arrowfunctionsallowyoutohaveanimplicitreturn:valuesarereturnedwithouthavingtousethe returnkeyword.

Itworkswhenthereisaon-linestatementinthefunctionbody:

constmyFunction=()=>'test'

myFunction()//'test'

Anotherexample,returninganobject(remembertowrapthecurlybracketsinparenthesestoavoiditbeingconsideredthewrappingfunctionbodybrackets):

constmyFunction=()=>({value:'test'})

myFunction()//{value:'test'}

How thisworksinarrowfunctionsthisisaconceptthatcanbecomplicatedtograsp,asitvariesalotdependingonthecontextandalsovariesdependingonthemodeofJavaScript(strictmodeornot).

It'simportanttoclarifythisconceptbecausearrowfunctionsbehaveverydifferentlycomparedtoregularfunctions.

Whendefinedasamethodofanobject,inaregularfunction thisreferstotheobject,soyoucando:

constcar={

model:'Fiesta',

manufacturer:'Ford',

fullName:function(){

return`${this.manufacturer}${this.model}`

}

}

calling car.fullName()willreturn "FordFiesta".

The thisscopewitharrowfunctionsisinheritedfromtheexecutioncontext.Anarrowfunctiondoesnotbind thisatall,soitsvaluewillbelookedupinthecallstack,sointhiscode car.fullName()willnotwork,andwillreturnthestring "undefinedundefined":

constcar={

model:'Fiesta',

manufacturer:'Ford',

fullName:()=>{

ArrowFunctions

84

Page 85: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

return`${this.manufacturer}${this.model}`

}

}

Duetothis,arrowfunctionsarenotsuitedasobjectmethods.

Arrowfunctionscannotbeusedasconstructorsaswell,wheninstantiatinganobjectwillraisea TypeError.

Thisiswhereregularfunctionsshouldbeusedinstead,whendynamiccontextisnotneeded.

Thisisalsoaproblemwhenhandlingevents.DOMEventlistenersset thistobethetargetelement,andifyourelyon thisinaneventhandler,aregularfunctionisnecessary:

constlink=document.querySelector('#link')

link.addEventListener('click',()=>{

//this===window

})

constlink=document.querySelector('#link')

link.addEventListener('click',function(){

//this===link

})

ArrowFunctions

85

Page 86: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ClosuresAgentleintroductiontothetopicofclosures,keytounderstandinghowJavaScriptfunctionswork

Ifyou'veeverwrittenafunctioninJavaScript,youalreadymadeuseofclosures.

It'sakeytopictounderstand,whichhasimplicationsonthethingsyoucando.

Whenafunctionisrun,it'sexecutedwiththescopethatwasinplacewhenitwasdefined,andnotwiththestatethat'sinplacewhenitisexecuted.

Thescopebasicallyisthesetofvariableswhicharevisible.

AfunctionremembersitsLexicalScope,andit'sabletoaccessvariablesthatweredefinedintheparentscope.

Inshort,afunctionhasanentirebaggageofvariablesitcanaccess.

Letmeimmediatelygiveanexampletoclarifythis.

constbark=dog=>{

constsay=`${dog}barked!`

;(()=>console.log(say))()

}

bark(`Roger`)

Closures

86

Page 87: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thislogstotheconsole Rogerbarked!,asexpected.

Whatifyouwanttoreturntheactioninstead:

constprepareBark=dog=>{

constsay=`${dog}barked!`

return()=>console.log(say)

}

constbark=prepareBark(`Roger`)

bark()

Thissnippetalsologstotheconsole Rogerbarked!.

Let'smakeonelastexample,whichreuses prepareBarkfortwodifferentdogs:

constprepareBark=dog=>{

constsay=`${dog}barked!`

return()=>{

console.log(say)

}

}

constrogerBark=prepareBark(`Roger`)

constsydBark=prepareBark(`Syd`)

rogerBark()

sydBark()

Thisprints

Rogerbarked!

Sydbarked!

Asyoucansee,thestateofthevariable sayislinkedtothefunctionthat'sreturnedfromprepareBark().

Alsonoticethatweredefineanew sayvariablethesecondtimewecall prepareBark(),butthatdoesnotaffectthestateofthefirst prepareBark()scope.

Thisishowaclosureworks:thefunctionthat'sreturnedkeepstheoriginalstateinitsscope.

Closures

87

Page 88: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ArraysJavaScriptarraysovertimegotmoreandmorefeatures,sometimesit'strickytoknowwhentousesomeconstructvsanother.Thispostaimstoexplainwhatyoushoulduse,asof2018

JavaScriptarraysovertimegotmoreandmorefeatures,sometimesit'strickytoknowwhentousesomeconstructvsanother.Thispostaimstoexplainwhatyoushouldusein2018.

Initializearray

consta=[]

consta=[1,2,3]

consta=Array.of(1,2,3)

consta=Array(6).fill(1)//initanarrayof6itemsofvalue1

Don'tusetheoldsyntax(justuseitfortypedarrays)

consta=newArray()//neveruse

consta=newArray(1,2,3)//neveruse

Arrays

88

Page 89: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Getlengthofthearray

constl=a.length

Iteratingthearray

Every

a.every(f)

Iterates auntil f()returnsfalse

Some

a.some(f)

Iterates auntil f()returnstrue

Iteratethearrayandreturnanewonewiththereturnedresultofafunction

constb=a.map(f)

Iterates aandbuildsanewarraywiththeresultofexecuting f()oneach aelement

Filteranarray

constb=a.filter(f)

Iterates aandbuildsanewarraywithelementsof athatreturnedtruewhenexecutingf()oneach aelement

Reduce

a.reduce((accumulator,currentValue,currentIndex,array)=>{

//...

Arrays

89

Page 90: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

},initialValue)

reduce()executesacallbackfunctiononalltheitemsofthearrayandallowstoprogressivelycomputearesult.If initialValueisspecified, accumulatorinthefirstiterationwillequaltothatvalue.

Example:

;[1,2,3,4].reduce((accumulator,currentValue,currentIndex,array)=>{

returnaccumulator*currentValue

},1)

//iteration1:1*1=>return1

//iteration2:1*2=>return2

//iteration3:2*3=>return6

//iteration4:6*4=>return24

//returnvalueis24

forEach

ES6

a.forEach(f)

Iterates fon awithoutawaytostop

Example:

a.forEach(v=>{

console.log(v)

})

for..of

ES6

for(letvofa){

console.log(v)

}

for

for(leti=0;i<a.length;i+=1){

//a[i]

Arrays

90

Page 91: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

}

Iterates a,canbestoppedusing returnor breakandaniterationcanbeskippedusingcontinue

@@iterator

ES6

Gettingtheiteratorfromanarrayreturnsaniteratorofvalues

consta=[1,2,3]

letit=a[Symbol.iterator]()

console.log(it.next().value)//1

console.log(it.next().value)//2

console.log(it.next().value)//3

.entries()returnsaniteratorofkey/valuepairs

letit=a.entries()

console.log(it.next().value)//[0,1]

console.log(it.next().value)//[1,2]

console.log(it.next().value)//[2,3]

.keys()allowstoiterateonthekeys:

letit=a.keys()

console.log(it.next().value)//0

console.log(it.next().value)//1

console.log(it.next().value)//2

.next()returns undefinedwhenthearrayends.Youcanalsodetectiftheiterationendedbylookingat it.next()whichreturnsa value,donepair. doneisalwaysfalseuntilthelastelement,whichreturns true.

Addingtoanarray

Addattheend

a.push(4)

Arrays

91

Page 92: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Addatthebeginning

a.unshift(0)

a.unshift(-2,-1)

Removinganitemfromanarray

Fromtheend

a.pop()

Fromthebeginning

a.shift()

Atarandomposition

a.splice(0,2)//getthefirst2items

a.splice(3,2)//getthe2itemsstartingfromindex3

Donotuse remove()asitleavesbehindundefinedvalues.

Removeandinsertinplace

a.splice(2,3,2,'a','b')//removes3itemsstartingfrom

//index2,andadds2items,

//stillstartingfromindex2

Joinmultiplearrays

consta=[1,2]

constb=[3,4]

a.concat(b)//1,2,3,4

Lookupthearrayforaspecificelement

Arrays

92

Page 93: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ES5

a.indexOf()

Returnstheindexofthefirstmatchingitemfound,or-1ifnotfound

a.lastIndexOf()

Returnstheindexofthelastmatchingitemfound,or-1ifnotfound

ES6

a.find((element,index,array)=>{

//returntrueorfalse

})

Returnsthefirstitemthatreturnstrue.Returnsundefinedifnotfound.

Acommonlyusedsyntaxis:

a.find(x=>x.id===my_id)

Theabovelinewillreturnthefirstelementinthearraythathas id===my_id.

findIndexreturnstheindexofthefirstitemthatreturnstrue,andifnotfound,itreturnsundefined:

a.findIndex((element,index,array)=>{

//returntrueorfalse

})

ES7

a.includes(value)

Returnstrueif acontains value.

a.includes(value,i)

Returnstrueif acontains valueaftertheposition i.

Arrays

93

Page 94: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Getaportionofanarray

a.slice()

SortthearraySortalphabetically(byASCIIvalue- 0-9A-Za-z)

consta=[1,2,3,10,11]

a.sort()//1,10,11,2,3

constb=[1,'a','Z',3,2,11]

b=a.sort()//1,11,2,3,Z,a

Sortbyacustomfunction

consta=[1,10,3,2,11]

a.sort((a,b)=>a-b)//1,2,3,10,11

Reversetheorderofanarray

a.reverse()

Getastringrepresentationofanarray

a.toString()

Returnsastringrepresentationofanarray

a.join()

Returnsastringconcatenationofthearrayelements.Passaparametertoaddacustomseparator:

a.join(',')

Copyanexistingarraybyvalue

Arrays

94

Page 95: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

constb=Array.from(a)

constb=Array.of(...a)

Copyjustsomevaluesfromanexistingarray

constb=Array.from(a,x=>x%2==0)

Copyportionsofanarrayintothearrayitself,inotherpositions

consta=[1,2,3,4]

a.copyWithin(0,2)//[3,4,3,4]

constb=[1,2,3,4,5]

b.copyWithin(0,2)//[3,4,5,4,5]

//0iswheretostartcopyinginto,

//2iswheretostartcopyingfrom

constc=[1,2,3,4,5]

c.copyWithin(0,2,4)//[3,4,3,4,5]

//4isanendindex

Arrays

95

Page 96: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

LoopsJavaScriptprovidesmanywaytoiteratethroughloops.ThistutorialexplainsallthevariouslooppossibilitiesinmodernJavaScript

IntroductionJavaScriptprovidesmanywaytoiteratethroughloops.Thistutorialexplainseachonewithasmallexampleandthemainproperties.

for

constlist=['a','b','c']

for(leti=0;i<list.length;i++){

console.log(list[i])//value

console.log(i)//index

}

Youcaninterrupta forloopusing breakYoucanfastforwardtothenextiterationofa forloopusing continue

Loops

96

Page 97: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

forEachIntroducedinES5.Givenanarray,youcaniterateoveritspropertiesusing list.forEach():

constlist=['a','b','c']

list.forEach((item,index)=>{

console.log(item)//value

console.log(index)//index

})

//indexisoptional

list.forEach(item=>console.log(item))

unfortunatelyyoucannotbreakoutofthisloop.

do...while

constlist=['a','b','c']

leti=0

do{

console.log(list[i])//value

console.log(i)//index

i=i+1

}while(i<list.length)

Youcaninterrupta whileloopusing break:

do{

if(something)break

}while(true)

andyoucanjumptothenextiterationusing continue:

do{

if(something)continue

//dosomethingelse

}while(true)

while

constlist=['a','b','c']

leti=0

while(i<list.length){

Loops

97

Page 98: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

console.log(list[i])//value

console.log(i)//index

i=i+1

}

Youcaninterrupta whileloopusing break:

while(true){

if(something)break

}

andyoucanjumptothenextiterationusing continue:

while(true){

if(something)continue

//dosomethingelse

}

Thedifferencewith do...whileisthat do...whilealwaysexecuteitscycleatleastonce.

for...in

Iteratesalltheenumerablepropertiesofanobject,givingthepropertynames.

for(letpropertyinobject){

console.log(property)//propertyname

console.log(object[property])//propertyvalue

}

for...of

ES2015introducedthe for...ofloop,whichcombinestheconcisenessofforEachwiththeabilitytobreak:

//iterateoverthevalue

for(constvalueof['a','b','c']){

console.log(value)//value

}

//gettheindexaswell,using`entries()`

for(const[index,value]of['a','b','c'].entries()){

console.log(index)//index

console.log(value)//value

}

Loops

98

Page 99: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Noticetheuseof const.Thisloopcreatesanewscopeineveryiteration,sowecansafelyusethatinsteadof let.

for...invs for...ofThedifferencewith for...inis:

for...ofiteratesoverthepropertyvaluesfor...initeratesthepropertynames

Loops

99

Page 100: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

EventsJavaScriptinthebrowserusesanevent-drivenprogrammingmodel.Everythingstartsbyfollowinganevent.ThisisanintroductiontoJavaScripteventsandhoweventhandlingworks

IntroductionJavaScriptinthebrowserusesanevent-drivenprogrammingmodel.

Everythingstartsbyfollowinganevent.

TheeventcouldbetheDOMisloaded,oranasynchronousrequestthatfinishesfetching,orauserclickinganelementorscrollingthepage,ortheusertypesonthekeyboard.

Therearealotofdifferentkindofevents.

EventhandlersYoucanrespondtoanyeventusinganEventHandler,whichisjustafunctionthat'scalledwhenaneventoccurs.

Events

100

Page 101: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Youcanregistermultiplehandlersforthesameevent,andtheywillallbecalledwhenthateventhappens.

JavaScriptofferthreewaystoregisteraneventhandler:

Inlineeventhandlers

Thisstyleofeventhandlersisveryrarelyusedtoday,duetoitsconstrains,butitwastheonlywayintheJavaScriptearlydays:

<ahref="site.com"onclick="dosomething();">Alink</a>

DOMon-eventhandlers

Thisiscommonwhenanobjecthasatmostoneeventhandler,asthereisnowaytoaddmultiplehandlersinthiscase:

window.onload=()=>{

//windowloaded

}

It'smostcommonlyusedwhenhandlingXHRrequests:

constxhr=newXMLHttpRequest()

xhr.onreadystatechange=()=>{

//..dosomething

}

Youcancheckifanhandlerisalreadyassignedtoapropertyusing if('onsomething'inwindow){}.

Using addEventListener()

Thisisthemodernway.Thismethodallowstoregisterasmanyhandlersasweneed,andit'sthemostpopularyouwillfind:

window.addEventListener('load',()=>{

//windowloaded

})

Thismethodallowstoregisterasmanyhandlersasweneed,andit'sthemostpopularyouwillfind.

Events

101

Page 102: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

NotethatIE8andbelowdidnotsupportthis,andinsteaduseditsown attachEvent()API.Keepitinmindifyouneedtosupportolderbrowsers.

ListeningondifferentelementsYoucanlistenon windowtointercept"global"events,liketheusageofthekeyboard,andyoucanlistenonspecificelementstocheckeventshappeningonthem,likeamouseclickonabutton.

Thisiswhy addEventListenerissometimescalledon window,sometimesonaDOMelement.

TheEventobjectAneventhandlergetsan Eventobjectasthefirstparameter:

constlink=document.getElementById('my-link')

link.addEventListener('click',event=>{

//linkclicked

})

Thisobjectcontainsalotofusefulpropertiesandmethods,like:

target,theDOMelementthatoriginatedtheeventtype,thetypeofeventstopPropagation(),calledtostoppropagatingtheeventintheDOM

(seethefulllist).

Otherpropertiesareprovidedbyspecifickindofevents,as Eventisaninterfacefordifferentspecificevents:

MouseEventKeyboardEventDragEventFetchEvent...andothers

EachofthosehasaMDNpagelinked,soyoucaninspectalltheirproperties.

ForexamplewhenaKeyboardEventhappens,youcancheckwhichkeywaspressed,inarreadableformat( Escape, Enterandsoon)bycheckingthe keyproperty:

window.addEventListener('keydown',event=>{

//keypressed

Events

102

Page 103: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

console.log(event.key)

})

Onamouseeventwecancheckwhichmousebuttonwaspressed:

constlink=document.getElementById('my-link')

link.addEventListener('mousedown',event=>{

//mousebuttonpressed

console.log(event.button)//0=left,2=right

})

EventbubblingandeventcapturingBubblingandcapturingarethe2modelsthateventsusetopropagate.

SupposeyouDOMstructureis

<divid="container">

<button>Clickme</button>

</div>

Youwanttotrackwhenusersclickonthebutton,andyouhave2eventlisteners,oneonbutton,andoneon #container.Remember,aclickonachildelementwillalwayspropagatetoitsparents,unlessyoustopthepropagation(seelater).

Thoseeventlistenerswillbecalledinorder,andthisorderisdeterminedbytheeventbubbling/capturingmodelused.

Bubblingmeansthattheeventpropagatesfromtheitemthatwasclicked(thechild)uptoallitsparenttree,startingfromthenearestone.

Inourexample,thehandleron buttonwillfirebeforethe #containerhandler.

Capturingistheopposite:theoutereventhandlersarefiredbeforethemorespecifichandler,theoneon button.

Bydefaultalleventsbubble.

YoucanchoosetoadopteventcapturingbyapplyingathirdargumenttoaddEventListener,settingitto true:

document.getElementById('container').addEventListener(

'click',

()=>{

//windowloaded

},

Events

103

Page 104: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

true

)

Notethatfirstallcapturingeventhandlersarerun.

Thenallthebubblingeventhandlers.

Theorderfollowsthisprinciple:theDOMgoesthroughallelementsstartingfromtheWindowobject,andgoestofindtheitemthatwasclicked.Whiledoingso,itcallsanyeventhandlerassociatedtotheevent(capturingphase).

Onceitreachesthetarget,itthenrepeatsthejourneyuptotheparentstreeuntiltheWindowobject,callingagaintheeventhandlers(bubblingphase).

StoppingthepropagationAneventonaDOMelementwillbepropagatedtoallitsparentelementstree,unlessit'sstopped.

<html>

<body>

<section>

<aid="my-link"...>

Aclickeventon awillpropagateto sectionandthen body.

Youcanstopthepropagationbycallingthe stopPropagation()methodofanEvent,usuallyattheendoftheeventhandler:

constlink=document.getElementById('my-link')

link.addEventListener('mousedown',event=>{

//processtheevent

//...

event.stopPropagation()

})

PopulareventsHere'salistofthemostcommoneventsyouwilllikelyhandle.

Load

loadisfiredon windowandthe bodyelementwhenthepagehasfinishedloading.

Events

104

Page 105: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Mouseevents

clickfireswhenamousebuttonisclicked. dblclickwhenthemouseisclickedtwotimes.Ofcourseinthiscase clickisfiredjustbeforethisevent. mousedown, mousemoveandmouseupcanbeusedincombinationtotrackdrag-and-dropevents.Becarefulwithmousemove,asitfiresmanytimesduringthemousemovement(seethrottlinglater)

Keyboardevents

keydownfireswhenakeyboardbuttonispressed(andanytimethekeyrepeatswhilethebuttonstayspressed). keyupisfiredwhenthekeyisreleased.

Scroll

The scrolleventisfiredon windoweverytimeyouscrollthepage.Insidetheeventhandleryoucancheckthecurrentscrollingpositionbychecking window.scrollY.

Keepinmindthatthiseventisnotaone-timething.Itfiresalotoftimesduringscrolling,notjustattheendorbeginningofthescrolling,sodon'tdoanyheavycomputationormanipulationinthehandler-usethrottlinginstead.

ThrottlingAswementionedabove, mousemoveand scrollaretwoeventsthatarenotfiredone-timeperevent,butrathertheycontinuouslycalltheireventhandlerfunctionduringallthedurationoftheaction.

Thisisbecausetheyprovidecoordinatessoyoucantrackwhat'shappening.

Ifyouperformacomplexoperationintheeventhandler,youwillaffecttheperformanceandcauseasluggishexperiencetoyoursiteusers.

LibrariesthatprovidethrottlinglikeLodashimplementitin100+linesofcode,tohandleeverypossibleusecase.Asimpleandeasytounderstandimplementationisthis,whichusessetTimeouttocachethescrolleventevery100ms:

letcached=null

window.addEventListener('scroll',event=>{

if(!cached){

setTimeout(()=>{

//youcanaccesstheoriginaleventat`cached`

cached=null

},100)

}

cached=event

Events

105

Page 106: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

})

Events

106

Page 107: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TheEventLoopTheEventLoopisoneofthemostimportantaspectstounderstandaboutJavaScript.Thispostexplainsitinsimpleterms

IntroductionTheEventLoopisoneofthemostimportantaspectstounderstandaboutJavaScript.

I'veprogrammedforyearswithJavaScript,yetI'veneverfullyunderstoodhowthingsworkunderthehoods.It'scompletelyfinetonotknowthisconceptindetail,butasusual,it'shelpfultoknowhowitworks,andalsoyoumightjustbealittlecuriousatthispoint.

ThispostaimstoexplaintheinnerdetailsofhowJavaScriptworkswithasinglethread,andhowithandlesasynchronousfunctions.

YourJavaScriptcoderunssinglethreaded.Thereisjustonethinghappeningatatime.

Thisisalimitationthat'sactuallyveryhelpful,asitsimplifiesalothowyouprogramwithoutworryingaboutconcurrencyissues.

Youjustneedtopayattentiontohowyouwriteyourcodeandavoidanythingthatcouldblockthethread,likesynchronousnetworkcallsorinfiniteloops.

Ingeneral,inmostbrowsersthereisaneventloopforeverybrowsertab,tomakeeveryprocessisolatedandavoidawebpagewithinfiniteloopsorheavyprocessingtoblockyourentirebrowser.

Theenvironmentmanagesmultipleconcurrenteventloops,tohandleAPIcallsforexample.WebWorkersrunintheirowneventloopaswell.

Youmainlyneedtobeconcernedthatyourcodewillrunonasingleeventloop,andwritecodewiththisthinginmindtoavoidblockingit.

BlockingtheeventloopAnyJavaScriptcodethattakestoolongtoreturnbackcontroltotheeventloopwillblocktheexecutionofanyJavaScriptcodeinthepage,evenblocktheUIthread,andtheusercannotclickaround,scrollthepage,andsoon.

TheEventLoop

107

Page 108: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

AlmostalltheI/OprimitivesinJavaScriptarenon-blocking.Networkrequests,Node.jsfilesystemoperations,andsoon.Beingblockingistheexception,andthisiswhyJavaScriptisbasedsomuchoncallbacks,andmorerecentlyonpromisesandasync/await.

ThecallstackThecallstackisaLIFOqueue(LastIn,FirstOut).

Theeventloopcontinuouslychecksthecallstacktoseeifthere'sanyfunctionthatneedstorun.

Whiledoingso,itaddsanyfunctioncallitfindstothecallstackandexecuteseachoneinorder.

Youknowtheerrorstacktraceyoumightbefamiliarwith,inthedebuggerorinthebrowserconsole?Thebrowserlooksupthefunctionnamesinthecallstacktoinformyouwhichfunctionoriginatesthecurrentcall:

TheEventLoop

108

Page 109: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

AsimpleeventloopexplanationLet'spickanexample:

constbar=()=>console.log('bar')

constbaz=()=>console.log('baz')

constfoo=()=>{

console.log('foo')

bar()

baz()

}

foo()

TheEventLoop

109

Page 110: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thiscodeprints

foo

bar

baz

asexpected.

Whenthiscoderuns,first foo()iscalled.Inside foo()wefirstcall bar(),thenwecallbaz().

Atthispointthecallstacklookslikethis:

Theeventlooponeveryiterationlooksifthere'ssomethinginthecallstack,andexecutesit:

TheEventLoop

110

Page 111: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

untilthecallstackisempty.

QueuingfunctionexecutionTheaboveexamplelooksnormal,there'snothingspecialaboutit:JavaScriptfindsthingstoexecute,runstheminorder.

TheEventLoop

111

Page 112: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Let'sseehowtodeferafunctionuntilthestackisclear.

Theusecaseof setTimeout(()=>{}),0)istocallafunction,butexecuteitonceeveryotherfunctioninthecodehasexecuted.

Takethisexample:

constbar=()=>console.log('bar')

constbaz=()=>console.log('baz')

constfoo=()=>{

console.log('foo')

setTimeout(bar,0)

baz()

}

foo()

Thiscodeprints,maybesurprisingly:

foo

baz

bar

Whenthiscoderuns,firstfoo()iscalled.Insidefoo()wefirstcallsetTimeout,passing barasanargument,andweinstructittorunimmediatelyasfastasitcan,passing0asthetimer.Thenwecallbaz().

Atthispointthecallstacklookslikethis:

TheEventLoop

112

Page 113: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Hereistheexecutionorderforallthefunctionsinourprogram:

TheEventLoop

113

Page 114: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Whyisthishappening?

TheMessageQueue

TheEventLoop

114

Page 115: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

WhensetTimeout()iscalled,theBrowserorNode.jsstartthetimer.Oncethetimerexpires,inthiscaseimmediatelyasweput0asthetimeout,thecallbackfunctionisputintheMessageQueue.

TheMessageQueueisalsowhereuser-initiatedeventslikeclickorkeyboardevents,orfetchresponsesarequeuedbeforeyourcodehastheopportunitytoreacttothem.OralsoDOMeventslike onLoad.

Theloopgivesprioritytothecallstack,anditfirstprocesseseverythingitfindsinthecallstack,andoncethere'snothinginthere,itgoestopickupthingsintheeventqueue.

Wedon'thavetowaitforfunctionslike setTimeout,fetchorotherthingstodotheirownwork,becausetheyareprovidedbythebrowser,andtheyliveontheirownthreads.Forexample,ifyousetthe setTimeouttimeoutto2seconds,youdon'thavetowait2seconds-thewaithappenselsewhere.

ES6JobQueueECMAScript2015introducedtheconceptoftheJobQueue,whichisusedbyPromises(alsointroducedinES6/ES2015).It'sawaytoexecutetheresultofanasyncfunctionassoonaspossible,ratherthanbeingputattheendofthecallstack.

Promisesthatresolvebeforethecurrentfunctionendswillbeexecutedrightafterthecurrentfunction.

Ifindnicetheanalogyofarollercoasterrideatanamusementpark:themessagequeueputsyoubackinqueuewithafteralltheotherpeopleinthequeue,whilethejobqueueisthefastpassticketthatletsyoutakeanotherriderightafteryoufinishedthepreviousone.

Example:

constbar=()=>console.log('bar')

constbaz=()=>console.log('baz')

constfoo=()=>{

console.log('foo')

setTimeout(bar,0)

newPromise((resolve,reject)=>

resolve('shouldberightafterbaz,beforebar')

).then(resolve=>console.log(resolve))

baz()

}

foo()

TheEventLoop

115

Page 116: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thisprints

foo

baz

shouldberightafterbaz,beforebar

bar

That'sabigdifferencebetweenPromises(andAsync/await,whichisbuiltonpromises)andplainoldasynchronousfunctionsthrough setTimeout()orotherplatformAPIs.

TheEventLoop

116

Page 117: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

AsynchronousprogrammingandcallbacksJavaScriptissynchronousbydefault,andissinglethreaded.Thismeansthatcodecannotcreatenewthreadsandruninparallel.Findoutwhatasynchronouscodemeansandhowitlookslike

AsynchronicityinProgrammingLanguagesComputersareasynchronousbydesign.

Asynchronousmeansthatthingscanhappenindependentlyofthemainprogramflow.

Inthecurrentconsumercomputers,everyprogramrunsforaspecifictimeslot,andthenitstopsitsexecutiontoletanotherprogramcontinueitsexecution.Thisthingrunsinacyclesofastthat'simpossibletonotice,andwethinkourcomputersrunmanyprogramssimultaneously,butthisisanillusion(exceptonmultiprocessormachines).

Programsinternallyuseinterrupts,asignalthat'semittedtotheprocessortogaintheattentionofthesystem.

Asynchronousprogrammingandcallbacks

117

Page 118: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Iwon'tgointotheinternalsofthis,butjustkeepinmindthatit'snormalforprogramstobeasynchronous,andhalttheirexecutionuntiltheyneedattention,andthecomputercanexecuteotherthingsinthemeantime.Whenaprogramiswaitingforaresponsefromthenetwork,itcannothalttheprocessoruntiltherequestfinishes.

Normally,programminglanguagesaresynchronous,andsomeprovideawaytomanageasynchronicity,inthelanguageorthroughlibraries.C,Java,C#,PHP,Go,Ruby,Swift,Python,theyareallsynchronousbydefault.Someofthemhandleasyncbyusingthreads,spawninganewprocess.

JavaScriptJavaScriptissynchronousbydefaultandissinglethreaded.Thismeansthatcodecannotcreatenewthreadsandruninparallel.

Linesofcodeareexecutedinseries,oneafteranother,forexample:

consta=1

constb=2

constc=a*b

console.log(c)

doSomething()

ButJavaScriptwasborninsidethebrowser,itsmainjob,inthebeginning,wastorespondtouseractions,like onClick, onMouseOver, onChange, onSubmitandsoon.Howcoulditdothiswithasynchronousprogrammingmodel?

Theanswerwasinitsenvironment.ThebrowserprovidesawaytodoitbyprovidingasetofAPIsthatcanhandlethiskindoffunctionality.

Morerecently,Node.jsintroducedanon-blockingI/Oenvironmenttoextendthisconcepttofileaccess,networkcallsandsoon.

CallbacksYoucan'tknowwhenauserisgoingtoclickabutton,sowhatyoudois,youdefineaneventhandlerfortheclickevent.Thiseventhandleracceptsafunction,whichwillbecalledwhentheeventistriggered:

document.getElementById('button').addEventListener('click',()=>{

//itemclicked

})

Asynchronousprogrammingandcallbacks

118

Page 119: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Thisistheso-calledcallback.

Acallbackisasimplefunctionthat'spassedasavaluetoanotherfunction,andwillonlybeexecutedwhentheeventhappens.WecandothisbecauseJavaScripthasfirst-classfunctions,whichcanbeassignedtovariablesandpassedaroundtootherfunctions(calledhigher-orderfunctions)

It'scommontowrapallyourclientcodeina loadeventlisteneronthe windowobject,whichrunsthecallbackfunctiononlywhenthepageisready:

window.addEventListener('load',()=>{

//windowloaded

//dowhatyouwant

})

Callbacksareusedeverywhere,notjustinDOMevents.

Onecommonexampleisbyusingtimers:

setTimeout(()=>{

//runsafter2seconds

},2000)

XHRrequestsalsoacceptacallback,inthisexamplebyassigningafunctiontoapropertythatwillbecalledwhenaparticulareventoccurs(inthiscase,thestateoftherequestchanges):

constxhr=newXMLHttpRequest()

xhr.onreadystatechange=()=>{

if(xhr.readyState===4){

xhr.status===200?console.log(xhr.responseText):console.error('error')

}

}

xhr.open('GET','https://yoursite.com')

xhr.send()

HandlingerrorsincallbacksHowdoyouhandleerrorswithcallbacks?OneverycommonstrategyistousewhatNode.jsadopted:thefirstparameterinanycallbackfunctionistheerrorobject:error-firstcallbacks

Ifthereisnoerror,theobjectis null.Ifthereisanerror,itcontainssomedescriptionoftheerrorandotherinformation.

fs.readFile('/file.json',(err,data)=>{

if(err!==null){

Asynchronousprogrammingandcallbacks

119

Page 120: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

//handleerror

console.log(err)

return

}

//noerrors,processdata

console.log(data)

})

TheproblemwithcallbacksCallbacksaregreatforsimplecases!

Howevereverycallbackaddsalevelofnesting,andwhenyouhavelotsofcallbacks,thecodestartstobecomplicatedveryquickly:

window.addEventListener('load',()=>{

document.getElementById('button').addEventListener('click',()=>{

setTimeout(()=>{

items.forEach(item=>{

//yourcodehere

})

},2000)

})

})

Thisisjustasimple4-levelscode,butI'veseenmuchmorelevelsofnestingandit'snotfun.

Howdowesolvethis?

AlternativestocallbacksStartingwithES6,JavaScriptintroducedseveralfeaturesthathelpuswithasynchronouscodethatdonotinvolveusingcallbacks:

Promises(ES6)Async/Await(ES8)

Asynchronousprogrammingandcallbacks

120

Page 121: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

PromisesPromisesareonewaytodealwithasynchronouscodeinJavaScript,withoutwritingtoomanycallbacksinyourcode.

IntroductiontopromisesApromiseiscommonlydefinedasaproxyforavaluethatwilleventuallybecomeavailable.

Promisesareonewaytodealwithasynchronouscode,withoutwritingtoomanycallbacksinyourcode.

Althoughbeingaroundsinceyears,theyhavebeenstandardizedandintroducedinES2015,andnowtheyhavebeensupersededinES2017byasyncfunctions.

AsyncfunctionsusethepromisesAPIastheirbuildingblock,sounderstandingthemisfundamentalevenifinnewercodeyou'lllikelyuseasyncfunctionsinsteadofpromises.

Howpromiseswork,inbrief

Onceapromisehasbeencalled,itwillstartinpendingstate.Thismeansthatthecallerfunctioncontinuestheexecution,whileitwaitsforthepromisetodoitsownprocessing,andgivethecallerfunctionsomefeedback.

Atthispoint,thecallerfunctionwaitsforittoeitherreturnthepromiseinaresolvedstate,orinarejectedstate,butasyouknowJavaScriptisasynchronous,sothefunctioncontinuesitsexecutionwhilethepromisedoesitwork.

WhichJSAPIusepromises?

Inadditiontoyourowncodeandlibrariescode,promisesareusedbystandardmodernWebAPIssuchas:

theBatteryAPItheFetchAPIServiceWorkers

It'sunlikelythatinmodernJavaScriptyou'llfindyourselfnotusingpromises,solet'sstartdivingrightintothem.

Promises

121

Page 122: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

CreatingapromiseThePromiseAPIexposesaPromiseconstructor,whichyouinitializeusing newPromise():

letdone=true

constisItDoneYet=newPromise(

(resolve,reject)=>{

if(done){

constworkDone='HereisthethingIbuilt'

resolve(workDone)

}else{

constwhy='Stillworkingonsomethingelse'

reject(why)

}

}

)

Asyoucanseethepromisechecksthe doneglobalconstant,andifthat'strue,wereturnaresolvedpromise,otherwisearejectedpromise.

Using resolveand rejectwecancommunicatebackavalue,intheabovecasewejustreturnastring,butitcouldbeanobjectaswell.

ConsumingapromiseInthelastsection,weintroducedhowapromiseiscreated.

Nowlet'sseehowthepromisecanbeconsumedorused.

constisItDoneYet=newPromise(

//...

)

constcheckIfItsDone=()=>{

isItDoneYet

.then((ok)=>{

console.log(ok)

})

.catch((err)=>{

console.error(err)

})

}

Promises

122

Page 123: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Running checkIfItsDone()willexecutethe isItDoneYet()promiseandwillwaitforittoresolve,usingthe thencallback,andifthereisanerror,itwillhandleitinthe catchcallback.

ChainingpromisesApromisecanbereturnedtoanotherpromise,creatingachainofpromises.

AgreatexampleofchainingpromisesisgivenbytheFetchAPI,alayerontopoftheXMLHttpRequestAPI,whichwecanusetogetaresourceandqueueachainofpromisestoexecutewhentheresourceisfetched.

TheFetchAPIisapromise-basedmechanism,andcalling fetch()isequivalenttodefiningourownpromiseusing newPromise().

Exampleofchainingpromises

conststatus=(response)=>{

if(response.status>=200&&response.status<300){

returnPromise.resolve(response)

}

returnPromise.reject(newError(response.statusText))

}

constjson=(response)=>response.json()

fetch('/todos.json')

.then(status)

.then(json)

.then((data)=>{console.log('RequestsucceededwithJSONresponse',data)})

.catch((error)=>{console.log('Requestfailed',error)})

Inthisexample,wecall fetch()togetalistofTODOitemsfromthe todos.jsonfilefoundinthedomainroot,andwecreateachainofpromises.

Running fetch()returnsaresponse,whichhasmanyproperties,andwithinthosewereference:

status,anumericvaluerepresentingtheHTTPstatuscodestatusText,astatusmessage,whichis OKiftherequestsucceeded

responsealsohasa json()method,whichreturnsapromisethatwillresolvewiththecontentofthebodyprocessedandtransformedintoJSON.

Promises

123

Page 124: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Sogiventhosepremises,thisiswhathappens:thefirstpromiseinthechainisafunctionthatwedefined,called status(),thatcheckstheresponsestatusandifit'snotasuccessresponse(between200and299),itrejectsthepromise.

Thisoperationwillcausethepromisechaintoskipallthechainedpromiseslistedandwillskipdirectlytothe catch()statementatthebottom,loggingthe Requestfailedtextalongwiththeerrormessage.

Ifthatsucceedsinstead,itcallsthejson()functionwedefined.Sincethepreviouspromise,whensuccessful,returnedthe responseobject,wegetitasaninputtothesecondpromise.

Inthiscase,wereturnthedataJSONprocessed,sothethirdpromisereceivestheJSONdirectly:

.then((data)=>{

console.log('RequestsucceededwithJSONresponse',data)

})

andwesimplylogittotheconsole.

HandlingerrorsIntheexample,intheprevioussection,wehada catchthatwasappendedtothechainofpromises.

Whenanythinginthechainofpromisesfailsandraisesanerrororrejectsthepromise,thecontrolgoestothenearest catch()statementdownthechain.

newPromise((resolve,reject)=>{

thrownewError('Error')

})

.catch((err)=>{console.error(err)})

//or

newPromise((resolve,reject)=>{

reject('Error')

})

.catch((err)=>{console.error(err)})

Cascadingerrors

Ifinsidethe catch()youraiseanerror,youcanappendasecond catch()tohandleit,andsoon.

Promises

124

Page 125: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

newPromise((resolve,reject)=>{

thrownewError('Error')

})

.catch((err)=>{thrownewError('Error')})

.catch((err)=>{console.error(err)})

Orchestratingpromises

Promise.all()

Ifyouneedtosynchronizedifferentpromises, Promise.all()helpsyoudefinealistofpromises,andexecutesomethingwhentheyareallresolved.

Example:

constf1=fetch('/something.json')

constf2=fetch('/something2.json')

Promise.all([f1,f2]).then((res)=>{

console.log('Arrayofresults',res)

})

.catch((err)=>{

console.error(err)

})

TheES2015destructuringassignmentsyntaxallowsyoutoalsodo

Promise.all([f1,f2]).then(([res1,res2])=>{

console.log('Results',res1,res2)

})

Youarenotlimitedtousing fetchofcourse,anypromiseisgoodtogo.

Promise.race()

Promise.race()runswhenthefirstofthepromisesyoupasstoitresolves,anditrunstheattachedcallbackjustonce,withtheresultofthefirstpromiseresolved.

Example:

constfirst=newPromise((resolve,reject)=>{

setTimeout(resolve,500,'first')

})

constsecond=newPromise((resolve,reject)=>{

Promises

125

Page 126: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

setTimeout(resolve,100,'second')

})

Promise.race([first,second]).then((result)=>{

console.log(result)//second

})

Commonerrors

UncaughtTypeError:undefinedisnotapromise

Ifyougetthe UncaughtTypeError:undefinedisnotapromiseerrorintheconsole,makesureyouuse newPromise()insteadofjust Promise()

Promises

126

Page 127: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

AsyncandAwaitDiscoverthemodernapproachtoasynchronousfunctionsinJavaScript.JavaScriptevolvedinaveryshorttimefromcallbackstoPromises,andsinceES2017asynchronousJavaScriptisevensimplerwiththeasync/awaitsyntax

IntroductionJavaScriptevolvedinaveryshorttimefromcallbackstopromises(ES2015),andsinceES2017asynchronousJavaScriptisevensimplerwiththeasync/awaitsyntax.

Asyncfunctionsareacombinationofpromisesandgenerators,andbasically,theyareahigherlevelabstractionoverpromises.Letmerepeat:async/awaitisbuiltonpromises.

Whywereasync/awaitintroduced?Theyreducetheboilerplatearoundpromises,andthe"don'tbreakthechain"limitationofchainingpromises.

WhenPromiseswereintroducedinES2015,theyweremeanttosolveaproblemwithasynchronouscode,andtheydid,butoverthe2yearsthatseparatedES2015andES2017,itwasclearthatpromisescouldnotbethefinalsolution.

Promiseswereintroducedtosolvethefamouscallbackhellproblem,buttheyintroducedcomplexityontheirown,andsyntaxcomplexity.

Theyweregoodprimitivesaroundwhichabettersyntaxcouldbeexposedtothedevelopers,sowhenthetimewasrightwegotasyncfunctions.

Theymakethecodelooklikeit'ssynchronous,butit'sasynchronousandnon-blockingbehindthescenes.

HowitworksAnasyncfunctionreturnsapromise,likeinthisexample:

constdoSomethingAsync=()=>{

returnnewPromise((resolve)=>{

setTimeout(()=>resolve('Ididsomething'),3000)

})

AsyncandAwait

127

Page 128: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

}

Whenyouwanttocallthisfunctionyouprepend await,andthecallingcodewillstopuntilthepromiseisresolvedorrejected.Onecaveat:theclientfunctionmustbedefinedasasync.Here'sanexample:

constdoSomething=async()=>{

console.log(awaitdoSomethingAsync())

}

AquickexampleThisisasimpleexampleofasync/awaitusedtorunafunctionasynchronously:

constdoSomethingAsync=()=>{

returnnewPromise((resolve)=>{

setTimeout(()=>resolve('Ididsomething'),3000)

})

}

constdoSomething=async()=>{

console.log(awaitdoSomethingAsync())

}

console.log('Before')

doSomething()

console.log('After')

Theabovecodewillprintthefollowingtothebrowserconsole:

Before

After

Ididsomething//after3s

PromiseallthethingsPrependingthe asynckeywordtoanyfunctionmeansthatthefunctionwillreturnapromise.

Evenifit'snotdoingsoexplicitly,itwillinternallymakeitreturnapromise.

Thisiswhythiscodeisvalid:

constaFunction=async()=>{

return'test'

}

AsyncandAwait

128

Page 129: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

aFunction().then(alert)//Thiswillalert'test'

andit'sthesameas:

constaFunction=async()=>{

returnPromise.resolve('test')

}

aFunction().then(alert)//Thiswillalert'test'

ThecodeismuchsimplertoreadAsyoucanseeintheexampleabove,ourcodelooksverysimple.Compareittocodeusingplainpromises,withchainingandcallbackfunctions.

Andthisisaverysimpleexample,themajorbenefitswillarisewhenthecodeismuchmorecomplex.

Forexamplehere'showyouwouldgetaJSONresource,andparseit,usingpromises:

constgetFirstUserData=()=>{

returnfetch('/users.json')//getuserslist

.then(response=>response.json())//parseJSON

.then(users=>users[0])//pickfirstuser

.then(user=>fetch(`/users/${user.name}`))//getuserdata

.then(userResponse=>response.json())//parseJSON

}

getFirstUserData()

Andhereisthesamefunctionalityprovidedusingawait/async:

constgetFirstUserData=async()=>{

constresponse=awaitfetch('/users.json')//getuserslist

constusers=awaitresponse.json()//parseJSON

constuser=users[0]//pickfirstuser

constuserResponse=awaitfetch(`/users/${user.name}`)//getuserdata

constuserData=awaituser.json()//parseJSON

returnuserData

}

getFirstUserData()

Multipleasyncfunctionsinseries

AsyncandAwait

129

Page 130: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Asyncfunctionscanbechainedveryeasily,andthesyntaxismuchmorereadablethanwithplainpromises:

constpromiseToDoSomething=()=>{

returnnewPromise(resolve=>{

setTimeout(()=>resolve('Ididsomething'),10000)

})

}

constwatchOverSomeoneDoingSomething=async()=>{

constsomething=awaitpromiseToDoSomething()

returnsomething+'andIwatched'

}

constwatchOverSomeoneWatchingSomeoneDoingSomething=async()=>{

constsomething=awaitwatchOverSomeoneDoingSomething()

returnsomething+'andIwatchedaswell'

}

watchOverSomeoneWatchingSomeoneDoingSomething().then((res)=>{

console.log(res)

})

Willprint:

IdidsomethingandIwatchedandIwatchedaswell

EasierdebuggingDebuggingpromisesishardbecausethedebuggerwillnotstepoverasynchronouscode.

Async/awaitmakesthisveryeasybecausetothecompilerit'sjustlikesynchronouscode.

AsyncandAwait

130

Page 131: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

LoopsandScopeThereisonefeatureofJavaScriptthatmightcauseafewheadachestodevelopers,relatedtoloopsandscoping.Learnsometricksaboutloopsandscopingwithvarandlet

ThereisonefeatureofJavaScriptthatmightcauseafewheadachestodevelopers,relatedtoloopsandscoping.

Takethisexample:

constoperations=[]

for(vari=0;i<5;i++){

operations.push(()=>{

console.log(i)

})

}

for(constoperationofoperations){

operation()

}

Itbasicallyiteratesandfor5timesitaddsafunctiontoanarraycalledoperations.Thisfunctionsimplyconsolelogstheloopindexvariable i.

Lateritrunsthesefunctions.

Theexpectedresulthereshouldbe:

0

1

2

3

4

butactuallywhathappensisthis:

5

5

5

5

5

Whyisthisthecase?Becauseoftheuseof var.

Since vardeclarationsarehoisted,theabovecodeequalsto

LoopsandScope

131

Page 132: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

vari;

constoperations=[]

for(i=0;i<5;i++){

operations.push(()=>{

console.log(i)

})

}

for(constoperationofoperations){

operation()

}

so,inthefor-ofloop, iisstillvisible,it'sequalto5andeveryreferenceto iinthefunctionisgoingtousethisvalue.

Sohowshouldwedotomakethingsworkaswewant?

Thesimplestsolutionistouse letdeclarations.IntroducedinES2015,theyareagreathelpinavoidingsomeoftheweirdthingsabout vardeclarations.

Simplychanging varto letintheloopvariableisgoingtoworkfine:

constoperations=[]

for(leti=0;i<5;i++){

operations.push(()=>{

console.log(i)

})

}

for(constoperationofoperations){

operation()

}

Here'stheoutput:

0

1

2

3

4

Howisthispossible?Thisworksbecauseoneveryloopiteration iiscreatedasanewvariableeachtime,andeveryfunctionaddedtothe operationsarraygetsitsowncopyof i.

Keepinmindyoucannotuse constinthiscase,becausetherewouldbeanerroras fortriestoassignanewvalueintheseconditeration.

LoopsandScope

132

Page 133: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Anotherwaytosolvethisproblemwasverycommoninpre-ES6code,anditiscalledImmediatelyInvokedFunctionExpression(IIFE).

Inthiscaseyoucanwraptheentirefunctionandbind itoit.Sinceinthiswayyou'recreatingafunctionthatimmediatelyexecutes,youreturnanewfunctionfromit,sowecanexecuteitlater:

constoperations=[]

for(vari=0;i<5;i++){

operations.push(((j)=>{

return()=>console.log(j)

})(i))

}

for(constoperationofoperations){

operation()

}

LoopsandScope

133

Page 134: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TimersWhenwritingJavaScriptcode,youmightwanttodelaytheexecutionofafunction.LearnhowtousesetTimeoutandsetIntervaltoschedulefunctionsinthefuture

setTimeout()

WhenwritingJavaScriptcode,youmightwanttodelaytheexecutionofafunction.

Thisisthejobof setTimeout.Youspecifyacallbackfunctiontoexecutelater,andavalueexpressinghowlateryouwantittorun,inmilliseconds:

setTimeout(()=>{

//runsafter2seconds

},2000)

setTimeout(()=>{

//runsafter50milliseconds

},50)

Thissyntaxdefinesanewfunction.Youcancallwhateverotherfunctionyouwantinthere,oryoucanpassanexistingfunctionname,andasetofparameters:

constmyFunction=(firstParam,secondParam)=>{

//dosomething

}

//runsafter2seconds

setTimeout(myFunction,2000,firstParam,secondParam)

Timers

134

Page 135: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

setTimeoutreturnsthetimerid.Thisisgenerallynotused,butyoucanstorethisid,andclearitifyouwanttodeletethisscheduledfunctionexecution:

constid=setTimeout(()=>{

//shouldrunafter2seconds

},2000)

//Ichangedmymind

clearTimeout(id)

Zerodelay

Ifyouspecifythetimeoutdelayto 0,thecallbackfunctionwillbeexecutedassoonaspossible,butafterthecurrentfunctionexecution:

setTimeout(()=>{

console.log('after')

},0)

console.log('before')

willprint beforeafter.

ThisisespeciallyusefultoavoidblockingtheCPUonintensivetasksandletotherfunctionsbeexecutedwhileperformingaheavycalculation,byqueuingfunctionsinthescheduler.

Somebrowsers(IEandEdge)implementa setImmediate()methodthatdoesthissameexactfunctionality,butit'snotstandardandunavailableonotherbrowsers.Butit'sastandardfunctioninNode.js.

setInterval()

setIntervalisafunctionsimilarto setTimeout,withadifference:insteadofrunningthecallbackfunctiononce,itwillrunitforever,atthespecifictimeintervalyouspecify(inmilliseconds):

setInterval(()=>{

//runsevery2seconds

},2000)

Thefunctionaboverunsevery2secondsunlessyoutellittostop,using clearInterval,passingittheintervalidthat setIntervalreturned:

constid=setInterval(()=>{

Timers

135

Page 136: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

//runsevery2seconds

},2000)

clearInterval(id)

It'scommontocall clearIntervalinsidethesetIntervalcallbackfunction,toletitauto-determineifitshouldrunagainorstop.ForexamplethiscoderunssomethingunlessApp.somethingIWaithasthevalue arrived:

constinterval=setInterval(()=>{

if(App.somethingIWait==='arrived'){

clearInterval(interval)

return

}

//otherwisedothings

},100)

RecursivesetTimeoutsetIntervalstartsafunctioneverynmilliseconds,withoutanyconsiderationaboutwhenafunctionfinisheditsexecution.

Ifafunctiontakesalwaysthesameamountoftime,it'sallfine:

Maybethefunctiontakesdifferentexecutiontimes,dependingonnetworkconditionsforexample:

Andmaybeonelongexecutionoverlapsthenextone:

Toavoidthis,youcanschedulearecursivesetTimeouttobecalledwhenthecallbackfunctionfinishes:

Timers

136

Page 137: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

constmyFunction=()=>{

//dosomething

setTimeout(myFunction,1000)

}

setTimeout(

myFunction()

},1000)

toachievethisscenario:

setTimeoutand setIntervalareavailableinNode.js,throughtheTimersmodule.

Node.jsalsoprovides setImmediate(),whichisequivalenttousing setTimeout(()=>{},0),mostlyusedtoworkwiththeNode.jsEventLoop.

Timers

137

Page 138: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

this`this`isavaluethathasdifferentvaluesdependingonwhereit'sused.NotknowingthistinydetailofJavaScriptcancausealotofheadaches,soit'sworthtaking5minutestolearnallthetricks

thisisavaluethathasdifferentvaluesdependingonwhereit'sused.

NotknowingthistinydetailofJavaScriptcancausealotofheadaches,soit'sworthtaking5minutestolearnallthetricks.

thisinstrictmodeOutsideanyobject, thisinstrictmodeisalways undefined.

NoticeImentionedstrictmode.Ifstrictmodeisdisabled(thedefaultstateifyoudon'texplicitlyadd 'usestrict'ontopofyourfile),youareintheso-calledsloppymode,and this-unlesssomespecificcasesmentionedherebelow-hasthevalueoftheglobalobject.

Whichmeans windowinabrowsercontext.

thisinmethodsAmethodisafunctionattachedtoanobject.

Youcanseeitinvariousforms.

this

138

Page 139: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Here'sone:

constcar={

maker:'Ford',

model:'Fiesta',

drive(){

console.log(`Drivinga${this.maker}${this.model}car!`)

}

}

car.drive()

//DrivingaFordFiestacar!

Inthiscase,usingaregularfunction, thisisautomaticallyboundtotheobject.

Note:theabovemethoddeclarationisthesameas drive:function(){...,butshorter:

constcar={

maker:'Ford',

model:'Fiesta',

drive:function(){

console.log(`Drivinga${this.maker}${this.model}car!`)

}

}

Thesameworksinthisexample:

constcar={

maker:'Ford',

model:'Fiesta'

}

car.drive=function(){

console.log(`Drivinga${this.maker}${this.model}car!`)

}

car.drive()

//DrivingaFordFiestacar!

Anarrowfunctiondoesnotworkinthesameway,asit'slexicallybound:

constcar={

maker:'Ford',

model:'Fiesta',

drive:()=>{

console.log(`Drivinga${this.maker}${this.model}car!`)

}

}

this

139

Page 140: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

car.drive()

//Drivingaundefinedundefinedcar!

BindingarrowfunctionsYoucannotbindavaluetoanarrowfunction,likeyoudowithnormalfunctions.

It'ssimplynotpossibleduetothewaytheywork. thisislexicallybound,whichmeansitsvalueisderivedfromthecontextwheretheyaredefined.

Explicitlypassanobjecttobeusedas thisJavaScriptoffersafewwaystomap thistoanyobjectyouwant.

Using bind(),atthefunctiondeclarationstep:

constcar={

maker:'Ford',

model:'Fiesta'

}

constdrive=function(){

console.log(`Drivinga${this.maker}${this.model}car!`)

}.bind(car)

drive()

//DrivingaFordFiestacar!

Youcouldalsobindanexistingobjectmethodtoremapits thisvalue:

constcar={

maker:'Ford',

model:'Fiesta',

drive(){

console.log(`Drivinga${this.maker}${this.model}car!`)

}

}

constanotherCar={

maker:'Audi',

model:'A4'

}

car.drive.bind(anotherCar)()

//DrivingaAudiA4car!

this

140

Page 141: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Using call()or apply(),atthefunctioninvocationstep:

constcar={

maker:'Ford',

model:'Fiesta'

}

constdrive=function(kmh){

console.log(`Drivinga${this.maker}${this.model}carat${kmh}km/h!`)

}

drive.call(car,100)

//DrivingaFordFiestacarat100km/h!

drive.apply(car,[100])

//DrivingaFordFiestacarat100km/h!

Thefirstparameteryoupassto call()or apply()isalwaysboundto this.Thedifferencebetweencall()andapply()isjustthatthesecondonewantsanarrayastheargumentslist,whilethefirstacceptsavariablenumberofparameters,whichpassesasfunctionarguments.

ThespecialcaseofbrowsereventhandlersIneventhandlerscallbacks, thisreferstotheHTMLelementthatreceivedtheevent:

document.querySelector('#button').addEventListener('click',function(e){

console.log(this)//HTMLElement

}

Youcanbinditusing

document.querySelector('#button').addEventListener(

'click',

function(e){

console.log(this)//Windowifglobal,oryourcontext

}.bind(this)

)

this

141

Page 142: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

StrictModeStrictModeisanES5feature,andit'sawaytomakeJavaScriptbehaveinabetterway.Andinadifferentway,asenablingStrictModechangesthesemanticsoftheJavaScriptlanguage.It'sreallyimportanttoknowthemaindifferencesbetweenJavaScriptcodeinstrictmode,andnormalJavaScript,whichisoftenreferredassloppymode

StrictModeisanES5feature,andit'sawaytomakeJavaScriptbehaveinabetterway.

Andinadifferentway,asenablingStrictModechangesthesemanticsoftheJavaScriptlanguage.

It'sreallyimportanttoknowthemaindifferencesbetweenJavaScriptcodeinstrictmode,and"normal"JavaScript,whichisoftenreferredassloppymode.

StrictModemostlyremovesfunctionalitythatwaspossibleinES3,anddeprecatedsinceES5(butnotremovedbecauseofbackwardscompatibilityrequirements)

HowtoenableStrictMode

StrictMode

142

Page 143: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Strictmodeisoptional.AswitheverybreakingchangeinJavaScript,wecan'tsimplychangehowthelanguagebehavesbydefault,becausethatwouldbreakgazillionsofJavaScriptaround,andJavaScriptputsalotofeffortintomakingsure1996JavaScriptcodestillworkstoday.It'sakeyofitssuccess.

Sowehavethe 'usestrict'directiveweneedtousetoenableStrictMode.

Youcanputitatthebeginningofafile,toapplyittoallthecodecontainedinthefile:

'usestrict'

constname='Flavio'

consthello=()=>'hey'

//...

YoucanalsoenableStrictModeforanindividualfunction,byputting 'usestrict'atthebeginningofthefunctionbody:

functionhello(){

'usestrict'

return'hey'

}

Thisisusefulwhenoperatingonlegacycode,whereyoudon'thavethetimetotestortheconfidencetoenablestrictmodeonthewholefile.

WhatchangesinStrictMode

Accidentalglobalvariables

Ifyouassignavaluetoanundeclaredvariable,JavaScriptbydefaultcreatesthatvariableontheglobalobject:

;(function(){

variable='hey'

})()(()=>{

name='Flavio'

})()

variable//'hey'

name//'Flavio'

TurningonStrictMode,anerrorisraisedifyoutrytodowhatwedidabove:

StrictMode

143

Page 144: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

;(function(){

'usestrict'

variable='hey'

})()(()=>{

'usestrict'

myname='Flavio'

})()

Assignmenterrors

JavaScriptsilentlyfailssomeconversionerrors.

InStrictMode,thosesilenterrorsnowraiseissues:

constundefined=1(()=>{

'usestrict'

undefined=1

})()

StrictMode

144

Page 145: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ThesameappliestoInfinity,NaN, eval, argumentsandmore.

InJavaScriptyoucandefineapropertyofanobjecttobenotwritable,byusing

constcar={}

Object.defineProperty(car,'color',{value:'blue',writable:false})

Instrictmode,youcan'toverridethisvalue,whileinsloppymodethat'spossible:

Thesameworksforgetters:

constcar={

getcolor(){

return'blue'

}

}

car.color='red'(

//ok

()=>{

'usestrict'

StrictMode

145

Page 146: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

car.color='yellow'//TypeError:Cannotsetpropertycolorof#<Object>whichhasonl

yagetter

}

)()

Sloppymodeallowstoextendanon-extensibleobject:

constcar={color:'blue'}

Object.preventExtensions(car)

car.model='Fiesta'(

//ok

()=>{

'usestrict'

car.owner='Flavio'//TypeError:Cannotaddpropertyowner,objectisnotextensible

}

)()

Also,sloppymodeallowstosetpropertiesonprimitivevalues,withoutfailing,butalsowithoutdoingnothingatall:

true.false=''(

//''

1

).name=

'xxx'//'xxx'

vartest='test'//undefined

test.testing=true//true

test.testing//undefined

Strictmodefailsinallthosecases:

;(()=>{

'usestrict'

true.false=''(

//TypeError:Cannotcreateproperty'false'onboolean'true'

1

).name=

'xxx'//TypeError:Cannotcreateproperty'name'onnumber'1'

'test'.testing=true//TypeError:Cannotcreateproperty'testing'onstring'test'

})()

Deletionerrors

Insloppymode,ifyoutrytodeleteapropertythatyoucannotdelete,JavaScriptsimplyreturnsfalse,whileinStrictMode,itraisesaTypeError:

deleteObject.prototype(

StrictMode

146

Page 147: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

//false

()=>{

'usestrict'

deleteObject.prototype//TypeError:Cannotdeleteproperty'prototype'offunctionOb

ject(){[nativecode]}

}

)()

Functionargumentswiththesamename

Innormalfunctions,youcanhaveduplicateparameternames:

(function(a,a,b){

console.log(a,b)

})(1,2,3)

//23

(function(a,a,b){

'usestrict'

console.log(a,b)

})(1,2,3)

//UncaughtSyntaxError:Duplicateparameternamenotallowedinthiscontext

Notethatarrowfunctionsalwaysraisea SyntaxErrorinthiscase:

((a,a,b)=>{

console.log(a,b)

})(1,2,3)

//UncaughtSyntaxError:Duplicateparameternamenotallowedinthiscontext

Octalsyntax

OctalsyntaxinStrictModeisdisabled.Bydefault,prependinga 0toanumbercompatiblewiththeoctalnumericformatmakesit(sometimesconfusingly)interpretedasanoctalnumber:

(()=>{

console.log(010)

})()

//8

(()=>{

'usestrict'

console.log(010)

})()

//UncaughtSyntaxError:Octalliteralsarenotallowedinstrictmode.

StrictMode

147

Page 148: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

YoucanstillenableoctalnumbersinStrictModeusingthe 0oXXsyntax:

;(()=>{

'usestrict'

console.log(0o10)

})()

//8

Removed with

StrictModedisablesthe withkeyword,toremovesomeedgecasesandallowmoreoptimizationatthecompilerlevel.

StrictMode

148

Page 149: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Immediately-invokedFunctionExpressions(IIFE)AnImmediately-invokedFunctionExpressionisawaytoexecutefunctionsimmediately,assoonastheyarecreated.IIFEsareveryusefulbecausetheydon'tpollutetheglobalobject,andtheyareasimplewaytoisolatevariablesdeclarations

AnImmediately-invokedFunctionExpression(IIFEforfriends)isawaytoexecutefunctionsimmediately,assoonastheyarecreated.

IIFEsareveryusefulbecausetheydon'tpollutetheglobalobject,andtheyareasimplewaytoisolatevariablesdeclarations.

ThisisthesyntaxthatdefinesanIIFE:

;(function(){

/**/

})()

IIFEscanbedefinedwitharrowfunctionsaswell:

Immediately-invokedFunctionExpressions(IIFE)

149

Page 150: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

;(()=>{

/**/

})()

Webasicallyhaveafunctiondefinedinsideparentheses,andthenweappend ()toexecutethatfunction: (https://flaviocopes.com/*function*/)().

Thosewrappingparenthesesareactuallywhatmakeourfunction,internally,beconsideredanexpression.Otherwise,thefunctiondeclarationwouldbeinvalid,becausewedidn'tspecifyanyname:

Functiondeclarationswantaname,whilefunctionexpressionsdonotrequireit.

Youcouldalsoputtheinvokingparenthesesinsidetheexpressionparentheses,thereisnodifference,justastylingpreference:

(function(){

/**/

}())

(()=>{

/**/

}())

AlternativesyntaxusingunaryoperatorsThereissomeweirdersyntaxthatyoucanusetocreateanIIFE,butit'sveryrarelyusedintherealworld,anditreliesonusinganyunaryoperator:

;-(function(){

/**/

})()+

(function(){

/**/

})()

Immediately-invokedFunctionExpressions(IIFE)

150

Page 151: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

~(function(){

/**/

})()

!(function(){

/**/

})()

(doesnotworkwitharrowfunctions)

NamedIIFEAnIIFEcanalsobenamedregularfunctions(notarrowfunctions).Thisdoesnotchangethefactthatthefunctiondoesnot"leak"totheglobalscope,anditcannotbeinvokedagainafteritsexecution:

;(functiondoSomething(){

/**/

})()

IIFEsstartingwithasemicolonYoumightseethisinthewild:

;(function(){

/**/

})()

ThispreventsissueswhenblindlyconcatenatingtwoJavaScriptfiles.SinceJavaScriptdoesnotrequiresemicolons,youmightconcatenatewithafilewithsomestatementsinitslastlinethatcausesasyntaxerror.

Thisproblemisessentiallysolvedwith"smart"codebundlerslikewebpack.

Immediately-invokedFunctionExpressions(IIFE)

151

Page 152: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

MathoperatorsPerformingmathoperationsandcalculusisaverycommonthingtodowithanyprogramminglanguage.JavaScriptoffersseveraloperatorstohelpusworkwithnumbers

Performingmathoperationsandcalculusisaverycommonthingtodowithanyprogramminglanguage.

JavaScriptoffersseveraloperatorstohelpusworkwithnumbers.

Operators

Arithmeticoperators

Addition(+)

constthree=1+2

constfour=three+1

The +operatoralsoservesasstringconcatenationifyouusestrings,sopayattention:

constthree=1+2

three+1//4

'three'+1//three1

Subtraction(-)

consttwo=4-2

Division(https://flaviocopes.com/)

Returnsthequotientofthefirstoperatorandthesecond:

constresult=20/5//result===4

constresult=20/7//result===2.857142857142857

Ifyoudividebyzero,JavaScriptdoesnotraiseanyerrorbutreturnsthe Infinityvalue(or -Infinityifthevalueisnegative).

Mathoperators

152

Page 153: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

1/0//Infinity

-1/0//-Infinity

Remainder(%)

Theremainderisaveryusefulcalculationinmanyusecases:

constresult=20%5//result===0

constresult=20%7//result===6

Areminderbyzeroisalways NaN,aspecialvaluethatmeans"NotaNumber":

1%0//NaN

-1%0//NaN

Multiplication(*)

1*2//2

-1*2//-2

Exponentiation(**)

Raisethefirstoperandtothepowersecondoperand

1**2//1

2**1//2

2**2//4

2**8//256

8**2//64

Unaryoperators

Increment(++)

Incrementanumber.Thisisaunaryoperator,andifputbeforethenumber,itreturnsthevalueincremented.

Ifputafterthenumber,itreturnstheoriginalvalue,thenincrementsit.

letx=0

x++//0

x//1

++x//2

Mathoperators

153

Page 154: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Decrement(--)

Worksliketheincrementoperator,exceptitdecrementsthevalue.

letx=0

x--//0

x//-1

--x//-2

Unarynegation(-)

Returnthenegationoftheoperand

letx=2

-x//-2

x//2

Unaryplus(+)

Iftheoperandisnotanumber,ittriestoconvertit.Otherwiseiftheoperandisalreadyanumber,itdoesnothing.

letx=2

+x//2

x='2'

+x//2

x='2a'

+x//NaN

AssignmentshortcutsTheregularassignmentoperator, =,hasseveralshortcutsforallthearithmeticoperatorswhichletyoucombineassignment,assigningtothefirstoperandtheresultoftheoperationswiththesecondoperand.

Theyare:

+=:additionassignment-=:subtractionassignment*=:multiplicationassignment

Mathoperators

154

Page 155: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

/=:divisionassignment%=:remainderassignment**=:exponentiationassignment

Examples:

consta=0

a+=5//a===5

a-=2//a===3

a*=2//a===6

a/=2//a===3

a%=2//a===1

PrecedencerulesEverycomplexstatementwillintroduceprecedenceproblems.

Takethis:

consta=1*2+5/2%2

Theresultis2.5,butwhy?Whatoperationsareexecutedfirst,andwhichneedtowait?

Someoperationshavemoreprecedencethantheothers.Theprecedencerulesarelistedinthistable:

Operator Description

- + ++ -- unaryoperators,incrementanddecrement

* / % multiply/divide

+ - addition/subtraction

= += -= *= /= %= **= assignments

Operationsonthesamelevel(like +and -)areexecutedintheordertheyarefound

Followingthistable,wecansolvethiscalculation:

consta=1*2+5/2%2

consta=1*2+5/2%2

consta=2+2.5%2

consta=2+0.5

consta=2.5

Mathoperators

155

Page 156: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Mathoperators

156

Page 157: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

TheMathobjectTheMathobjectcontainslotsofutilitiesmath-related.Thistutorialdescribesthemall

TheMathobjectcontainslotsofutilitiesmath-related.

Itcontainsconstantsandfunctions.

Constants

Item Description

Math.E Theconstante,baseofthenaturallogarithm(means~2.71828)

Math.LN10 Theconstantthatrepresentsthebasee(natural)logarithmof10

Math.LN2 Theconstantthatrepresentsthebasee(natural)logarithmof2

Math.LOG10E Theconstantthatrepresentsthebase10logarithmofe

Math.LOG2E Theconstantthatrepresentsthebase2logarithmofe

Math.PI Theπconstant(~3.14159)

Math.SQRT1_2 Theconstantthatrepresentsthereciprocalofthesquarerootof2

Math.SQRT2 Theconstantthatrepresentsthesquarerootof2

FunctionsAllthosefunctionsarestatic.Mathcannotbeinstantiated.

Math.abs()

Returnstheabsolutevalueofanumber

Math.abs(2.5)//2.5

Math.abs(-2.5)//2.5

Math.acos()

Returnsthearccosineoftheoperand

Theoperandmustbebetween-1and1

TheMathobject

157

Page 158: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Math.acos(0.8)//0.6435011087932843

Math.asin()

Returnsthearcsineoftheoperand

Theoperandmustbebetween-1and1

Math.asin(0.8)//0.9272952180016123

Math.atan()

Returnsthearctangentoftheoperand

Math.atan(30)//1.5374753309166493

Math.atan2()

Returnsthearctangentofthequotientofitsarguments.

Math.atan2(30,20)//0.982793723247329

Math.ceil()

Roundsanumberup

Math.ceil(2.5)//3

Math.ceil(2)//2

Math.ceil(2.1)//3

Math.ceil(2.99999)//3

Math.cos()

Returnthecosineofanangleexpressedinradiants

Math.cos(0)//1

Math.cos(Math.PI)//-1

Math.exp()

ReturnthevalueofMath.Emultipliedpertheexponentthat'spassedasargument

TheMathobject

158

Page 159: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Math.exp(1)//2.718281828459045

Math.exp(2)//7.38905609893065

Math.exp(5)//148.4131591025766

Math.floor()

Roundsanumberdown

Math.ceil(2.5)//2

Math.ceil(2)//2

Math.ceil(2.1)//2

Math.ceil(2.99999)//2

Math.log()

Returnthebasee(natural)logarithmofanumber

Math.log(10)//2.302585092994046

Math.log(Math.E)//1

Math.max()

Returnthehighestnumberinthesetofnumberspassed

Math.max(1,2,3,4,5)//5

Math.max(1)//1

Math.min()

Returnthesmallestnumberinthesetofnumberspassed

Math.max(1,2,3,4,5)//1

Math.max(1)//1

Math.pow()

Returnthefirstargumentraisedtothesecondargument

Math.pow(1,2)//1

Math.pow(2,1)//2

Math.pow(2,2)//4

Math.pow(2,4)//16

TheMathobject

159

Page 160: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Math.random()

Returnsapseudorandomnumberbetween0.0and1.0

Math.random()//0.9318168241227056

Math.random()//0.35268950194094395

Math.round()

Roundsanumbertothenearestinteger

Math.round(1.2)//1

Math.round(1.6)//2

Math.sin()

Calculatesthesinofanangleexpressedinradiants

Math.sin(0)//0

Math.sin(Math.PI)//1.2246467991473532e-16)

Math.sqrt()

Returnthesquarerootoftheargument

Math.sqrt(4)//2

Math.sqrt(16)//4

Math.sqrt(5)//2.23606797749979

Math.tan()

Calculatesthetangentofanangleexpressedinradiants

Math.tan(0)//0

Math.tan(Math.PI)//-1.2246467991473532e-16

TheMathobject

160

Page 161: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ESModulesESModulesistheECMAScriptstandardforworkingwithmodules.WhileNode.jshasbeenusingtheCommonJSstandardsinceyears,thebrowserneverhadamodulesystem,aseverymajordecisionsuchasamodulesystemmustbefirststandardizedbyECMAScriptandthenimplemented

IntroductiontoESModulesESModulesistheECMAScriptstandardforworkingwithmodules.

WhileNode.jshasbeenusingtheCommonJSstandardsinceyears,thebrowserneverhadamodulesystem,aseverymajordecisionsuchasamodulesystemmustbefirststandardizedbyECMAScriptandthenimplementedbythebrowser.

ThisstandardizationprocesscompletedwithES6andbrowsersstartedimplementingthisstandardtryingtokeepeverythingwellaligned,workingallinthesameway,andnowESModulesaresupportedinChrome,Safari,EdgeandFirefox(sinceversion60).

ESModules

161

Page 162: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Modulesareverycool,becausetheyletyouencapsulateallsortsoffunctionality,andexposethisfunctionalitytootherJavaScriptfiles,aslibraries.

TheESModulesSyntaxThesyntaxtoimportamoduleis:

importpackagefrom'module-name'

whileCommonJSuses

constpackage=require('module-name')

AmoduleisaJavaScriptfilethatexportsoneormorevalue(objects,functionsorvariables),usingthe exportkeyword.Forexample,thismoduleexportsafunctionthatreturnsastringuppercase:

uppercase.js

exportdefaultstr=>str.toUpperCase()

ESModules

162

Page 163: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Inthisexample,themoduledefinesasingle,defaultexport,soitcanbeananonymousfunction.Otherwiseitwouldneedanametodistinguishitfromotherexports.

Now,anyotherJavaScriptmodulecanimportthefunctionalityofferedbyuppercase.jsbyimportingit.

AnHTMLpagecanaddamodulebyusinga <script>tagwiththespecial type="module"attribute:

<scripttype="module"src="index.js"></script>

Note:thismoduleimportbehaveslikea deferscriptload.SeeefficientlyloadJavaScriptwithdeferandasync

It'simportanttonotethatanyscriptloadedwith type="module"isloadedinstrictmode.

Inthisexample,the uppercase.jsmoduledefinesadefaultexport,sowhenweimportit,wecanassignitanameweprefer:

importtoUpperCasefrom'./uppercase.js'

andwecanuseit:

toUpperCase('test')//'TEST'

Youcanalsouseanabsolutepathforthemoduleimport,toreferencemodulesdefinedonanotherdomain:

importtoUpperCasefrom'https://flavio-es-modules-example.glitch.me/uppercase.js'

Thisisalsovalidimportsyntax:

import{foo}from'/uppercase.js'

import{foo}from'../uppercase.js'

Thisisnot:

import{foo}from'uppercase.js'

import{foo}from'utils/uppercase.js'

It'seitherabsolute,orhasa ./or /beforethename.

ESModules

163

Page 164: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

Otherimport/exportoptionsWesawthisexampleabove:

exportdefaultstr=>str.toUpperCase()

Thiscreatesonedefaultexport.Inafilehoweveryoucanexportmorethanonething,byusingthissyntax:

consta=1

constb=2

constc=3

export{a,b,c}

Anothermodulecanimportallthoseexportsusing

import*from'module'

Youcanimportjustafewofthoseexports,usingthedestructuringassignment:

import{a}from'module'

import{a,b}from'module'

Youcanrenameanyimport,forconvenience,using as:

import{a,bastwo}from'module'

Youcanimportthedefaultexport,andanynon-defaultexportbyname,likeinthiscommonReactimport:

importReact,{Component}from'react'

YoucancheckanESModulesexampleonhttps://glitch.com/edit/#!/flavio-es-modules-example?path=index.html

CORS

ESModules

164

Page 165: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ModulesarefetchedusingCORS.Thismeansthatifyoureferencescriptsfromotherdomains,theymusthaveavalidCORSheaderthatallowscross-siteloading(like Access-Control-Allow-Origin:*)

Whataboutbrowsersthatdonotsupportmodules?Useacombinationof type="module"and nomodule:

<scripttype="module"src="module.js"></script>

<scriptnomodulesrc="fallback.js"></script>

ConclusionESModulesareoneofthebiggestfeaturesintroducedinmodernbrowsers.TheyarepartofES6buttheroadtoimplementthemhasbeenlong.

Wecannowusethem!Butwemustalsorememberthathavingmorethanafewmodulesisgoingtohaveaperformancehitonourpages,asit'sonemorestepthatthebrowsermustperformatruntime.

WebpackisprobablygoingtostillbeahugeplayerevenifESModuleslandinthebrowser,buthavingsuchafeaturedirectlybuiltinthelanguageishugeforaunificationofhowmodulesworkintheclient-sideandonNode.jsaswell.

ESModules

165

Page 166: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

CommonJSTheCommonJSmodulespecificationisthestandardusedinNode.jsforworkingwithmodules.Modulesareverycool,becausetheyletyouencapsulateallsortsoffunctionality,andexposethisfunctionalitytootherJavaScriptfiles,aslibraries

TheCommonJSmodulespecificationisthestandardusedinNode.jsforworkingwithmodules.

Client-sideJavaScriptthatrunsinthebrowserusesanotherstandard,calledESModules

Modulesareverycool,becausetheyletyouencapsulateallsortsoffunctionality,andexposethisfunctionalitytootherJavaScriptfiles,aslibraries.Theyletyoucreateclearlyseparateandreusablesnippetsoffunctionality,eachtestableonitsown.

ThehugenpmecosystemisbuiltuponthisCommonJSformat.

Thesyntaxtoimportamoduleis:

constpackage=require('module-name')

CommonJS

166

Page 167: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

InCommonJS,modulesareloadedsynchronously,andprocessedintheordertheJavaScriptruntimefindsthem.Thissystemwasbornwithserver-sideJavaScriptinmind,andisnotsuitablefortheclient-side(thisiswhyESModuleswereintroduced).

AJavaScriptfileisamodulewhenitexportsoneormoreofthesymbolsitdefines,beingthemvariables,functions,objects:

uppercase.js

exports.uppercase=str=>str.toUpperCase()

AnyJavaScriptfilecanimportandusethismodule:

constuppercaseModule=require('uppercase.js')

uppercaseModule.uppercase('test')

AsimpleexamplecanbefoundinthisGlitch.

Youcanexportmorethanonevalue:

exports.a=1

exports.b=2

exports.c=3

andimportthemindividuallyusingthedestructuringassignment:

const{a,b,c}=require('./uppercase.js')

orjustexportonevalueusing:

//file.js

module.exports=value

andimportitusing

constvalue=require('./file.js')

CommonJS

167

Page 168: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

GlossaryAguidetoafewtermsusedinfrontenddevelopmentthatmightbealientoyou

AsynchronousCodeisasynchronouswhenyouinitiatesomething,forgetaboutit,andwhentheresultisreadyyougetitbackwithouthavingtowaitforit.ThetypicalexampleisanAJAXcall,whichmighttakeevensecondsandinthemeantimeyoucompleteotherstuff,andwhentheresponseisready,thecallbackfunctiongetscalled.Promisesandasync/awaitarethemodernwaytohandleasync.

BlockInJavaScriptablockisdelimitedcurlybraces( {}).An ifstatementcontainsablock,aforloopcontainsablock.

BlockScopingWithFunctionScoping,anyvariabledefinedinablockisvisibleandaccessiblefrominsidethewholeblock,butnotoutsideofit.

CallbackAcallbackisafunctionthat'sinvokedwhensomethinghappens.Aclickeventassociatedtoanelementhasacallbackfunctionthat'sinvokedwhentheuserclickstheelement.Afetchrequesthasacallbackthat'scalledwhentheresourceisdownloaded.

DeclarativeAdeclarativeapproachiswhenyoutellthemachinewhatyouneedtodo,andyouletitfigureoutthedetails.Reactisconsidereddeclarative,asyoureasonaboutabstractionsratherthaneditingtheDOMdirectly.Everyhighlevelprogramminglanguageismoredeclarativethana

Glossary

168

Page 169: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

lowlevelprogramminglanguagelikeAssembler.JavaScriptismoredeclarativethanC.HTMLisdeclarative.

FallbackAfallbackisusedtoprovideagoodexperiencewhenauserhasn'taccesstoaparticularfunctionality.ForexampleauserthatbrowseswithJavaScriptdisabledshouldbeabletohaveafallbacktoaplainHTMLversionofthepage.OrforabrowserthathasnotimplementedanAPI,youshouldhaveafallbacktoavoidcompletelybreakingtheexperienceoftheuser.

FunctionScopingWithFunctionScoping,anyvariabledefinedinafunctionisvisibleandaccessiblefrominsidethewholefunction.

ImmutabilityAvariableisimmutablewhenitsvaluecannotchangeafterit'screated.Amutablevariablecanbechanged.Thesameappliestoobjectsandarrays.

LexicalScopingLexicalScopingisaparticularkindofscopingwherevariablesofaparentfunctionaremadeavailabletoinnerfunctionsaswell.Thescopeofaninnerfunctionalsoincludesthescopeofaparentfunction.

PolyfillApolyfillisawaytoprovidenewfunctionalityavailableinmodernJavaScriptoramodernbrowserAPItoolderbrowsers.Apolyfillisaparticularkindofshim.

PurefunctionAfunctionthathasnosideeffects(doesnotmodifyexternalresources),anditsoutputisonlydeterminedbythearguments.Youcouldcallthisfunction1Mtimes,andgiventhesamesetofarguments,theoutputwillalwaysbethesame.

Glossary

169

Page 170: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

ReassignmentJavaScriptwith varand letdeclarationallowsyoutoreassignavariableindefinitely.Withconstdeclarationsyoueffectivelydeclareanimmutablevalueforstrings,integers,booleans,andanobjectthatcannotbereassigned(butyoucanstillmodifyitthroughitsmethods).

ScopeScopeisthesetofvariablesthat'svisibletoapartoftheprogram.

ScopingScopingisthesetofrulesthat'sdefinedinaprogramminglanguagetodeterminethevalueofavariable.

ShimAshimisalittlewrapperaroundafunctionality,orAPI.It'sgenerallyusedtoabstractsomething,pre-fillparametersoraddapolyfillforbrowsersthatdonotsupportsomefunctionality.Youcanconsideritlikeacompatibilitylayer.

SideeffectAsideeffectiswhenafunctioninteractswithsomeotherfunctionorobjectoutsideit.Interactionwiththenetworkorthefilesystem,orwiththeUI,areallsideeffects.

StateStateusuallycomesintoplaywhentalkingaboutComponents.Acomponentcanbestatefulifitmanagesitsowndata,orstatelessifitdoesn't.

StatefulAstatefulcomponent,functionorclassmanagesitsownstate(data).Itcouldstoreanarray,acounteroranythingelse.

Glossary

170

Page 171: Table of Contents · checking (something that TypeScript and Flow aim to improve) interpreted: it's commonly known as an interpreted language, which means that it does not need a

StatelessAstatelesscomponent,functionorclassisalsocalleddumbbecauseit'sincapableofhavingitsowndatatomakedecisions,soitsoutputorpresentationisentirelybasedonitsarguments.Thisimpliesthatpurefunctionsarestateless.

StrictmodeStrictmodeisanECMAScript5.1newfeature,whichcausestheJavaScriptruntimetocatchmoreerrors,butithelpsyouimprovetheJavaScriptcodebydenyingundeclaredvariablesandotherthingsthatmightcauseoverlookedissueslikeduplicatedobjectpropertiesandothersubtlethings.Hint:useit.Thealternativeis"sloppymode"whichisnotagoodthingevenlookingatthenamewegaveit.

TreeShakingTreeshakingmeansremoving"deadcode"fromthebundleyoushiptoyourusers.Ifyouaddsomecodethatyouneveruseinyourimportstatements,that'snotgoingtobesenttotheusersofyourapp,toreducefilesizeandloadingtime.

Glossary

171