Table of Contents · The JavaScript Beginner's Handbook follows the 80/20 rule: learn in 20% of the...
Transcript of Table of Contents · The JavaScript Beginner's Handbook follows the 80/20 rule: learn in 20% of the...
TableofContentsPreface
IntroductiontoJavaScript
History
JustJavaScript
Syntax
Semicolons
Values
Variables
Types
Expressions
Operators
Precedence
Comparisons
Conditionals
Strings
Arrays
Loops
Functions
ArrowFunctions
Objects
Objectproperties
Objectmethods
Classes
Inheritance
AsynchonousProgrammingandCallbacks
Promises
2
AsyncandAwait
Variablesscope
Conclusion
3
PrefaceTheJavaScriptBeginner'sHandbook follows the80/20 rule: learn in20%ofthetimethe80%ofatopic.
Ifindthisapproachgivesawell-roundedoverview.
ThisbookdoesnottrytocovereverythingunderthesunrelatedtoJavaScript.It focuses on the core of the language, trying to simplify themore complextopics.
Ihopethecontentsofthisbookwillhelpyouachievewhatyouwant:learnthebasicsofJavaScript.
This book iswritten by Flavio. Ipublishweb development tutorials everydayonmywebsiteflaviocopes.com.
YoucanreachmeonTwitter@flaviocopes.
Enjoy!
4
IntroductiontoJavaScriptJavaScriptisoneofthemostpopularprogramminglanguagesintheworld.
Ibelieveit'sagreatlanguagetobeyourfirstprogramminglanguageever.
WemainlyuseJavaScripttocreate
websiteswebapplicationsserver-sideapplicationsusingNode.js
butJavaScriptisnotlimitedtothesethings,anditcanalsobeusedto
createmobileapplicationsusingtoolslikeReactNativecreateprogramsformicrocontrollersandtheinternetofthingscreatesmartwatchapplications
Itcanbasicallydoanything.It'ssopopularthateverythingnewthatshowsupisgoingtohavesomekindofJavaScriptintegrationatsomepoint.
JavaScriptisaprogramminglanguagethatis:
highlevel: itprovidesabstractionsthatallowyoutoignorethedetailsofthemachinewhereit'srunningon.Itmanagesmemoryautomaticallywithagarbagecollector, soyoucan focuson thecode insteadofmanagingmemory like other languages like C would need, and provides manyconstructs which allow you to deal with highly powerful variables andobjects.dynamic:opposedtostaticprogramminglanguages,adynamiclanguageexecutes at runtime many of the things that a static language does atcompile time.Thishasprosandcons,and itgivesuspowerful featureslike dynamic typing, late binding, reflection, functional programming,object runtime alteration, closures andmuchmore.Don't worry if thosethings are unknown to you - you'll know all of those at the end of thecourse.dynamicallytyped:avariabledoesnotenforceatype.Youcanreassign
5
anytypetoavariable,forexample,assigninganintegertoavariablethatholdsastring.loosely typed: as opposed to strong typing, loosely (or weakly) typedlanguagesdonot enforce the typeof anobject, allowingmore flexibilitybutdenyingustypesafetyandtypechecking(somethingthatTypeScript-whichbuildsontopofJavaScript-provides)interpreted: it's commonly known as an interpreted language, whichmeans that it does not need a compilation stage before a program canrun,asopposed toC,JavaorGo forexample. Inpractice,browsersdocompileJavaScriptbeforeexecutingit, forperformancereasons,butthisistransparenttoyou:thereisnoadditionalstepinvolved.multi-paradigm: the language does not enforce any particularprogrammingparadigm,unlikeJavaforexample,whichforcestheuseofobject-oriented programming, or C that forces imperative programming.You can write JavaScript using an object-oriented paradigm, usingprototypes and the new (as of ES6) classes syntax. You can writeJavaScriptinafunctionalprogrammingstyle,withitsfirst-classfunctions,oreveninanimperativestyle(C-like).
Incaseyou'rewondering,JavaScripthasnothingtodowithJava, it'sapoornamechoicebutwehavetolivewithit.
6
HistoryCreated in 1995, JavaScript has gone a very long way since its humblebeginnings.
It was the first scripting language that was supported natively by webbrowsers,andthankstothisitgainedacompetitiveadvantageoveranyotherlanguage and today it's still the only scripting language that we can use tobuildWebApplications.
Otherlanguagesexist,butallmustcompiletoJavaScript-ormorerecentlytoWebAssembly,butthisisanotherstory.
Inthebeginnings,JavaScriptwasnotnearlypowerfulasitistoday,anditwasmainly used for fancy animations and the marvel known at the time asDynamicHTML.
With the growing needs that the web platform demanded (and continues todemand),JavaScripthad the responsibility togrowaswell, toaccommodatetheneedsofoneofthemostwidelyusedecosystemsoftheworld.
JavaScriptisnowwidelyusedalsooutsideofthebrowser.TheriseofNode.jsin the last few years unlocked backend development, once the domain ofJava,Ruby,Python,PHPandmoretraditionalserver-sidelanguages.
JavaScript is now also the language powering databases and many moreapplications,andit'sevenpossibletodevelopembeddedapplications,mobileapps,TVsetsappsandmuchmore.Whatstartedasa tiny language insidethebrowserisnowthemostpopularlanguageintheworld.
7
JustJavaScriptSometimes it's hard to separate JavaScript from the features of theenvironmentitisusedin.
Forexample,the console.log()lineyoucanfindinmanycodeexamplesisnotJavaScript.Instead,it'spartofthevastlibraryofAPIsprovidedtousinthebrowser.Inthesameway,ontheserveritcanbesometimeshardtoseparatetheJavaScriptlanguagefeaturesfromtheAPIsprovidedbyNode.js.
IsaparticularfeatureprovidedbyReactorVue?Orisit"plainJavaScript",or"vanillaJavaScript"asoftencalled?
InthisbookItalkaboutJavaScript,thelanguage.
Without complicatingyour learningprocesswith things thatareoutsideof it,andprovidedbyexternalecosystems.
8
SyntaxInthislittleintroductionIwanttotellyouabout5concepts:
whitespacecasesensitivityliteralsidentifierscomments
WhitespaceJavaScriptdoesnotconsiderwhitespacemeaningful.Spacesandlinebreakscanbeaddedinanyfashionyoumightlike,eventhoughthisisintheory.
Inpractice,youwillmost likelykeepawelldefinedstyleandadhere towhatpeoplecommonlyuse,andenforce thisusinga linterorastyle toolsuchasPrettier.
Forexample,Iliketoalways2characterstoindent.
CasesensitiveJavaScript is case sensitive.A variable named something is different fromSomething.
Thesamegoesforanyidentifier.
LiteralsWedefineasliteralavaluethatiswritteninthesourcecode,forexample,anumber, a string, a boolean or also more advanced constructs, like ObjectLiteralsorArrayLiterals:
9
5
'Test'
true
['a','b']
{color:'red',shape:'Rectangle'}
IdentifiersAn identifier is a sequence of characters that can be used to identify avariable,afunction,anobject.Itcanstartwithaletter,thedollarsign$oranunderscore _,and itcancontaindigits.UsingUnicode,a lettercanbeanyallowedchar,forexample,anemojiߠ .
Test
test
TEST
_test
Test1
$test
ThedollarsigniscommonlyusedtoreferenceDOMelements.
SomenamesarereservedforJavaScriptinternaluse,andwecan'tusethemasidentifiers.
CommentsComments are one of the most important part of any program. In anyprogramminglanguage.Theyareimportantbecausetheyletusannotatethecodeandadd important information thatotherwisewouldnotbeavailable tootherpeople(orourselves)readingthecode.
InJavaScript,wecanwriteacommentonasinglelineusing //.Everythingafter//isnotconsideredascodebytheJavaScriptinterpreter.
10
Likethis:
//acomment
true//anothercomment
Anothertypeofcommentisamulti-linecomment.Itstartswith /*andendswith*/.
Everythinginbetweenisnotconsideredascode:
/*somekind
of
comment
*/
11
SemicolonsEverylineinaJavaScriptprogramisoptionallyterminatedusingsemicolons.
I said optionally, because the JavaScript interpreter is smart enough tointroducesemicolonsforyou.
Inmostcases,youcanomitsemicolonsaltogetherfromyourprograms.
This fact is very controversial, and you'll always find code that usessemicolonsandcodethatdoesnot.
My personal preference is to always avoid semicolons unless strictlynecessary.
12
ValuesAhellostringisavalue.Anumberlike12isavalue.
helloand 12 arevalues. string and number are the types of thosevalues.
The type is thekindofvalue, itscategory.Wehavemanydifferent types inJavaScript,andwe'lltalkaboutthemindetaillateron.Eachtypehasitsowncharacteristics.
Whenweneedtohaveareferencetoavalue,weassignittoavariable.Thevariablecanhaveaname,andthevalueiswhat'sstoredinavariable,sowecanlateraccessthatvaluethroughthevariablename.
13
VariablesAvariableisavalueassignedtoanidentifier,soyoucanreferenceanduseitlaterintheprogram.
ThisisbecauseJavaScriptislooselytyped,aconceptyou'll frequentlyhearabout.
Avariablemustbedeclaredbeforeyoucanuseit.
Wehave2mainwaystodeclarevariables.Thefirstistouseconst:
consta=0
Thesecondwayistouselet:
leta=0
What'sthedifference?
const defines a constant reference to a value. Thismeans the referencecannotbechanged.Youcannotreassignanewvaluetoit.
Usingletyoucanassignanewvaluetoit.
Forexample,youcannotdothis:
consta=0
a=1
Becauseyou'llgetanerror:TypeError:Assignmenttoconstantvariable..
Ontheotherhand,youcandoitusinglet:
leta=0
a=1
14
const does notmean "constant" in the way some other languages like Cmean. In particular, it doesnotmean the value cannot change - itmeans itcannotbereassigned.Ifthevariablepointstoanobjectoranarray(we'llseemoreaboutobjectsandarrayslater)thecontentoftheobjectorthearraycanfreelychange.
Constvariablesmustbeinitializedatthedeclarationtime:
consta=0
butletvaluescanbeinitializedlater:
leta
a=0
Youcandeclaremultiplevariablesatonceinthesamestatement:
consta=1,b=2
letc=1,d=2
Butyoucannotredeclarethesamevariablemorethanonetime:
leta=1
leta=2
oryou'dgeta"duplicatedeclaration"error.
Myadviceistoalwaysuse constandonlyuse letwhenyouknowyou'llneed to reassignavalue to thatvariable.Why?Because the lesspowerourcodehas, thebetter. Ifweknowavaluecannotbe reassigned, it'sone lesssourceforbugs.
Nowthatwesawhowtoworkwithconstandlet,Iwanttomentionvar.
15
Until2015, varwastheonlywaywecoulddeclareavariableinJavaScript.Today,amoderncodebasewillmostlikelyjustuse constand let.Therearesomefundamentaldifferenceswhich Idetail inthispostbut ifyou're juststartingout,youmightnotcareabout.Justuseconstandlet.
16
TypesVariablesinJavaScriptdonothaveanytypeattached.
Theyareuntyped.
Onceyouassignavaluewithsometypetoavariable,youcanlaterreassignthevariabletohostavalueofanyothertype,withoutanyissue.
In JavaScript we have 2 main kinds of types: primitive types and objecttypes.
PrimitivetypesPrimitivetypesare
numbersstringsbooleanssymbols
Andtwospecialtypes:nullandundefined.
ObjecttypesAnyvaluethat'snotofaprimitivetype(astring,anumber,aboolean,nullorundefined)isanobject.
Object typeshavepropertiesandalsohavemethods thatcanacton thoseproperties.
We'lltalkmoreaboutobjectslateron.
17
18
ExpressionsAnexpression isa singleunit of JavaScript code that theJavaScriptenginecanevaluate,andreturnavalue.
Expressionscanvaryincomplexity.
Westartfromtheverysimpleones,calledprimaryexpressions:
2
0.02
'something'
true
false
this//thecurrentscope
undefined
i//whereiisavariableoraconstant
Arithmetic expressionsareexpressions that takea variable andanoperator(moreonoperatorssoon),andresultintoanumber:
1/2
i++
i-=2
i*2
Stringexpressionsareexpressionsthatresultintoastring:
'A'+'string'
Logical expressionsmakeuseof logical operatorsand resolve toabooleanvalue:
a&&b
a||b
!a
19
More advanced expressions involve objects, functions, and arrays, and I'llintroducethemlater.
20
OperatorsOperatorsallowyoutogettwosimpleexpressionsandcombinethemtoformamorecomplexexpression.
We can classify operators based on the operands they work with. Someoperatorsworkwith1operand.Mostwith2operands.Justoneoperatorworkswith3operands.
Inthisfirstintroductiontooperators,we'llintroducetheoperatorsyouaremostlikelyfamilarwith:binaryoperators.
I already introduced one when talking about variables: the assignmentoperator=.Youuse=toassignavaluetoavariable:
letb=2
Let'snow introduceanother setofbinaryoperators that youalready familiarwith,frombasicmath.
Theadditionoperator(+)
constthree=1+2
constfour=three+1
The+operatoralsoservesasstringconcatenationifyouusestrings,sopayattention:
constthree=1+2
three+1//4
'three'+1//three1
Thesubtractionoperator(-)
21
consttwo=4-2
Thedivisionoperator(/)
Returnsthequotientofthefirstoperatorandthesecond:
constresult=20/5//result===4
constresult=20/7//result===2.857142857142857
If you divide by zero, JavaScript does not raise any error but returns theInfinityvalue(or-Infinityifthevalueisnegative).
1/0//Infinity
-1/0//-Infinity
Theremainderoperator(%)
Theremainderisaveryusefulcalculationinmanyusecases:
constresult=20%5//result===0
constresult=20%7//result===6
A reminder by zero is always NaN , a special value that means "Not aNumber":
1%0//NaN
-1%0//NaN
Themultiplicationoperator(*)
Multiplytwonumbers
1*2//2
-1*2//-2
22
Theexponentiationoperator(**)
Raisethefirstoperandtothepowersecondoperand
1**2//1
2**1//2
2**2//4
2**8//256
8**2//64
23
PrecedenceEverycomplexstatementwithmultipleoperatorsinthesamelinewillintroduceprecedenceproblems.
Takethisexample:
leta=1*2+5/2%2
Theresultis2.5,butwhy?
Whatoperationsareexecutedfirst,andwhichneedtowait?
Some operations have more precedence than the others. The precedencerulesarelistedinthistable:
Operator Description
*/% multiplication/division
+- addition/subtraction
= assignment
Operationsonthesamelevel(like +and-)areexecutedintheordertheyarefound,fromlefttoright.
Followingtheserules,theoperationabovecanbesolvedinthisway:
leta=1*2+5/2%2
leta=2+5/2%2
leta=2+2.5%2
leta=2+0.5
leta=2.5
24
ComparisonsAfter assignment and math operators, the third set of operators I want tointroduceisconditionaloperators.
Youcanusethefollowingoperatorstocomparetwonumbers,ortwostrings.
Comparison operators always returns a boolean, a value that's true orfalse).
Thosearedisequalitycomparisonoperators:
<means"lessthan"<=means"minusthan,orequalto">means"greaterthan">=means"greaterthan,orequalto"
Example:
leta=2
a>=1//true
Inadditiontothose,wehave4equalityoperators.Theyaccept twovalues,andreturnaboolean:
===checksforequality!==checksforinequality
Notethatwealsohave==and!=inJavaScript,butIhighlysuggesttoonlyuse===and!==becausetheycanpreventsomesubtleproblems.
25
ConditionalsWiththecomparisonoperatorsinplace,wecantalkaboutconditionals.
An if statement is used to make the program take a route, or another,dependingontheresultofanexpressionevaluation.
Thisisthesimplestexample,whichalwaysexecutes:
if(true){
//dosomething
}
onthecontrary,thisisneverexecuted:
if(false){
//dosomething(?never?)
}
Theconditionalcheckstheexpressionyoupasstoitfortrueorfalsevalue.Ifyoupassanumber, thatalwaysevaluatestotrueunless it's0. Ifyoupassastring, it always evaluates to true unless it's an empty string. Those aregeneralrulesofcastingtypestoaboolean.
Didyounoticethecurlybraces?Thatiscalledablock,anditisusedtogroupalistofdifferentstatements.
Ablockcanbeputwhereveryoucanhaveasinglestatement.Andifyouhaveasinglestatement toexecuteafter theconditionals, youcanomit theblock,andjustwritethestatement:
if(true)doSomething()
ButIalwaysliketousecurlybracestobemoreclear.
26
ElseYoucanprovideasecondparttotheifstatement:else.
Youattacha statement that is going to beexecuted if the if condition isfalse:
if(true){
//dosomething
}else{
//dosomethingelse
}
Since else accepts a statement, you can nest another if/else statementinsideit:
if(a===true){
//dosomething
}elseif(b===true){
//dosomethingelse
}else{
//fallback
}
27
StringsAstringisasequenceofcharacters.
Itcanbealsodefinedasastringliteral,whichisenclosedinquotesordoublequotes:
'Astring'
"Anotherstring"
I personallyprefer singlequotesall the time,andusedoublequotesonly inHTMLtodefineattributes.
Youassignastringvaluetoavariablelikethis:
constname='Flavio'
Youcandeterminethelengthofastringusingthelengthpropertyofit:
'Flavio'.length//6
constname='Flavio'
name.length//6
Thisisanemptystring:''.Itslengthpropertyis0:
''.length//0
Twostringscanbejoinedusingthe+operator:
"A"+"string"
Youcanusethe+operatortointerpolatevariables:
constname='Flavio'
28
"Mynameis"+name//MynameisFlavio
Another way to define strings is to use template literals, defined insidebackticks.Theyareespeciallyuseful tomakemultilinestringsmuchsimpler.With single or double quotes you can't define amultiline string easily: you'dneedtouseescapingcharacters.
Once a template literal is opened with the backtick, you just press enter tocreateanewline,withnospecialcharacters,andit'srenderedas-is:
conststring=`Hey
this
string
isawesome!`
Template literals are also great because they provide an easy way tointerpolatevariablesandexpressionsintostrings.
Youdosobyusingthe${...}syntax:
constvar='test'
conststring=`something${var}`
//somethingtest
insidethe${}youcanaddanything,evenexpressions:
conststring=`something${1+2+3}`
conststring2=`something
${foo()?'x':'y'}`
29
ArraysAnarrayisacollectionofelements.
ArraysinJavaScriptarenotatypeontheirown.
Arraysareobjects.
Wecaninitializeanemptyarrayinthese2differentways:
consta=[]
consta=Array()
Thefirstisusingthearrayliteralsyntax.ThesecondusestheArraybuilt-infunction.
Youcanpre-fillthearrayusingthissyntax:
consta=[1,2,3]
consta=Array.of(1,2,3)
Anarraycanholdanyvalue,evenvalueofdifferenttypes:
consta=[1,'Flavio',['a','b']]
Since we can add an array into an array, we can create multi-dimensionalarrays,whichhaveveryusefulapplications(e.g.amatrix):
constmatrix=[
[1,2,3],
[4,5,6],
[7,8,9]
]
matrix[0][0]//1
matrix[2][0]//7
30
Youcanaccessanyelementofthearraybyreferencingitsindex,whichstartsfromzero:
a[0]//1
a[1]//2
a[2]//3
Youcaninitializeanewarraywithasetofvaluesusingthissyntax,whichfirstinitializesanarrayof12elements,andfillseachelementwiththe0number:
Array(12).fill(0)
You can get the number of elements in the array by checking its lengthproperty:
consta=[1,2,3]
a.length//3
Note thatyoucanset the lengthof thearray. Ifyouassignabiggernumberthan the arrays current capacity, nothing happens. If you assign a smallernumber,thearrayiscutatthatposition:
consta=[1,2,3]
a//[1,2,3]
a.length=2
a//[1,2]
HowtoaddanitemtoanarrayWecanaddanelementattheendofanarrayusingthepush()method:
a.push(4)
31
We can add an element at the beginning of an array using the unshift()method:
a.unshift(0)
a.unshift(-2,-1)
HowtoremoveanitemfromanarrayWecanremoveanitemfromtheendofanarrayusingthepop()method:
a.pop()
Wecan removean item from thebeginningof anarrayusing the shift()method:
a.shift()
HowtojointwoormorearraysYoucanjoinmultiplearraysbyusingconcat():
consta=[1,2]
constb=[3,4]
constc=a.concat(b)//[1,2,3,4]
a//[1,2]
b//[3,4]
Youcanalsousethespreadoperator(...)inthisway:
consta=[1,2]
constb=[3,4]
constc=[...a,...b]
c//[1,2,3,4]
32
HowtofindaspecificiteminthearrayYoucanusethefind()methodofanarray:
a.find((element,index,array)=>{
//returntrueorfalse
})
Returnsthefirstitemthatreturnstrue.Returnsundefinediftheelementisnotfound.
Acommonlyusedsyntaxis:
a.find(x=>x.id===my_id)
Theabovelinewillreturnthefirstelementinthearraythathasid===my_id.
findIndex()workssimilarlytofind(),butreturnstheindexofthefirstitemthatreturnstrue,andifnotfound,itreturnsundefined:
a.findIndex((element,index,array)=>{
//returntrueorfalse
})
Anothermethodisincludes():
a.includes(value)
Returnstrueifacontainsvalue.
a.includes(value,i)
Returnstrueifacontainsvalueafterthepositioni.
33
34
LoopsLoopsareoneofthemaincontrolstructuresofJavaScript.
Withaloopwecanautomateandrepeatindefinitelyablockofcode,forhowmanytimeswewantittorun.
JavaScriptprovidesmanywaytoiteratethroughloops.
Iwanttofocuson3ways:
whileloopsforloopsfor..ofloops
while
ThewhileloopisthesimplestloopingstructurethatJavaScriptprovidesus.
Weaddaconditionafterthe whilekeyword,andweprovideablockthatisrununtiltheconditionevaluatestotrue.
Example:
constlist=['a','b','c']
leti=0
while(i<list.length){
console.log(list[i])//value
console.log(i)//index
i=i+1
}
Youcaninterruptawhileloopusingthebreakkeyword,likethis:
while(true){
if(somethingIsTrue)break
}
35
and if you decide that in themiddle of a loop you want to skip the currentiteration,youcanjumptothenextiterationusingcontinue:
while(true){
if(somethingIsTrue)continue
//dosomethingelse
}
Verysimilarto while,wehave do..while loops.It'sbasicallythesameaswhile,excepttheconditionisevaluatedafterthecodeblockisexecuted.
Thismeanstheblockisalwaysexecutedatleastonce.
Example:
constlist=['a','b','c']
leti=0
do{
console.log(list[i])//value
console.log(i)//index
i=i+1
}while(i<list.length)
for
ThesecondveryimportantloopingstructureinJavaScriptistheforloop.
We use the for keyword and we pass a set of 3 instructions: theinitialization,thecondition,andtheincrementpart.
Example:
constlist=['a','b','c']
for(leti=0;i<list.length;i++){
console.log(list[i])//value
console.log(i)//index
36
}
Justlikewith whileloops,youcaninterrupta forloopusing breakandyoucanfastforwardtothenextiterationofaforloopusingcontinue.
for...of
Thisloopisrelativelyrecent(introducedin2015)andit'sasimplifiedversionoftheforloop:
constlist=['a','b','c']
for(constvalueoflist){
console.log(value)//value
}
37
FunctionsIn any moderately complex JavaScript program, everything happens insidefunctions.
Functionsareacore,essentialpartofJavaScript.
Whatisafunction?
Afunctionisablockofcode,selfcontained.
Here'safunctiondeclaration:
functiongetData(){
//dosomething
}
Afunctioncanberunanytimesyouwantbyinvokingit,likethis:
getData()
Afunctioncanhaveoneormoreargument:
functiongetData(){
//dosomething
}
functiongetData(color){
//dosomething
}
functiongetData(color,age){
//dosomething
}
Whenwecanpassanargument,weinvokethefunctionpassingparameters:
38
functiongetData(color,age){
//dosomething
}
getData('green',24)
getData('black')
Note that in thesecond invokation Ipassed the black stringparameterasthe colorargument,butno age. In thiscase, age inside the function isundefined.
Wecancheckifavalueisnotundefinedusingthisconditional:
functiongetData(color,age){
//dosomething
if(typeofage!=='undefined'){
//...
}
}
typeofisaunaryoperatorthatallowsustocheckthetypeofavariable.
Youcanalsocheckinthisway:
functiongetData(color,age){
//dosomething
if(age){
//...
}
}
although theconditionalwillalsobe true if age is null, 0 oranemptystring.
Youcanhavedefaultvaluesforparameters,incasetheyarenotpassed:
functiongetData(color='black',age=25){
//dosomething
39
}
Youcanpassanyvalueasaparameter:numbers,strings,booleans,arrays,objects,andalsofunctions.
Afunctionhasareturnvalue.Bydefaultafunctionreturnsundefined,unlessyouaddareturnkeywordwithavalue:
functiongetData(){
//dosomething
return'hi!'
}
Wecanassignthisreturnvaluetoavariablewhenweinvokethefunction:
functiongetData(){
//dosomething
return'hi!'
}
letresult=getData()
resultnowholdsastringwiththethehi!value.
Youcanonlyreturnonevalue.
Toreturnmultiplevalues,youcanreturnanobject,oranarray,likethis:
functiongetData(){
return['Flavio',37]
}
let[name,age]=getData()
Functionscanbedefinedinsideotherfunctions:
constgetData=()=>{
constdosomething=()=>{}
40
dosomething()
return'test'
}
The nested function cannot be called from the outside of the enclosingfunction.
Youcanreturnafunctionfromafunction,too.
41
ArrowFunctionsArrowfunctionsarearecentintroductiontoJavaScript.
Theyareveryoftenusedinsteadof"regular"functions,theoneIdescribedinthepreviouschapter.You'llfindbothformsusedeverywhere.
Visually,theyallowsyoutowritefunctionswithashortersyntax,from:
functiongetData(){
//...
}
to
()=>{
//...
}
But..noticethatwedon'thaveanamehere.
Arrowfunctionsareanonymous.Wemustassignthemtoavariable.
Wecanassignaregularfunctiontoavariable,likethis:
letgetData=functiongetData(){
//...
}
Whenwedoso,wecanremovethenamefromthefunction:
letgetData=function(){
//...
}
andinvokethefunctionusingthevariablename:
42
letgetData=function(){
//...
}
getData()
That'sthesamethingwedowitharrowfunctions:
letgetData=()=>{
//...
}
getData()
If the function body contains just a single statement, you can omit theparenthesesandwriteallonasingleline:
constgetData=()=>console.log('hi!')
Parametersarepassedintheparentheses:
constgetData=(param1,param2)=>
console.log(param1,param2)
If you have one (and just one) parameter, you could omit the parenthesescompletely:
constgetData=param=>console.log(param)
Arrow functions allow you to have an implicit return: values are returnedwithouthavingtousethereturnkeyword.
Itworkswhenthereisaon-linestatementinthefunctionbody:
constgetData=()=>'test'
getData()//'test'
43
Likewithregularfunctions,wecanhavedefaultparameters:
Youcanhavedefaultvaluesforparameters,incasetheyarenotpassed:
constgetData=(color='black',
age=2)=>{
//dosomething
}
andwecanonlyreturnonevalue.
Arrowfunctionscancontainotherarrowfunction,oralsoregularfunctions.
The are very similar, so youmight ask why they were introduced? The bigdifference with regular functions is when they are used as object methods.Thisissomethingwe'llsoonlookinto.
44
ObjectsAny value that's not of a primitive type (a string, a number, a boolean, asymbol,null,orundefined)isanobject.
Here'showwedefineanobject:
constcar={
}
Thisistheobjectliteralsyntax,whichisoneofthenicestthingsinJavaScript.
YoucanalsousethenewObjectsyntax:
constcar=newObject()
AnothersyntaxistouseObject.create():
constcar=Object.create()
Youcanalsoinitializeanobjectusingthenewkeywordbeforeafunctionwithacapital letter.Thisfunctionservesasaconstructor for thatobject. In there,wecaninitializetheargumentswereceiveasparameters, tosetupthe initialstateoftheobject:
functionCar(brand,model){
this.brand=brand
this.model=model
}
Weinitializeanewobjectusing
constmyCar=newCar('Ford','Fiesta')
myCar.brand//'Ford'
45
myCar.model//'Fiesta'
Objectsarealwayspassedbyreference.
Ifyouassignavariablethesamevalueofanother,ifit'saprimitivetypelikeanumberorastring,theyarepassedbyvalue:
Takethisexample:
letage=36
letmyAge=age
myAge=37
age//36
constcar={
color:'blue'
}
constanotherCar=car
anotherCar.color='yellow'
car.color//'yellow'
Evenarraysorfunctionsare,underthehoods,objects,soit'sveryimportanttounderstandhowtheywork.
46
ObjectpropertiesObjects haveproperties,which are composed by a label associatedwith avalue.
The value of a property can be of any type,whichmeans that it can be anarray, a function, and it can even be an object, as objects can nest otherobjects.
Thisistheobjectliteralsyntaxwesawinthepreviouschapter:
constcar={
}
Wecandefineacolorpropertyinthisway:
constcar={
color:'blue'
}
herewehaveacarobjectwithapropertynamedcolor,withvalueblue.
Labelscanbeanystring,butbewarespecialcharacters:ifIwantedtoincludeacharacternotvalidasavariablename in thepropertyname, Iwouldhavehadtousequotesaroundit:
constcar={
color:'blue',
'thecolor':'blue'
}
Invalidvariablenamecharacters includespaces,hyphens,andotherspecialcharacters.
47
Asyousee,whenwehavemultipleproperties,weseparateeachpropertywithacomma.
Wecanretrievethevalueofapropertyusing2differentsyntaxes.
Thefirstisdotnotation:
car.color//'blue'
The second (which is the only one we can use for properties with invalidnames),istousesquarebrackets:
car['thecolor']//'blue'
Ifyouaccessanunexistingproperty,you'llgettheundefinedvalue:
car.brand//undefined
Assaid,objectscanhavenestedobjectsasproperties:
constcar={
brand:{
name:'Ford'
},
color:'blue'
}
Inthisexample,youcanaccessthebrandnameusing
car.brand.name
or
car['brand']['name']
48
Youcansetthevalueofapropertywhenyoudefinetheobject.
Butyoucanalwaysupdateitlateron:
constcar={
color:'blue'
}
car.color='yellow'
car['color']='red'
Andyoucanalsoaddnewpropertiestoanobject:
car.model='Fiesta'
car.model//'Fiesta'
Giventheobject
constcar={
color:'blue',
brand:'Ford'
}
youcandeleteapropertyfromthisobjectusing
deletecar.brand
49
ObjectmethodsItalkedaboutfunctionsinapreviouschapter.
Functions can be assigned to a function property, and in this case they arecalledmethods.
In this example, the start property has a function assigned, andwe caninvokeitbyusingthedotsyntaxweusedforproperties,withtheparenthesesattheend:
constcar={
brand:'Ford',
model:'Fiesta',
start:function(){
console.log('Started')
}
}
car.start()
Insideamethoddefinedusingafunction(){}syntaxwehaveaccesstotheobjectinstancebyreferencingthis.
In the following example, we have access to the brand and model
propertiesvaluesusingthis.brandandthis.model:
constcar={
brand:'Ford',
model:'Fiesta',
start:function(){
console.log(`Started
${this.brand}${this.model}`)
}
}
car.start()
50
It's important to note this distinction between regular functions and arrowfunctions:wedon'thaveaccesstothisifweuseanarrowfunction:
constcar={
brand:'Ford',
model:'Fiesta',
start:()=>{
console.log(`Started
${this.brand}${this.model}`)//notgoingtowork
}
}
car.start()
Thisisbecausearrowfunctionsarenotboundtotheobject.
Thisisthereasonwhyregularfunctionsareoftenusedasobjectmethods.
Methodscanacceptparameters,likeregularfunctions:
constcar={
brand:'Ford',
model:'Fiesta',
goTo:function(destination){
console.log(`Goingto${destination}`)
}
}
car.goTo('Rome')
51
ClassesWe talked about objects, which are one of the most interesting parts ofJavaScript.
Inthischapterwe'llgouponelevel,introducingclasses.
What are classes?They are away to define a commonpattern formultipleobjects.
Let'stakeapersonobject:
constperson={
name:'Flavio'
}
We can create a class named Person (note the capital P , a conventionwhenusingclasses),thathasanameproperty:
classPerson{
name
}
Nowfromthisclass,weinitializeaflavioobjectlikethis:
constflavio=newPerson()
flavioiscalledaninstanceofthePersonclass.
Wecansetthevalueofthenameproperty:
flavio.name='Flavio'
andwecanaccessitusing
52
flavio.name
likewedoforobjectproperties.
Classescanholdproperties,likename,andmethods.
Methodsaredefinedinthisway:
classPerson{
hello(){
return'Hello,IamFlavio'
}
}
andwecaninvokemethodsonaninstanceoftheclass:
classPerson{
hello(){
return'Hello,IamFlavio'
}
}
constflavio=newPerson()
flavio.hello()
There is a specialmethod called called constructor() thatwe can use toinitializetheclasspropertieswhenwecreateanewobjectinstance.
Itworkslikethis:
classPerson{
constructor(name){
this.name=name
}
hello(){
return'Hello,Iam'+this.name+'.'
}
}
53
Notehowweusethistoaccesstheobjectinstance.
Now we can instantiate a new object from the class, passing a string, andwhenwecallhello,we'llgetapersonalizedmessage:
constflavio=newPerson('flavio')
flavio.hello()//'Hello,Iamflavio.'
When the object is initialized, the constructor method is called, with anyparameterspassed.
Normallymethodsaredefinedontheobjectinstance,notontheclass.
Youcandefineamethodas static toallow it tobeexecutedontheclassinstead:
classPerson{
staticgenericHello(){
return'Hello'
}
}
Person.genericHello()//Hello
Thisisveryuseful,attimes.
54
InheritanceA class can extend another class, and objects initialized using that classinheritallthemethodsofbothclasses.
SupposewehaveaclassPerson:
classPerson{
hello(){
return'Hello,IamaPerson'
}
}
WecandefineanewclassProgrammerthatextendsPerson:
classProgrammerextendsPerson{
}
NowifweinstantiateanewobjectwithclassProgrammer,ithasaccesstothehello()method:
constflavio=newProgrammer()
flavio.hello()//'Hello,IamaPerson'
Insideachildclass,youcanreferencetheparentclasscallingsuper():
classProgrammerextendsPerson{
hello(){
returnsuper.hello()+
'.Iamalsoaprogrammer.'
}
}
constflavio=newProgrammer()
flavio.hello()
55
TheaboveprogramprintsHello,IamaPerson.Iamalsoaprogrammer..
56
AsynchonousProgrammingandCallbacksMostofthetime,JavaScriptcodeisransynchronously.
Thismeansthatalineofcodeisexecuted,thenthenextoneisexecuted,andsoon.
Everything is as you expect, and how it works in most programminglanguages.
However there are times when you cannot just wait for a line of code toexecute.
You can't just wait 2 seconds for a big file to load, and halt the programcompletely.
You can't just wait for a network resource to be downloaded, before doingsomethingelse.
JavaScriptsolvesthisproblemusingcallbacks.
Oneofthesimplestexamplesofhowtousecallbacksistimers.TimersarenotpartofJavaScript,buttheyareprovidedbythebrowser,andNode.js.Letmetalkaboutoneofthetimerswehave:setTimeout().
The setTimeout() functionaccepts2arguments:a function,andanumber.Thenumberisthemillisecondsthatmustpassbeforethefunctionisran.
Example:
setTimeout(()=>{
//runsafter2seconds
console.log('insidethefunction')
},2000)
57
Thefunctioncontainingthe console.log('insidethefunction') linewillbeexecutedafter2seconds.
If you add a console.log('before') prior to the function, andconsole.log('after')afterit:
console.log('before')
setTimeout(()=>{
//runsafter2seconds
console.log('insidethefunction')
},2000)
console.log('after')
Youwillseethishappeninginyourconsole:
before
after
insidethefunction
Thecallbackfunctionisexecutedasynchronously.
Thisisaverycommonpatternwhenworkingwiththefilesystem,thenetwork,events,ortheDOMinthebrowser.
All of the things I mentioned are not "core" JavaScript, so they are notexplained in this handbook, but you'll find lots of examples in my otherhandbooksavailableathttps://flaviocopes.com.
Here'showwecanimplementcallbacksinourcode.
Wedefineafunctionthatacceptsacallbackparameter,whichisafunction.
Whenthecodeisreadytoinvokethecallback,weinvokeitpassingtheresult:
constdoSomething=callback=>{
//dothings
//dothings
constresult=/*..*/
callback(result)
58
}
Codeusingthisfunctionwoulduseitlikethis:
doSomething(result=>{
console.log(result)
})
59
PromisesPromisesareanalternativewaytodealwithasynchronouscode.
Aswesawinthepreviouschapter,withcallbackswe'dbepassingafunctiontoanother function call, thatwouldbe calledwhen the functionhas finishedprocessing.
Likethis:
doSomething(result=>{
console.log(result)
})
When the doSomething() code ends, it calls the function received as a aparameter:
constdoSomething=callback=>{
//dothings
//dothings
constresult=/*..*/
callback(result)
}
Themainproblemwiththisapproachisthatifweneedtousetheresultofthisfunction in the rest of our code, all our code must be nested inside thecallback,andifwehavetodo2-3callbacksweenterinwhatisusuallydefined"callbackhell"withmanylevelsoffunctionsindentedintootherfunctions:
doSomething(result=>{
doSomethingElse(anotherResult=>{
doSomethingElseAgain(yetAnotherResult=>{
console.log(result)
})
})
})
60
Promisesareonewaytodealwiththis.
Insteadofdoing:
doSomething(result=>{
console.log(result)
})
Wecallapromise-basedfunctioninthisway:
doSomething()
.then(result=>{
console.log(result)
})
Wefirstcallthefunction,thenwehavea then()methodthatiscalledwhenthefunctionends.
Theindentationdoesnotmatter,butyou'lloftenusethisstyleforclarity.
It'scommontodetecterrorsusingacatch()method:
doSomething()
.then(result=>{
console.log(result)
})
.catch(error=>{
console.log(error)
})
Now, to be able to use this syntax, the doSomething() functionimplementationmustbealittlebitspecial.ItmustusethePromisesAPI.
Insteadofdeclaringitasanormalfunction:
constdoSomething=()=>{
}
61
Wedeclareitasapromiseobject:
constdoSomething=newPromise()
andwepassafunctioninthePromiseconstructor:
constdoSomething=newPromise(()=>{
})
This functionreceives2parameters.Thefirst isa functionwecall toresolvethepromise,thesecondafunctionwecalltorejectthepromise.
constdoSomething=newPromise(
(resolve,reject)=>{
})
Resolvingapromisemeanscomplete itsuccessfully (which results incallingthethen()methodinwhousesit).
Rejectingapromisemeansendingitwithanerror(whichresultsincallingthecatch()methodinwhousesit).
Here'show:
constdoSomething=newPromise(
(resolve,reject)=>{
//somecode
constsuccess=/*...*/
if(success){
resolve('ok')
}else{
reject('thiserroroccurred')
}
}
)
62
Wecanpassaparametertotheresolveandrejectfunctions,ofanytypewewant.
63
AsyncandAwaitAsyncfunctionsareahigherlevelabstractionoverpromises.
Anasyncfunctionreturnsapromise,likeinthisexample:
constgetData=()=>{
returnnewPromise((resolve,reject)=>{
setTimeout(()=>
resolve('somedata'),2000)
})
}
Any code that want to use this function will use the async keyword rightbeforethefunction:
constdata=awaitgetData()
anddoingso,anydatareturnedbythepromiseisgoingtobeassignedtothedatavariable.
Inourcase,thedataisthe"somedata"string.
Withoneparticularcaveat:wheneverweusetheawaitkeyword,wemustdosoinsideafunctiondefinedasasync.
Likethis:
constdoSomething=async()=>{
constdata=awaitgetData()
console.log(data)
}
TheAsync/awaitduoallowsus tohaveacleanercodeandasimplementalmodeltoworkwithasynchronouscode.
64
Asyoucanseeintheexampleabove,ourcodelooksverysimple.Compareittocodeusingpromises,orcallbackfunctions.
Andthisisaverysimpleexample,themajorbenefitswillarisewhenthecodeismuchmorecomplex.
Asanexample,here'showyouwouldgetaJSONresourceusing theFetchAPI,andparseit,usingpromises:
constgetFirstUserData=()=>{
//getuserslist
returnfetch('/users.json')
//parseJSON
.then(response=>response.json())
//pickfirstuser
.then(users=>users[0])
//getuserdata
.then(user=>
fetch(`/users/${user.name}`))
//parseJSON
.then(userResponse=>response.json())
}
getFirstUserData()
Andhereisthesamefunctionalityprovidedusingawait/async:
constgetFirstUserData=async()=>{
//getuserslist
constresponse=awaitfetch('/users.json')
//parseJSON
constusers=awaitresponse.json()
//pickfirstuser
constuser=users[0]
//getuserdata
constuserResponse=
awaitfetch(`/users/${user.name}`)
//parseJSON
constuserData=awaituser.json()
returnuserData
}
65
getFirstUserData()
66
VariablesscopeWhenIintroducedvariables,Italkedaboutusingconst,let,andvar.
Scopeisthesetofvariablesthat'svisibletoapartoftheprogram.
InJavaScriptwehaveaglobalscope,blockscopeandfunctionscope.
Ifavariableisdefinedoutsideofafunctionorblock,it'sattachedtotheglobalobjectand ithasaglobalscope,whichmean it'savailable ineverypartofaprogram.
There is a very important difference between var , let and constdeclarations.
Avariabledefinedasvarinsideafunctionisonlyvisibleinsidethatfunction.Similarlytoafunctionarguments:
Avariabledefinedas constor letontheotherhandisonlyvisibleinsidetheblockwhereitisdefined.
Ablockisasetofinstructionsgroupedintoapairofcurlybraces,liketheoneswecanfindinsideanifstatementoraforloop.Andafunction,too.
It'simportanttounderstandthatablockdoesnotdefineanewscopeforvar,butitdoesforletandconst.
Thishasverypracticalimplications.
Supposeyoudefineavarvariableinsideanifconditionalinafunction
functiongetData(){
if(true){
vardata='somedata'
console.log(data)
}
}
Ifyoucallthisfunction,you'llgetsomedataprintedtotheconsole.
67
Ifyoutrytomoveconsole.log(data)aftertheif,itstillworks:
functiongetData(){
if(true){
vardata='somedata'
}
console.log(data)
}
Butifyouswitchvardatatoletdata:
functiongetData(){
if(true){
letdata='somedata'
}
console.log(data)
}
You'llgetanerror:ReferenceError:dataisnotdefined.
This is because var is function scoped, and there's a special thinghappeninghere,calledhoisting.Inshort,thevardeclarationismovedtothetopoftheclosestfunctionbyJavaScript,beforeitrunsthecode.MoreorlessthisiswhatthefunctionlooksliketoJS,internally:
functiongetData(){
vardata
if(true){
data='somedata'
}
console.log(data)
}
This iswhyyoucanalso console.log(data) at the top of a function, evenbeforeit'sdeclared,andyou'llgetundefinedasavalueforthatvariable:
functiongetData(){
console.log(data)
68
if(true){
vardata='somedata'
}
}
but if you switch to let, you'll get an error ReferenceError: data is notdefined,becausehoistingdoesnothappentoletdeclarations.
constfollowsthesamerulesaslet:it'sblockscoped.
Itcanbetrickyatfirst,butonceyourealizethisdifference,thenyou'llseewhyvarisconsideredabadpracticenowadayscomparedto let:theydohavelessmovingparts,and their scope is limited to theblock,whichalsomakesthemverygoodasloopvariables,becausetheyceasetoexistafteraloophasended:
functiondoLoop(){
for(vari=0;i<10;i++){
console.log(i)
}
console.log(i)
}
doLoop()
Whenyouexittheloop,iwillbeavalidvariablewithvalue10.
If you switch to let , if you try to console.log(i) will result in an errorReferenceError:iisnotdefined.
69
ConclusionThanksalotforreadingthisbook.
IhopeitwillinspireyoutoknowmoreaboutJavaScript.
FormoreonJavaScript,checkoutmyblogflaviocopes.com.
Sendanyfeedback,[email protected]
70