Professional Documents
Culture Documents
Glossary of Modern JavaScript Concepts - Part 1
Glossary of Modern JavaScript Concepts - Part 1
GUIDE
BLOG
programming,andfunctionalreactiveprogramminginJavaScript.
Kim Maida
TL;DR:IntherstpartoftheGlossaryofModernJSConceptsseries,we'llgainanunderstandingoffunctionalprogramming,reactive
programming,andfunctionalreactiveprogramming.Todoso,we'lllearnaboutpurity,statefulnessandstatelessness,immutabilityand
mutability,imperativeanddeclarativeprogramming,higher-orderfunctions,observables,andtheFP,RP,andFRPparadigms.
Introduction
ModernJavaScripthasexperiencedmassiveproliferationoverrecentyearsandshowsnosignsofslowing.Numerousconceptsappearing
inJSblogsanddocumentationarestillunfamiliartomanyfront-enddevelopers.Inthispostseries,we'lllearnintermediateand
advancedconceptsinthecurrentfront-endprogramminglandscapeandexplorehowtheyapplytomodernJavaScript.
Concepts
Inthisarticle,we'lladdressconceptsthatarecrucialtounderstandingfunctionalprogramming,reactiveprogramming,andfunctional
reactiveprogrammingandtheirusewithJavaScript.
Youcanjumpstraightintoeachconcepthere,orcontinuereadingtolearnabouttheminorder.
Purity:PureFunctions,ImpureFunctions,SideEects
State:StatefulandStateless
ImmutabilityandMutability
ImperativeandDeclarativeProgramming
Higher-orderFunctions
FunctionalProgramming
Observables:HotandCold
ReactiveProgramming
FunctionalReactiveProgramming
Pure Functions
Apurefunction'sreturnvalueisdeterminedonlybyitsinputvalues(arguments)withnosideeects.Whengiventhesameargument,
theresultwillalwaysbethesame.Hereisanexample:
functionhalf(x){
returnx/2;
whereverusedinourcodewithnochangetothenaloutcome.isiscalledreferentialtransparency.
Purefunctionsonlydependonwhat'spassedtothem.Forexample,apurefunctioncannotreferencevariablesfromaparentscopeunless
theyareexplicitlypassedintothefunctionasarguments.Eventhen,thefunctioncannotmodifytheparentscope.
varsomeNum=8;
//thisisNOTapurefunction
functionimpureHalf(){
returnsomeNum/2;
Insummary:
Purefunctionsmusttakearguments.
esameinput(arguments)willalwaysproducethesameoutput(return).
Purefunctionsrelyonlyonlocalstateanddonotmutateexternalstate(note: console.log changesglobalstate).
Purefunctionsdonotproducesideeects.
Purefunctionscannotcallimpurefunctions.
Impure Functions
Animpurefunctionmutatesstateoutsideitsscope.Anyfunctionthathassideeects(seebelow)isimpure.Proceduralfunctionswithno
utilizedreturnvaluearealsoimpure.
Considerthefollowingexamples:
//impurefunctionproducingasideeffect
functionshowAlert(){
alert('Thisisasideeffect!');
//impurefunctionmutatingexternalstate
varglobalVal=1;
functionincrementGlobalVal(x){
globalVal+=x;
//impurefunctioncallingpurefunctionsprocedurally
functionproceduralFn(){
constresult1=pureFnFirst(1);
constresult2=pureFnLast(2);
console.log(`Donewith${result1}and${result2}!`);
}
//impurefunctionthatresemblesapurefunction,
//butreturnsdifferentresultsgiventhesameinputs
functiongetRandomRange(min,max){
returnMath.random()*(maxmin)+min;
Whenafunctionorexpressionmodiesstateoutsideitsowncontext,theresultisasideeect.Examplesofsideeectsincludemakinga
calltoanAPI,manipulatingtheDOM,raisinganalertdialog,writingtoadatabase,etc.Ifafunctionproducessideeects,itis
consideredimpure.Functionsthatcausesideeectsarelesspredictableandhardertotestsincetheyresultinchangesoutsidetheirlocal
scope.
Purity Takeaways
Plentyofqualitycodeconsistsofimpurefunctionsthatprocedurallyinvokepurefunctions.isstillproducesadvantagesfortestingand
immutability.Referentialtransparencyalsoenablesmemoization:cachingandstoringfunctioncallresultsandreusingthecachedresults
whenthesameinputsareusedagain.Itcanbeachallengetodeterminewhenfunctionsaretrulypure.
Tolearnmoreaboutpurity,checkoutthefollowingresources:
Pureversusimpurefunctions
MastertheJavaScriptInterview:WhatisaPureFunction?
FunctionalProgramming:PureFunctions
State
Statereferstotheinformationaprogramhasaccesstoandcanoperateonatapointintime.isincludesdatastoredinmemoryaswell
asOSmemory,input/outputports,database,etc.Forexample,thecontentsofvariablesinanapplicationatanygiveninstantare
representativeoftheapplication'sstate.
Stateful
Statefulprograms,apps,orcomponentsstoredatainmemoryaboutthecurrentstate.eycanmodifythestateaswellasaccessits
history.efollowingexampleisstateful:
//stateful
varnumber=1;
functionincrement(){
returnnumber++;
increment();//globalvariablemodified:number=2
Stateless
Statelessfunctionsorcomponentsperformtasksasthoughrunningthemforthersttime,everytime.ismeanstheydonotreference
orutilizeanyinformationfromearlierintheirexecution.Statelessnessenablesreferentialtransparency.Functionsdependonlyontheir
argumentsanddonotaccessorneedknowledgeofanythingoutsidetheirscope.Purefunctionsarestateless.Seethefollowingexample:
//stateless
varnumber=1;
functionincrement(n){
returnn+1;
}
increment(number);//globalvariableNOTmodified:returns2
Statelessapplicationsdostillmanagestate.However,theyreturntheircurrentstatewithoutmutatingpreviousstate.isisatenetof
functionalprogramming.
State Takeaways
Statemanagementisimportantforanycomplexapplication.Statefulfunctionsorcomponentsmodifystateandstorehistory,butare
morediculttotestanddebug.Statelessfunctionsrelyonlyontheirinputstoproduceoutputs.Astatelessprogramreturnsnewstate
ratherthanmodifyingexistingstate.
Tolearnmoreaboutstate,checkoutthefollowingresources:
State
Advantagesofstatelessprogramming
Statefulandstatelesscomponents,themissingmanual
Redux:predictablestatecontainerforJavaScriptapps
econceptsofimmutabilityandmutabilityareslightlymorenebulousinJavaScriptthaninsomeotherprogramminglanguages.
However,youwillhearalotaboutimmutabilitywhenreadingaboutfunctionalprogramminginJS.It'simportanttoknowwhatthese
termsmeanclassicallyandalsohowtheyarereferencedandimplementedinJavaScript.edenitionsaresimpleenough:
Immutable
Ifanobjectisimmutable,itsvaluecannotbemodiedaercreation.
Mutable
Ifanobjectismutable,itsvaluecanbemodiedaercreation.
InJavaScript,stringsandnumberliteralsareimmutablebydesign.isiseasilyunderstandableifweconsiderhowweoperateonthem:
varstr='Hello!';
varanotherStr=str.substring(2);
//result:str='Hello!'(unchanged)
//result:anotherStr='llo!'(newstring)
Numberliteralsareimmutableaswell.efollowingwillalwayshavethesameresult:
varthree=1+2;
//result:three=3
isdemonstratesthatimmutabilitybydesigndoesexistinJavaScript.However,JSdevelopersareawarethatthelanguageallowsmost
thingstobechanged.Forexample,objectsandarraysaremutablebydesign.Considerthefollowing:
vararr=[1,2,3];
arr.push(4);
//result:arr=[1,2,3,4]
varobj={greeting:'Hello'};
obj.name='Jon';
//result:obj={greeting:'Hello',name:'Jon'}
Intheseexamples,theoriginalobjectsaremutated.Newobjectsarenotreturned.
Tolearnmoreaboutmutabilityinotherlanguages,checkoutMutablevsImmutableObjects.
FunctionalprogramminginJavaScripthasgainedalotofmomentum.Butbydesign,JSisaverymutable,multi-paradigmlanguage.
Functionalprogrammingemphasizesimmutability.Otherfunctionallanguageswillraiseerrorswhenadevelopertriestomutatean
immutableobject.SohowcanwereconciletheinnatemutabilityofJSwhenwritingfunctionalorfunctionalreactiveJS?
WhenwetalkaboutfunctionalprogramminginJS,theword"immutable"isusedalot,butit'stheresponsibilityofthedevelopertowrite
theircodewithimmutabilityinmind.Forexample,Reduxreliesonasingle,immutablestatetree.However,JavaScriptitselfiscapableof
mutatingthestateobject.Toimplementanimmutablestatetree,weneedtoreturnanewstateobjecteachtimethestatechanges.
JavaScriptobjectscanalsobefrozenwith Object.freeze(obj) tomakethemimmutable.Notethatthisisshallow,meaningobjectvalues
withinafrozenobjectcanstillbemutated.Tofurtherensureimmutability,functionslikeMozilla'sdeepFreeze()andnpmdeep-freeze
canrecursivelyfreezeobjects.FreezingismostpracticalwhenusedintestsratherthaninapplicationJS.Testswillalertdeveloperswhen
mutationsoccursotheycanbecorrectedoravoidedintheactualbuildwithout Object.freeze clutteringupthecorecode.
erearealsolibrariesavailabletosupportimmutabilityinJS.MorideliverspersistentdatastructuresbasedonClojure.Immutable.jsby
FacebookalsoprovidesimmutablecollectionsforJS.UtilitylibrarieslikeUnderscore.jsandlodashprovidemethodsandmodulesto
promoteamoreimmutablefunctionalprogrammingstyle.
Overall,JavaScriptisaverymutablelanguage.SomestylesofJScodingrelyonthisinnatemutability.However,whenwritingfunctional
JS,implementingimmutabilityrequiresmindfulness.JSwillnotnativelythrowerrorswhenyoumodifysomethingunintentionally.
Testingandlibrariescanassist,butworkingwithimmutabilityinJStakespracticeandmethodology.
Immutabilityhasadvantages.Itresultsincodethatissimplertoreasonabout.Italsoenablespersistency,theabilitytokeepolderversions
ofadatastructureandcopyonlythepartsthathavechanged.
edisadvantageofimmutabilityisthatmanyalgorithmsandoperationscannotbeimplementedeciently.
Tolearnmoreaboutimmutabilityandmutability,checkoutthefollowingresources:
ImmutabilityinJavaScript
ImmutableObjectswithObjectFreeze
MutablevsImmutableObjects
UsingImmutableDataStucturesinJavaScript
GettingStartedwithRedux(includesexamplesforaddressingimmutablestate)
Whilesomelanguagesweredesignedtobeimperative(C,PHP)ordeclarative(SQL,HTML),JavaScript(andotherslikeJavaandC#)
cansupportbothprogrammingparadigms.
MostdevelopersfamiliarwitheventhemostbasicJavaScripthavewrittenimperativecode:instructionsinformingthecomputerhowto
Declarativecodetellsthecomputerwhatyouwanttoachieveratherthanhow,andthecomputertakescareofhowtoachievetheend
resultwithoutexplicitdescriptionfromthedeveloper.Ifyou'veused Array.map ,you'vewrittendeclarativeJS.
Imperative Programming
Imperativeprogrammingdescribeshowaprogram'slogicworksinexplicitcommandswithstatementsthatmodifytheprogramstate.
Considerafunctionthatincrementseverynumberinanarrayofintegers.AnimperativeJavaScriptexampleofthismightbe:
functionincrementArray(arr){
letresultArr=[];
for(leti=0;i<arr.length;i++){
resultArr.push(arr[i]+1);
}
returnresultArr;
isfunctionshowsexactlyhowthefunction'slogicworks:weiterateoverthearrayandexplicitlyincreaseeachnumber,pushingittoa
newarray.Wethenreturntheresultingarray.isisastep-by-stepdescriptionofthefunction'slogic.
Declarative Programming
Declarativeprogrammingdescribeswhataprogram'slogicaccomplisheswithoutdescribinghow.
SELECT*FROMPeopleWHERELastName='Smith'
iscodeiseasytoreadanddescribeswhatwewanttoaccomplish.ereisnodescriptionofhowtheresultshouldbeachieved.e
computertakescareofthat.
functionincrementArray(arr){
returnarr.map(item=>item+1);
showinghowitcreatesthenewarray.
Note:JavaScript's map , reduce ,and filter aredeclarative,functionalarraymethods.Utilitylibrarieslikelodash
providemethodslike takeWhile , uniq , zip ,andmoreinadditionto map , reduce ,and filter .
Asalanguage,JavaScriptallowsbothimperativeanddeclarativeprogrammingparadigms.MuchoftheJScodewereadandwriteis
imperative.However,withtheriseoffunctionalprogramminginJS,declarativeapproachesarebecomingmorecommon.
Declarativeprogramminghasobviousadvantageswithregardtobrevityandreadability,butatthesametimeitcanfeelmagical.Many
JavaScriptbeginnerscanbenetfromgainingexperiencewritingimperativeJSbeforedivingtoodeepintodeclarativeprogramming.
Tolearnmoreaboutimperativeanddeclarativeprogramming,checkoutthefollowingresources:
ImperativevsDeclarativeProgramming
What'stheDierenceBetweenImperative,Procedural,andStructuredProgramming?
Imperativeand(Functional)DeclarativeJSInPractice
JavaScript'sMap,Reduce,andFilter
Higher-order Functions
Ahigher-orderfunctionisafunctionthat:
acceptsanotherfunctionasanargument,or
returnsafunctionasaresult.
InJavaScript,functionsarerst-classobjects.eycanbestoredandpassedaroundasvalues:wecanassignafunctiontoavariableor
passafunctiontoanotherfunction.
constdouble=function(x){
returnx*2;
}
consttimesTwo=double;
timesTwo(4);//result:returns8
Oneexampleoftakingafunctionasanargumentisacallback.Callbackscanbeinlineanonymousfunctionsornamedfunctions:
constmyBtn=document.getElementById('myButton');
//anonymouscallbackfunction
myBtn.addEventListener('click',function(e){console.log(`Clickevent:${e}`);});
//namedcallbackfunction
functionbtnHandler(e){
console.log(`Clickevent:${e}`);
}
myBtn.addEventListener('click',btnHandler);
Wecanalsopassafunctionasanargumenttoanyotherfunctionwecreateandthenexecutethatargument:
functionsayHi(){
alert('Hi!');
}
functiongreet(greeting){
greeting();
}
greet(sayHi);//alerts"Hi!"
Note:Whenpassinganamedfunctionasanargument,asinthetwoexamplesabove,wedon'tuseparentheses () .is
waywe'repassingthefunctionasanobject.Parenthesesexecutethefunctionandpasstheresultinsteadofthefunction
itself.
Higher-orderfunctionscanalsoreturnanotherfunction:
functionwhenMeetingJohn(){
returnfunction(){
alert('Hi!');
}
}
varatLunchToday=whenMeetingJohn();
atLunchToday();//alerts"Hi!"
Tolearnmoreabouthigher-orderfunctions,checkoutthefollowingresources:
FunctionsarerstclassobjectsinJavaScript
Higher-OrderFunctionsinJavaScript
Higher-orderfunctions-Part1ofFunctionalProgramminginJavaScript
EloquentJavaScript-Higher-orderFunctions
HigherOrderFunctions
Functional Programming
Nowwe'velearnedaboutpurity,statelessness,immutability,declarativeprogramming,andhigher-orderfunctions.eseareallconcepts
thatareimportantinunderstandingthefunctionalprogrammingparadigm.
Functionalprogrammingencompassestheaboveconceptsinthefollowingways:
Corefunctionalityisimplementedusingpurefunctionswithoutsideeects.
Dataisimmutable.
Functionalprogramsarestateless.
Imperativecontainercodemanagessideeectsandexecutesdeclarative,purecorecode.*
*IfwetriedtowriteaJavaScriptwebapplicationcomposedofnothingbutpurefunctionswithnosideeects,it
couldn'tinteractwithitsenvironmentandthereforewouldn'tbeparticularlyuseful.
Let'sexploreanexample.Saywehavesometextcopyandwewanttogetitswordcount.Wealsowanttondkeywordsthatarelonger
thanvecharacters.Usingfunctionalprogramming,ourresultingcodemightlooksomethinglikethis:
constfpCopy=`Functionalprogrammingispowerfulandenjoyabletowrite.It'sverycool!`;
//removepunctuationfromstring
conststripPunctuation=(str)=>
str.replace(/[.,\/#!$%\^&\*;:{}=\_`~()]/g,'');
//splitpassedstringonspacestocreateanarray
constgetArr=(str)=>
str.split('');
//countitemsinthepassedarray
constgetWordCount=(arr)=>
arr.length;
//finditemsinthepassedarraylongerthan5characters
//makeitemslowercase
constgetKeywords=(arr)=>
arr
.filter(item=>item.length>5)
.map(item=>item.toLowerCase());
//processcopytoprepthestring,createanarray,countwords,andgetkeywords
functionprocessCopy(str,prepFn,arrFn,countFn,kwFn){
constcopyArray=arrFn(prepFn(str));
console.log(`Wordcount:${countFn(copyArray)}`);
console.log(`Keywords:${kwFn(copyArray)}`);
processCopy(fpCopy,stripPunctuation,getArr,getWordCount,getKeywords);
//result:Wordcount:11
//result:Keywords:functional,programming,powerful,enjoyable
iscodeisavailabletorunatthisJSFiddle:FunctionalProgrammingwithJavaScript.It'sbrokenintodigestible,declarativefunctions
withclearpurpose.Ifwestepthroughitandreadthecomments,nofurtherexplanationofthecodeshouldbenecessary.Eachcore
functionismodularandreliesonlyonitsinputs(pure).elastfunctionprocessesthecoretogeneratethecollectiveoutputs.is
thatacceptstheotherfunctionsasargumentstomaintainthefunctionalstyle.
Immutabledataandstatelessnessmeanthattheprogram'sexistingstateisnotmodied.Instead,newvaluesarereturned.Purefunctions
areusedforcorefunctionality.Inordertoimplementtheprogramandhandlenecessarysideeects,impurefunctionscancallpure
functionsimperatively.
Tolearnmoreaboutfunctionalprogramming,checkoutthefollowingresources:
IntroductiontoImmutable.jsandFunctionalProgrammingConcepts
FunctionalProgrammingForeRestofUs
FunctionalProgrammingwithJavaScript
Don'tbeScaredofFunctionalProgramming
SoYouWanttobeaFunctionalProgrammer
lodash-FunctionalProgrammingGuide
Whatisthedierencebetweenfunctionalandimperativeprogramminglanguages?
EloquentJavaScript,1stEdition-FunctionalProgramming
FunctionalProgrammingbyExample
FunctionalProgramminginJavaScript-VideoSeries
IntroductiontoFunctionalJavaScript
Howtoperformsideeectsinpurefunctionalprogramming
PreventingSideEectsinJavaScript
Observables
Observablesaresimilartoarrays,exceptinsteadofbeingstoredinmemory,itemsarriveasynchronouslyovertime(alsocalledstreams).
Wecansubscribetoobservablesandreacttoeventsemittedbythem.JavaScriptobservablesareanimplementationoftheobserver
pattern.ReactiveExtensions(commonlyknownasRx*)providesanobservableslibraryforJSviaRxJS.
Todemonstratetheconceptofobservables,let'sconsiderasimpleexample:resizingthebrowserwindow.It'seasytounderstand
observablesinthiscontext.Resizingthebrowserwindowemitsastreamofeventsoveraperiodoftimeasthewindowisdraggedtoits
desiredsize.Wecancreateanobservableandsubscribetoittoreacttothestreamofresizeevents:
//createwindowresizestream
//throttleresizeevents
constresize$=
Rx.Observable
.fromEvent(window,'resize')
.throttleTime(350);
//subscribetotheresize$observable
//logwindowwidthxheight
constsubscription=
resize$.subscribe((event)=>{
lett=event.target;
console.log(`${t.innerWidth}pxx${t.innerHeight}px`);
});
eexamplecodeaboveshowsthatasthewindowsizechanges,wecanthrottletheobservablestreamandsubscribetothechangesto
respondtonewvaluesinthecollection.isisanexampleofahotobservable.
Hot Observables
Userinterfaceeventslikebuttonclicks,mousemovement,etc.arehot.Hotobservableswillalwayspushevenifwe'renotspecically
subscription exists.
Cold Observables
Acoldobservablebeginspushingonlywhenwesubscribetoit.Ifwesubscribeagain,itwillstartover.
Let'screateanobservablecollectionofnumbersrangingfrom 1 to 5 :
//createsourcenumberstream
constsource$=Rx.Observable.range(1,5);
//subscribetosource$observable
constsubscription=source$.subscribe(
(value)=>{console.log(`Next:${value}`);},//onNext
(event)=>{console.log(`Error:${event}`);},//onError
()=>{console.log('Completed!');}//onCompleted
);
doesn'tpushunlesswesubscribetoit.
Observables Takeaways
Observablesarestreams.Wecanobserveanystream:fromresizeeventstoexistingarraystoAPIresponses.Wecancreateobservables
fromalmostanything.Apromiseisanobservablewithasingleemittedvalue,butobservablescanreturnmanyvaluesovertime.
Wecanoperateonobservablesinmanyways.RxJSutilizesnumerousoperatormethods.Observablesareoenvisualizedusingpointson
aline,asdemonstratedontheRxMarblessite.Sincethestreamconsistsofasynchronouseventsovertime,it'seasytoconceptualizethisin
alinearfashionandusesuchvisualizationstounderstandRx*operators.Forexample,thefollowingRxMarblesimageillustratesthelter
operator:
Tolearnmoreaboutobservables,checkoutthefollowingresources:
ReactiveExtensions:Observable
CreatingandSubscribingtoSimpleObservableSequences
eintroductiontoReactiveProgrammingyou'vebeenmissing:RequestandResponse
IntroducingtheObservable
RxMarbles
RxBook-Observable
IntroducingtheObservable
Reactive Programming
Reactiveprogrammingisconcernedwithpropagatingandrespondingtoincomingeventsovertime,declaratively(describingwhattodo
ratherthanhow).
ReactiveprogrammingisoenassociatedwithReactiveExtensions,anAPIforasynchronousprogrammingwithobservablestreams.
ReactiveExtensions(abbreviatedRx*)provideslibrariesforavarietyoflanguages,includingJavaScript(RxJS).
Hereisanexampleofreactiveprogrammingwithobservables.Let'ssaywehaveaninputwheretheusercanenterasix-character
conrmationcodeandwewanttoprintoutthelatestvalidcodeattempt.OurHTMLmightlooklikethis:
<!HTML>
<inputid="confirmationcode"type="text">
<p>
<strong>Validcodeattempt:</strong>
<codeid="attemptedcode"></code>
</p>
We'lluseRxJSandcreateastreamofinputeventstoimplementourfunctionality,likeso:
//JS
constconfCodeInput=document.getElementById('confirmationcode');
constattemptedCode=document.getElementById('attemptedcode');
constconfCodes$=
Rx.Observable
.fromEvent(confCodeInput,'input')
.map(e=>e.target.value)
.filter(code=>code.length===6);
constsubscription=confCodes$.subscribe(
(value)=>attemptedCode.innerText=value,
(event)=>{console.warn(`Error:${event}`);},
()=>{console.info('Completed!');}
);
validconrmationcodeattempt.Notethatthiswasdoneinresponsetoeventsovertime,declaratively:thisisthecruxofreactive
programming.
ereactiveprogrammingparadigminvolvesobservingandreactingtoeventsinasynchronousdatastreams.RxJSisusedinAngular
andisgainingpopularityasaJavaScriptsolutionforreactiveprogramming.
Tolearnmoreaboutreactiveprogramming,checkoutthefollowingresources:
eintroductiontoReactiveProgrammingyou'vebeenmissing
IntroductiontoRx
eReactiveManifesto
UnderstandingReactiveProgrammingandRxJS
ReactiveProgramming
ModernizationofReactivity
Reactive-ExtensionsRxJSAPICore
Insimpleterms,functionalreactiveprogrammingcouldbesummarizedasdeclarativelyrespondingtoeventsorbehaviorsovertime.To
understandthetenetsofFRPinmoredepth,let'stakealookatFRP'sformulation.enwe'llexamineitsuseinrelationtoJavaScript.
AmorecompletedenitionfromConalElliot,FRP'sformulator,wouldbethatfunctionalreactiveprogrammingis"denotativeand
temporallycontinuous".Elliotmentionsthathepreferstodescribethisprogrammingparadigmasdenotativecontinuous-time
programmingasopposedto"functionalreactiveprogramming".
Functionalreactiveprogramming,atitsmostbasic,originaldenition,hastwofundamentalproperties:
denotative:themeaningofeachfunctionortypeisprecise,simple,andimplementation-independent("functional"referencesthis)
continuoustime:variableshaveaparticularvalueforaveryshorttime:betweenanytwopointsareaninnitenumberofother
points;providestransformationexibility,eciency,modularity,andaccuracy("reactive"referencesthis)
Again,whenweputitsimply:functionalreactiveprogrammingisprogrammingdeclarativelywithtime-varyingvalues.
Tounderstandcontinuoustime/temporalcontinuity,considerananalogyusingvectorgraphics.Vectorgraphicshaveaninnite
resolution.Unlikebitmapgraphics(discreteresolution),vectorgraphicsscaleindenitely.eyneverpixellateorbecomeindistinctwhen
particularlylargeorsmallthewaybitmapgraphicsdo.
"FRPexpressionsdescribeentireevolutionsofvaluesovertime,representingtheseevolutionsdirectlyasrst-class
values."
ConalElliot
Functionalreactiveprogrammingshouldbe:
dynamic:canreactovertimeortoinputchanges
time-varying:reactivebehaviorscanchangecontinuallywhilereactivevalueschangediscretely
ecient:minimizeamountofprocessingnecessarywheninputschange
historicallyaware:purefunctionsmapstatefromapreviouspointintimetothenextpointintime;statechangesconcernthelocal
elementandnottheglobalprogramstate
ConalElliot'sslidesontheEssenceandOriginsofFRPcanbeviewedhere.eprogramminglanguageHaskelllendsitselftotrueFRP
duetoitsfunctional,pure,andlazynature.EvanCzaplicki,thecreatorofElm,givesagreatoverviewofFRPinhistalkControllingTime
andSpace:UnderstandingtheManyFormulationsofFRP.
Infact,let'stalkbrieyaboutEvanCzapliki'sElm.Elmisafunctional,typedlanguageforbuildingwebapplications.Itcompilesto
JavaScript,CSS,andHTML.eElmArchitecturewastheinspirationfortheReduxstatecontainerforJSapps.Elmwasoriginally
consideredatruefunctionalreactiveprogramminglanguage,butasofversion0.17,itimplementedsubscriptionsinsteadofsignalsinthe
interestofmakingthelanguageeasiertolearnanduse.Indoingso,ElmbidfarewelltoFRP.
etraditionaldenitionofFRPcanbediculttograsp,especiallyfordeveloperswhodon'thaveexperiencewithlanguageslikeHaskell
orElm.However,thetermhascomeupmorefrequentlyinthefront-endecosystem,solet'sshedsomelightonitsapplicationin
JavaScript.
InordertoreconcilewhatyoumayhavereadaboutFRPinJS,it'simportanttounderstandthatRx*,Bacon.js,Angular,andothersare
notconsistentwiththetwoprimaryfundamentalsofConalElliot'sdenitionofFRP.ElliotstatesthatRx*andBacon.jsarenotFRP.
Instead,theyare"compositionaleventsystemsinspiredbyFRP".
Functionalreactiveprogramming,asitrelatesspecicallytoJavaScriptimplementations,referstoprogramminginafunctionalstylewhile
creatingandreactingtostreams.isisfairlyfarfromElliot'soriginalformulation(whichspecicallyexcludesstreamsasacomponent),
butisneverthelessinspiredbytraditionalFRP.
It'salsocrucialtounderstandthatJavaScriptinherentlyinteractswiththeuserandUI,theDOM,andoenabackend.Sideeectsand
imperativecodeareparforthecourse,evenwhentakingafunctionalorfunctionalreactiveapproach.Withoutimperativeorimpure
code,aJSwebapplicationwithaUIwouldn'tbemuchusebecauseitcouldn'tinteractwithitsenvironment.
Let'stakealookatanexampletodemonstratethebasicprinciplesofFRP-inspiredJavaScript.issampleusesRxJSandprintsoutmouse
movementsoveraperiodoftenseconds:
//createatimeobservablethataddsanitemevery1second
//mapsoresultingstreamcontainseventvalues
consttime$=
Rx.Observable
.timer(0,1000)
.timeInterval()
.map(e=>e.value);
//createamousemovementobservable
//throttletoevery350ms
//mapsoresultingstreampushesobjectswithxandycoordinates
constmove$=
Rx.Observable
.fromEvent(document,'mousemove')
.throttleTime(350)
.map(e=>{return{x:e.clientX,y:e.clientY}});
//mergetime+mousemovementstreams
//completeafter10seconds
constsource$=
Rx.Observable
.merge(time$,move$)
.takeUntil(Rx.Observable.timer(10000));
//subscribetomergedsource$observable
//ifvalueisanumber,createTimeset()
//ifvalueisacoordinatesobject,addPoint()
constsubscription=
source$.subscribe(
//onNext
(x)=>{
if(typeofx==='number'){
createTimeset(x);
}else{
addPoint(x);
}
},
//onError
(err)=>{console.warn('Error:',err);},
//onCompleted
()=>{console.info('Completed');}
);
//addelementtoDOMtolistoutpointstouchedinaparticularsecond
functioncreateTimeset(n){
constelem=document.createElement('div');
constnum=n+1;
elem.id='t'+num;
elem.innerHTML=`<strong>${num}</strong>:`;
document.body.appendChild(elem);
}
//addpointstouchedtolatesttimeinstream
functionaddPoint(pointObj){
//addpointtolastappendedelement
constnumberElem=document.getElementsByTagName('body')[0].lastChild;
numberElem.innerHTML+=`(${pointObj.x},${pointObj.y})`;
}
YoucancheckoutthiscodeinactioninthisJSFiddle:FRP-inspiredJavaScript.Runtheddleandmoveyourmouseovertheresultarea
ofthescreenasitcountsupto10seconds.Youshouldseemousecoordinatesappearalongwiththecounter.isindicateswhereyour
mousewasduringeach1-secondtimeinterval.
Let'sbrieydiscussthisimplementationstep-by-step.
completesaertenseconds( 10000ms ).
DOM.
coordinateswithitscorrespondingtimeinterval.Wecannowreadwherethemousehasbeenovertime.
Note:esefunctionsareimpure:theyhavenoreturnvalueandtheyalsoproducesideeects.esideeectsare
DOMmanipulations.Asmentionedearlier,theJavaScriptweneedtowriteforourappsfrequentlyinteractswithscope
outsideitsfunctions.
FRPencodesactionsthatreacttoeventsusingpurefunctionsthatmapstatefromapreviouspointintimetothenextpointintime.FRP
inJavaScriptdoesn'tadheretothetwoprimaryfundamentalsofConalElliot'sFRP,butthereiscertainlyvalueinabstractionsofthe
originalconcept.JavaScriptreliesheavilyonsideeectsandimperativeprogramming,butwecancertainlytakeadvantageofthepower
ofFRPconceptstoimproveourJS.
Finally,considerthisquotefromthersteditionofEloquentJavaScript(thesecondeditionisavailablehere):
"Fu-Tzuhadwrittenasmallprogramthatwasfullofglobalstateanddubiousshortcuts.Readingit,astudentasked'You
warnedusagainstthesetechniques,yetIndtheminyourprogram.Howcanthisbe?'
Fu-Tzusaid'ereisnoneedtofetchawaterhosewhenthehouseisnotonre.'{isisnottobereadasan
encouragementofsloppyprogramming,butratherasawarningagainstneuroticadherencetorulesofthumb.}"
MarijnHaverbeke,EloquentJavaScript,1stEdition,Chapter6
Tolearnmoreaboutfunctionalreactiveprogramming(FRP),checkoutthefollowingresources:
FunctionalReactiveProgrammingforBeginners
eFunctionalReactiveMisconception
WhatisFunctionalReactiveProgramming?
Haskell-FunctionalReactiveProgramming
ComposingReactiveAnimations
Specicationforafunctionalreactiveprogramminglanguage
AmoreelegantspecicationforFRP
FunctionalReactiveProgrammingforBeginners
Elm-AFarewelltoFRP
Earlyinspirationsandnewdirectionsinfunctionalreactiveprogramming
BreakingDownFRP
Rx*isnotFRP
Conclusion
We'llconcludewithanotherexcellentquotefromthersteditionofEloquentJavaScript:
"Astudenthadbeensittingmotionlessbehindhiscomputerforhours,frowningdarkly.Hewastryingtowritea
beautifulsolutiontoadicultproblem,butcouldnotndtherightapproach.Fu-Tzuhithimonthebackofhishead
andshouted'Typesomething!'estudentstartedwritinganuglysolution.Aerhehadnished,hesuddenly
understoodthebeautifulsolution."
MarijnHaverbeke,EloquentJavaScript,1stEdition,Chapter6
econceptsnecessaryforunderstandingfunctionalprogramming,reactiveprogramming,andfunctionalreactiveprogrammingcanbe
diculttograsp,letalonemaster.Writingcodethattakesadvantageofaparadigm'sfundamentalsistheinitialstep,evenifitisn't
entirelyfaithfulatrst.Practiceilluminatesthepathaheadandalsorevealspotentialrevisions.
Withthisglossaryasastartingpoint,youcanbegintakingadvantageoftheseconceptsandprogrammingparadigmstoincreaseyour
JavaScriptexpertise.Ifanythingisstillunclearregardingthesetopics,pleaseconsultthelinksineachsectionforadditionalresources.