bioinformacs resources · bioinfres sose18 ecmascript ecmascript – standardized specificaon,...
TRANSCRIPT
BioinfRes SoSe18
Bioinforma)csResources
Lecture&ExercisesProf.B.Rost,Dr.L.Richter,J.Reeb
Ins)tutfürInforma)kI12
SlidesbyD.Nechaev
BioinfRes SoSe18
Origins
● BrendanEich,Netscape,1995
● LanguagefortheNetscapeNavigatorbrowser
● CalledJavaScriptbecausemarke)ng
● InspiredbyScheme(func)onallanguage)andSelf(prototypes),notbyJava
BioinfRes SoSe18
JScript
● MicrosoQreverseengineeredJavaScript
● CalleditJScriptandaddedtotheInternetExplorerin1996
● JScript&JavaScripthadincompa)bili)es,browserwarstarted
BioinfRes SoSe18
ECMAScript
● ECMAScript–standardizedspecifica)on,1997
● latestedi)on(ECMAScript6)finalizedinJune2015
● ES6iss)llnotcompletelysupportedbythebrowsers
● ThistalkpresentsES5features
BioinfRes SoSe18
LanguagefortheBrowser
● Designedasabrowserlanguagewithnoinput/outputcapabili)es
● Interac)onwiththeenvironment(HTMLpage)● use`script`tagtoaddjsfilestothepage
<script src="filename" type="text/javascript"></script>
BioinfRes SoSe18
Node.js
● Pla^ormforrunningJavaScriptontheserverside(2009)
● U)lizesGoogle’sV8JavaScriptenginetointerpretJavaScriptcode
● AllowstowritebothbackendandfrontendcodeinJavaScript
BioinfRes SoSe18
JavaScript
● Complexapplica)onsstartedbeingdevelopedinthesecondhalfof2000sasWeb2.0emerged
● Currentlyisoneofthemostpopularlanguages
● AllowstocreaterichUserInterfacesfortheWeb(plots,diagrams,classicalUIelements,etc.)
BioinfRes SoSe18
SimpleExecu)onEnvironment
● OneofthesimplestwaystorunJavaScriptcodeistouseChromeGoogleDeveloperTools
● Cmd+Alt+IorCtrl+Alt+I
● Alterna)vely,rightclick,choose`Inspect`,select`Console`tab
BioinfRes SoSe18
Firstlookatvariables
● `var`keywordallowstodeclareandini)alizevariables(severalatonce)
● valididen)fiersbeginwithaleger,`$`,or`_`● othersymbolscanbelegers,digits,`$`,and`_`
< var identifier; < var factory, $obj, _private; < var meaning = 42, level = 9000;
BioinfRes SoSe18
DataTypes
BioinfRes SoSe18
DataTypes
● Primi)ve:- Number- String- Boolean- null- undefined
● Referenced:- Object- Array- Date- Regexp- Func)on
BioinfRes SoSe18
Number,0.1+0.2
● Onlyonetypefornumbers-float● uses8bytesfornumberrepresenta)on
● becarefulwithfinancialdata
< 0.1 + 0.2 === 0.3; > false < 0.1 + 0.2; > 0.30000000000000004
BioinfRes SoSe18
Math.pow
● Standardarithme)calopera)onsandmoduloaredefinedfornumbers
● `Math`objectimplementsmorecomplexmathopera)ons
< 10 % 3; > 1 < Math.pow(2, 10); > 1024
BioinfRes SoSe18
Numberliterals
● Numberswrigeninthesourcecode(asintheexamplesabove),decimalbydefault,hexadecimalbeginwith`0x`
● Floatliteralscontain`.`or`e`
● prefixoperator`-`isusedfornega)venumbers
< 0xF; > 15 < 101e-1; > 10.1 < -10; > -10
BioinfRes SoSe18
SpecialValues
● `Infinity`&`-Infinity`arereturnedinthecaseofoverflow
● NaNisreturnedfortheopera)onswithnodefinedvalue
< -1e1000; > -Infinity < 1 / 0; > NaN
BioinfRes SoSe18
Wrappingobject
● Numbersareaprimi)vetype(byvalue)● `Number`constructorallowstocreatewrappingobjects
< typeof 7; > "number" < typeof new Number(7); > "object" < (new Number(7)).valueOf(); > 7
BioinfRes SoSe18
Strings
● Stringisasequenceof16-bitUnicodesymbols● Nochartype
● Stringliteralbeginsandendswith`'`or`"`(nodifference)
< 'Rostlab\t\n' === "Rostlab\t\n"; > true
BioinfRes SoSe18
ComplexStrings
● Nointerpola)on,concatenatewith+● Breakstringsintomul)plelineswith`\`
< 'Rostlab ' + 2016; > "Rostlab 2016” < 'a\ < b'; > "ab"
BioinfRes SoSe18
Immutability&wrappingobject
● Stringsareaprimi)veimmutabletype
● Methodslike`replace()`and`toLowerCase()`returnanewstring
● `String`constructorallowstocreatewrappingobjects
< typeof new String("Rostlab"); > "object” < (new String("Rostlab")).valueOf(); > "Rostlab"
BioinfRes SoSe18
Boolean
● Booleantypehastwovalues-`true`and`false● Anyexpressionusedinacondi)onalisautoma)callyconvertedtoBoolean
● `null`,`undefined`,0,`NaN`,and`“”`=>`false`
● anythingelse=>`true`
BioinfRes SoSe18
Wrappingobject
● `Boolean`constructorallowstocreatewrappingobjects
● Becareful–wrappingobjectfor`false`isevaluatedastrue!
< if (new Boolean(false)) { console.log("is true"); } > is true
BioinfRes SoSe18
undefined
● Specialtypeundefinedhasonlyonevalue–`undefined`
● unini)alizedvariable,nonexistentarrayelementorobjectproperty
● returnedbyfunc)onswithnoexplicitreturnvalue
● func)onparameterwithnocorrespondingargument
< var x; < x > undefined
BioinfRes SoSe18
undefined
● globalvariable`undefined`returnsvalue`undefined`,whichistheonlyvalueoftype`undefined`
BioinfRes SoSe18
null
● Abitcomplicated
● `null`isakeyword
● `typeof`returns`object`
● However,`null`hasnoproper)esandnomethodsunlikeotherobjects
● nullisasingleinstanceofaspecialtypemeaningnovalue
< typeof null; > "object"
BioinfRes SoSe18
null
● Justafewofinbuiltfunc)onsreturnnull● Thus,itisconsideredagoodprac)cetouse`null insteadof`undefined`inusercodetoindicateabsenceofvalue
BioinfRes SoSe18
Objects
● JSObjectisanassocia)vearray(thinkpythondic)onary),i.e.asetofproper)es,whereeachpropertyisakey-valuepair
● Objectsarestoredbyreference
< var a = { name: 'Rostlab’ }, b = a; < b.name = 'Rostlab 2016'; < a.name; > "Rostlab 2016"
BioinfRes SoSe18
ObjectContents
● Noclasses,sonolimitsonthenamesandvaluesoftheproper)es
● Anobjectcanhavearbitraryproper)es
● Anobject’sproperty’svaluecanbeanotherobject
● Toaccessanobject’spropertyusedotnota)onorsquarebracketnota)on
< var lct = { name: 'Dr. Richter' }; < var cls = { name: 'BioinfRes', lecturer: lct }; < cls.lecturer.name; > "Dr. Richter” < cls['lecturer'].name; > "Dr. Richter” < cls.lecturer['name']; > "Dr. Richter"
BioinfRes SoSe18
Noclasses?
● Yes,noclasses● Prototypalinheritanceisusedforcodereuseandmodelinggroupsofobjectswithsimilarbehavior
● Arrays,func)ons,regularexpressions,anddatesareobjectsandtheygettheirbehaviorviaprototypalinheritance
● We’lllookatitindetailslater
BioinfRes SoSe18
Array
● Anobjectthatstoresanorderedgroupofvalues● Dynamic(canchangesize)anduntyped(canstorevaluesofdifferenttypes)
● othersymbolscanbelegers,digits,`$`,and`_`
< var array = ['Rostlab']; < array.push(2016); < array; > ["Rostlab", 2016]
BioinfRes SoSe18
Anyvalue
● Anarraycanholdanyvalueincludingitself
=^__^=< var array = ['Rostlab']; < array.push(array); < array[1][0]; > "Rostlab"
BioinfRes SoSe18
Date
● Objectscreatedwiththe`Date`constructorhavemethodsforhandlingdatesand)me
< var now = new Date(); < now.getFullYear(); > 2016
BioinfRes SoSe18
Regexps
● Regexpobjectsdescribethestringtemplate
< var regexp = new RegExp('^Rostlab'); < regexp.test('Rostlab 2016'); > true; < regexp.test('2016 Rostlab'); > false
BioinfRes SoSe18
Func)ons
● Func)onsaresocalled‘firstclassci)zens’:
- canstoreinvariables,arrays,objects’proper)es
- canpasstootherfunc)onsasarguments
- canreturnfromotherfunc)ons
● Func)onsaremul)ary(don’tknowwhat`mul)ary`means?Comparewith`unary`,`binary`,etc.;-)
● Ifwedon’tpassanargumentforacertainparameter,itsvalueis`undefined`
● Canaccessallargumentspassedtoafunc)onwiththe`arguments`keyword
BioinfRes SoSe18
Func)ons
● Graspingfunc)onsisessen)alforJavaScript● We’lllookatfunc)onsindetail< function printArgs(a, b, c) { console.log(a); console.log(b); console.log(c); }; < printArgs('Rostlab', 2016); > Rostlab > 2016 > undefined
BioinfRes SoSe18
Summary
● `Boolean`,`Number`,and`String`areprimi)veimmutableobjectsstoredbyvalue
● Wecancreatewrapperobjectsforprimi)vevalues
● That’sexactlywhathappenswhenwecallamethodonaprimi)vevalue–awrapperobjectiscreated,amethodiscalledonthewrapperobject,thenthewrapperobjectisdestroyed
< (2016).toString(); > "2016” < ' Rostlab '.trim(); > "Rostlab"
BioinfRes SoSe18
SummaryPt.2
● `null`&`undefined`aretheonlyvaluesoftheirrespec)vedatatypes
● Nowrapperobjectsforthem
BioinfRes SoSe18
SummaryPt.3
● Objectsarestoredbyreference● Objectsaremutable
BioinfRes SoSe18
Typeconversions
● Func)ons`Number`,`Boolean`,and`String`● Func)ons`parseFloat`and`parseInt`
● Methods`toString`,`toExponen)al`,`toFixed`,and`toPrecision`
< String(2016); > "2016” < Boolean(2016); > true < (123.45).toExponential(); > "1.2345e+2"
BioinfRes SoSe18
Strongtyping
● Somelanguages(e.g.,Python)havestrongtyping● Strongtypingmeanswecan’tmixvaluesofdifferenttypes
>>> 'Rostlab ' + 2016Traceback (most recent call last): File "<stdin>", line 1, in <module>TypeError: cannot concatenate 'str' and 'int' objects
BioinfRes SoSe18
Weaktyping
● JavaScriptisadynamicweaklytypedlanguage● JavaScriptdoesn’tcare!
< 'Rostlab ' + 2016; > "Rostlab 2016"
BioinfRes SoSe18
Weaktyping
● REALLYdoesn’tcare
< '7' * '4'; > 28
BioinfRes SoSe18
Weaktyping
● Please,beverycareful
● Rulesofautoma)ctypecas)ngarecomplex
< '6' - '4'; > 2 < '6' + '4'; > "64"
BioinfRes SoSe18
Doubleequalityoperator
● Doubleequalityoperatorautoma)callydoestypeconversion
● Thatmakesitintransi)ve
< '0' == 0 && 0 == ''; > true < '0' == ''; > false
BioinfRes SoSe18
Tripleequalityoperator
● Tripleequalityoperatorreturns`true`onlyifoperandsbelongtothesamedatatypeandholdthesamevalue
● Itisconsideredagoodprac)cetouse`===`and`!==`operatorsinsteadofdoubleequality
< '0' === 0; > false < 0 === ''; > false
BioinfRes SoSe18
Magicstrings
● Automa)ctypecas)ngisdangerousbutallowstoperformsomefuntricks
< ![]; > false < !![]; > true < +!![]; > 1
< !![] + []; > "true” < (!![]+[])[+![]]; > "t”
BioinfRes SoSe18
Magicstrings
● Automa)ctypecas)ngisdangerousbutallowstoperformsomefuntricks
< +!![]+(+!![])+[]+(+![])+(+!![])+(+!![]+(+!![]))*(+!![]+(+!![])+(+!![]))+([]+{})[+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+!![])[+!+[]]+([]+{})[+!+[]]+([]+![])[+!+[]+!+[]+!+[]]+([]+{})[+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]]+([]+![])[+!+[]+!+[]]+([]+![])[+!+[]]+([]+{})[+!+[]+!+[]];> "2016 rostlab"
BioinfRes SoSe18
ControlStatements
BioinfRes SoSe18
ControlStatements
● `if–else`,`switch`andternaryoperator● `while`and`for`loop
● `break`and`con)nue`instruc)ons
BioinfRes SoSe18
Ifelse
● Canuse`if`againaQer`else`
● Usecurlybracesifwanttoexecutemorethanonestatement
● Itisconsideredagoodprac)cetoalwaysusecurlybraces
< if (hand === 'Rock') { console.log('Rock beats scissors, you win'); } else if (hand === 'Paper') { console.log('Scissors beat paper, you lose'); } else { console.log('Try again'); }
BioinfRes SoSe18
Ternaryoperator
● Ternaryoperatorallowstowritecondi)onalinamorecompactway
● `if–else`condi)onal:ifcondi+ondo1elsedo2
● Ternaryoperator:condi)on?do1:do2
< console.log(grade > 4 ? 'Fail' : 'Pass’)
BioinfRes SoSe18
Ternaryoperator
● Wecanuseternaryoperatorinsideanotherternaryoperator
● Justbecausewecandoesn’tmeanweshould
● Whatisthefollowingcodedoing?
< return (a<b) ? (b<c) ? b : (a<c) ? c : a : (a<c) ? a : (b<c) ? c : b;
BioinfRes SoSe18
Ternaryoperator
● Thefollowingcodereturnsmedianofa,b,andc● Unreadableandunmaintainable
< return (a<b) ? (b<c) ? b : (a<c) ? c : a : (a<c) ? a : (b<c) ? c : b;
BioinfRes SoSe18
Switch
● `switch`allowstochooseoneofmanystatements
● Wecandothesamewithmul)pleif–else,but`switch`allowstowritemorecompactandreadablecode
< switch(month) { case 0: 'Jan'; break; case 1: 'Feb'; break; …
case 11: 'Dec'; break; default: 'Unknown'; break; }
BioinfRes SoSe18
Switch● `switch`comparesvalueofthecondi)onalwiththevalueofeach`case`un)l
`===`operatorreturnstrue
● Onceequalityisfound,respec)vecodeblockisexecuted
● Unlesswe`break`outof`switch`statement,allofthebelowcodeblockswillbeexecutedaswell
● `default`codeblockisexecutedifnoequalityisfound< switch(month) { case 0: 'Jan'; break; case 1: 'Feb'; break; …
case 11: 'Dec'; break; default: 'Unknown'; break; }
BioinfRes SoSe18
Forloop
● JavaScript`for`loopisanalogoustoC`for`loop● for(init;condi)on;post-itera)on-statement)loop-statement
< for (var i = 0; i < 10; i++) console.log(i); > 0 > 1 > … > 9
BioinfRes SoSe18
Cthulhuloop
● Wecaneasilycreateaninfiniteloop(;;)
● Butjustbecausewecandoesn’tmeanweshould
< for (;;) //in the name of Cthulhu console.log('All your CPU are belong to Cthulhu!');
BioinfRes SoSe18
For–inloop
● `for-in`loopiteratesoverobjectproper)es’names
● Togetproperty’svalueusesquarebracketnota)on
< var cls = {name: 'Rostlab', year: '2016', lecturer: 'Dr. Richter'}; < for (var p in cls) { console.log(p + ': ' + cls[p]); }; > name: Rostlab > year: 2016 > lecturer: Dr. Richter
BioinfRes SoSe18
While
● `while`loopexecutesablockcodewhilethecondi)onistrue
● while(condi)on)statement
< var i = 0; < while (i < 10) { console.log(i); i++; }
> 0 > 1 > … > 9
BioinfRes SoSe18
Dowhile
● `do–while`loopexecutesablockcode,thenchecksthecondi)onandstartsanotheritera)onifitistrue
● Willrunatleastonce
< var i = 11; < do { console.log(i); i++; } while (i < 10); > 11
BioinfRes SoSe18
Break,con)nue,label
● `break`abortscurrentloopand`switch`statement
● `con)nue`startsnextloopitera)on
● Wecanuselabelswith`break`and`con)nue`
● LabelslooksuspicioslysimilartoGOTO
● Researchanduseatyourownrisk< outerLoop: while (true) { innerLoop: while(true) { console.log('No more loops'); break outerLoop; }; console.log('You won\'t see me!'); } > No more loops
BioinfRes SoSe18
Logicaloperators
● Wecanuselogicaloperatorsincomplexcondi)ons
● Use`&&`for`AND`,`||`for`OR`,and`!`for`NOT`
< true && false; > false < true || false; > true < !false; > true
BioinfRes SoSe18
Changingpriorityofopera)ons
● Useparenthesistochangepriorityofopera)ons
< 2 + 2 * 2 > 6 < (2 + 2) * 2 > 8
BioinfRes SoSe18
Func)ons
BioinfRes SoSe18
Func)onDeclara)on
● Usekeyword`func)on`followedbyafunc)on’snameandalistofparameters
< function functionName(par1, ..., parN) { statements }
BioinfRes SoSe18
Func)onExpression
● Allowstocreateanonymousfunc)ons● Wecanassigncreatedfunc)ontoavariable
< var varName = function(par1, ..., parN) { statements }
BioinfRes SoSe18
Func)onExpressionwithaName
● Wecanevenuseafunc)onexpressionwithaname
● Insuchcasewewillonlybeabletocallafunc)onbyit’snameinsidethefunc)onitself
< var myFactorial = function factorial(n) { if (n > 0) { return n * factorial(n - 1); } else { return 1; } }; < factorial(3); > Uncaught ReferenceError: factorial is not defined(…) < myFactorial(3); > 6
BioinfRes SoSe18
Declara)onandExpression
● Bothdefinefunc)ons
● Func)ondeclara)onrequiresaname,whilefunc)onexpressionallowsanonymousfunc)ons
● Thankstofunc)ondeclara)onhois)ngwecanusefunc)onsbeforetheyaredeclared,asiffunc)ondeclara)onwasliQedtothetopoftheblock
● Finally,wecan’tdeclarefunc)onsinsideloops,condi)onalsandothercontrolstatements,whilefunc)onexpressionshavenosuchlimits
BioinfRes SoSe18
Func)onDeclara)onHois)ng
< factorial(5); function factorial(n) { result = 1; for (var i = 1; i <= n; i++) { result *= i; } return result; } > 120
BioinfRes SoSe18
WorkingwithArguments
● Func)onhasparametersandtakesarguments
● Wecaninvokeafunc)onwithadifferentamountofargumentsthanparameters
● Parameterswithnocorrespondingargumentwillhavevalue`undefined`
< function myFunc(str1, str2) { console.log(str2); }; myFunc('only one argument!') > undefined
BioinfRes SoSe18
WorkingwithArguments
● Ifthenumberofargumentsislargerthanthenumberofparameters,“excessive”argumentssimplywillnotbeused
● Wes)llcanaccessthemthankstoaspecialvariable`arguments`
● `arguments`objectcontainsalltheargumentspassedtoafunc)on
< function myFunc(str1, str2) { console.log(arguments[3]); }; myFunc('one', 'two', 'three', 'four'); > four
BioinfRes SoSe18
Workingwith`arguments`object
● Although`arguments`objecthas`length`propertyandallowstoaccessitselementsbyindex,itisnotanarrayanddoesnothavearraymethods
< ['one', 'two', 'three', 'four'].indexOf('three'); > 2 < function myFunc(str1) { return arguments.indexOf('three'); } myFunc('one', 'two', 'three', 'four'); > TypeError: arguments.indexOf is not a function
BioinfRes SoSe18
Workingwith`arguments`object
● S)ll,wecanconvert`arguments`objecttoanarrayusing`Array.prototype.slice.call(arguments)`
● We’llinves)gatethiscodeindetailsaliglebitlater,fornowtreatitasasnippet
< ['one', 'two', 'three', 'four'].indexOf('three'); > 2 < function myFunc(str1) { var argumentsArray = Array.prototype.slice.call(arguments); return argumentsArray.indexOf('three'); } myFunc('one', 'two', 'three', 'four'); > 2
BioinfRes SoSe18
Func)onReturnValue
● Func)onalwaysreturnsavalue● Bydefault`undefined`isreturned
● Toreturnadifferentvalueuse`return`keyword
< function square(a) { return Math.pow(a, 2); } square(7); > 49
BioinfRes SoSe18
Automa)cSemicolonInser)on
● RememberaboutASIandputthereturnedvalueonthesamelineas`return`keyword
< function f1() { return { year: 2016 } } < func1() > undefined
< function f2() { return { year: 2016 } } < f2() > Object {year: 2016}
BioinfRes SoSe18
Automa)cSemicolonInser)on
● ThankstotheAutoma)cSemicolonInser)oncodeontheleQisequaltocodeontheright
< function f1() { return { year: 2016 } }
< function f1() { return; //ßALARM { year: 2016 } }
BioinfRes SoSe18
NoBlockScopinginJavaScript
● Insomeotherlanguages,declaringavariableinsideablockcreatesavariableonlyinsidethatblock
● InJavaScriptavariablewillbevisibleoutsidethisblockaswell
< for (var i = 0; i < 3; i++) { console.log(i); }; > 0 1 2 < i > 3 // if you wonder, why it’s 3, study loops again
BioinfRes SoSe18
Func)onsCreateScope
● Func)onsaretheonlywaytocontrolscope● Eachfunc)oncreatesanewscope
● Avariabledeclaredinascopeisaccessibleinsidealloftheinnerscopes
< var name = 'Rostlab'; function printName() { console.log(name); } printName(); > Rostlab
BioinfRes SoSe18
InnerFunc)onsandOuterScope
● Let’ssayitinadifferentway–wecanaccessinsideafunc)onallofthevariablesdeclaredinthisfunc)on’souterscope
● Wecanbothreadandwritesuchvariables
< var name = 'Rostlab'; function rebranding() { name = 'Bioinformatics Chair'; } rebranding(); name > "Bioinformatics Chair"
BioinfRes SoSe18
Variableshadowing
● Declaringavariablewiththesamenameasavariableinanouterscopeblocksaccesstotheoutervariable
< var name = 'Rostlab'; function rebranding() { var name = 'Bioinformatics Chair'; } rebranding(); name > "Rostlab"
BioinfRes SoSe18
Variablehois)ng
● Variabledeclara)onsarehoistedaswellasfunc)ondeclara)ons
● Avariabledeclara)onis‘liQed’tothetopofitsscope
< var name = 'Rostlab'; function rebranding() { name = 'Bioinformatics Chair'; var name; } rebranding(); name > "Rostlab"
BioinfRes SoSe18
IIFE
● ImmediatelyInvokedFunc)onExpressionsallowustopreventloitering
● VariablesdeclaredinsideIIFEareinaccessibleoutside
< (function() { var iDoNotPolluteOuterScope; }()); iDoNotPolluteOuterScope > Uncaught ReferenceError: iDoNotPolluteOuterScope is not defined
BioinfRes SoSe18
Higherorderfunc)ons
● Ahigherorderfunc)ontakesafunc)onasanargumentorreturnsafunc)onasareturnvalue
< function add(x) { return function innerAdd(y) { return x + y; } } add(4)(5) > 9
BioinfRes SoSe18
add(4)(5)
● `add(x)`takesanintegerasanargumentandreturnsanotherfunc)onthattakesanotherintegerasanargument
● `add(4)`returns`innerAdd(y)`andweimmediatelycallitpassing5asanargument
< function add(x) { return function innerAdd(y) { return x + y; } } add(4)(5) > 9
BioinfRes SoSe18
Closures
● Howcan`innerAdd`func)onaccessvariable`x`aQer`add`func)onhasbeeninvoked?
● It’sallabouttheclosures● JavaScriptinnerfunc)onhasanaccesstooutervariablesevenwhenanouterfunc)onhasbeenrun
● Afunc)on“encloses”itsenvironment
● Aclosureisfunc)onplusitscontext
BioinfRes SoSe18
Classicexample–asimplecounter
● IIFE+closure< var counter = (function() { var cntr = 0; return function() { return ++cntr; } }()); counter(); > 1 < counter(); > 2 < counter(); > 3
BioinfRes SoSe18
Objects
BioinfRes SoSe18
Objects–Recap
● Anobjectisanassocia)vearray,i.e.asetofproper)es,ofpairs`name-value`
● Anobjectismutableandispassedbyreference,itcanhavearbitraryproper)eswhosevaluescanbeofanytype,includingfunc)onsandotherobjects
● Arrays,func)ons,regularexpressionsanddatesareobjectsaswell
BioinfRes SoSe18
Crea)nganObject
● `newObject()`createsanewobjectwithnoproper)es
● Havingcreatedanobject,wecanaddproper)esonebyone
< var cls = new Object(); cls.name = 'Bioinformatics Resources'; cls.year = 2016; cls > Object {name: "Bioinformatics Resources", year: 2016}
BioinfRes SoSe18
Objectliteral
● Anobjectliteralallowstocreateanobjectwithitsproper)esfilled
● Anobjectliteralisalistofproper)es(name-valuepairs)incurlybraces
< var cls = { name: 'Bioinformatics Resources', year: 2016, } cls > Object {name: "Bioinformatics Resources", year: 2016}
BioinfRes SoSe18
Propertynames
● WecanusevalidJSiden)fiersaspropertynamesandaccesssuchproper)esviadotnota)on
● Avalididen)fierstartswithaleger,anunderscore(_),oradollarsign($)
● Subsequentcharacterscanbelegers,digits,underscores,ordollarsigns
< var validNames = { valid: 'valid name', $_$: 'valid as well', _$_100500: 'this is valid too', }; validNames._$_100500 > "this is valid too"
BioinfRes SoSe18
Propertynames
● Wecanusestringsthatarenotvalididen)fiersaswell
● Wehavetoquotethemandaccessviasquarebracketnota)on
< var validNames = { '100500': 'this is valid', }; validNames['100500'] > "this is valid"
BioinfRes SoSe18
Propertyvalues
● Apropertyvaluecanbeofanytype
● Func)onsthatareproper)esofanobjectarecalled‘methods’
● Insideofamethod`this`keywordreferstotheobjectthemethodiscalledon
● Wecanuseanystringasaproperty’sname
● Quoteaproperty’snameifit’snotavalididen)fier
< var cls = { name: 'Bioinformatics Resources', year: 2016, print: function() { console.log(this.name + ', ' + this.year); } } cls.print() > Bioinformatics Resources, 2016
BioinfRes SoSe18
Workingwithproper)es
● Wecanread,write,add,anddeleteproper)es
< var cls = { name: 'Bioinformatics Resources', year: 2016, } cls.chair = 'Rostlab'; console.log(cls); > Object {name: "Bioinformatics Resources", year: 2016, chair: "Rostlab"} < delete cls.chair; console.log(cls) > Object {name: "Bioinformatics Resources", year: 2016} < cls.chair > undefined
BioinfRes SoSe18
Itera)ngoverproper)es
● `for-in`loopiteratesoverobjectproper)es’names
● Togetproperty’svalueusesquarebracketnota)on
< var cls = { name: 'Bioinformatics Resources', year: 2016, print: function() { console.log(this.name + ', ' + this.year); } } for (var p in cls) { console.log(p + ': ' + cls[p]); }; > name: Bioinformatics Resources year: 2016 print: function () { console.log(this.name + ', ' + this.year); }
BioinfRes SoSe18
Checkingpropertyexistence
● `hasOwnProperty()`methodallowsustocheckifanobjecthasagivenproperty
< cls.hasOwnProperty('year') > true < cls.hasOwnProperty('month') > false
BioinfRes SoSe18
Comparingobjects
● Anobjectisequalonlytoitself● Inotherwords,equalityoperatorreturns`true`onlyifbothvariablesholdareferencetothesameobject
< lecture = cls; lecture === cls; > true < {name: 'value'} === {name: 'value'} > false
BioinfRes SoSe18
Prototypes
● Bytheway,weneveradded`hasOwnProperty`methodtoourobjects,butwes)llwereabletouseit.Why?
● Becauseprototypes!
< ({}).hasOwnProperty('year'); > false
BioinfRes SoSe18
PrototypalInheritance
● Eachobjecthasaspecialconnec)ontoanotherobject,toaprototype.Whenwetrytoaccessapropertythatisabsentinanobject,weaccessapropertyoftheprototype.Wecansaythatobjectinheritsitsprototypeproper)es.
● `Object.prototype`isaprototypeofallobjectscreatedviaanobjectliteral.`Object.prototype`has`hasOwnProperty`method,andthat’sexactlywhatweinvoked.
BioinfRes SoSe18
PrototypalInheritance
● Ifweaddapropertytoaprototype,alloftheobjectsinheri)ngfromthisprototypewillgetimmediateaccesstothenewproperty
< Object.prototype.easterEgg = 'Hello, world!'; cls.easterEgg > "Hello, world!"
BioinfRes SoSe18
PrototypalInheritance
● Whathappensifweadd`easterEgg`propertytoour`cls`object?
< cls.easterEgg = function() { console.log('Have I messed up my prototype?'); } cls.easterEgg(); > Have I messed up my prototype? < Object.prototype.easterEgg; > "Hello, world!” < ({}).easterEgg; > "Hello, world!"
BioinfRes SoSe18
Func)onsRevisited
BioinfRes SoSe18
Func)onsareObjects
● Afunc)onisanobject
● `name`property’svalueisfunc)on’sname(anemptystringforananonymousfunc)on)
● `length`property’svalueisanamountofparameters
< (function() {}).name > "" < var foo = function bar(a, b, c) {}; foo.name; > "bar” < foo.length; 3
BioinfRes SoSe18
Func)on.prototype
● Func)onobjectisconnectedtoaprototypeaswell
● `Func)on.prototype`istheprototypeoffunc)ons
< Object.getPrototypeOf(foo) === Function.prototype > true
BioinfRes SoSe18
`apply`&`call
● Func)onsinherit`apply`and`call`methods< var print = function() { console.log(this.name + ', ' + this.year); }; var cls = { name: 'Bioinformatics Resources', year: 2016, } print.apply(cls); > Bioinformatics Resources, 2016 < print.call(cls); > Bioinformatics Resources, 2016
BioinfRes SoSe18
`apply`&`call
● `apply`&`call`methodsallowtocallafunc)onasifitwasamethodoftheobjectthatispassedasafirstargument
● `this`keywordreturnspassedobject
< var returnThis = function() { return this; } returnThis.apply(cls) === cls; > true
BioinfRes SoSe18
`apply`&`call
● ArgumentspassedaQertheobjectbecomeargumentsofthefunc)on
● `call`takestheseargumentssimplyasarguments,`apply`takesanarray
< var print = function(times) { for (var i = 0; i < times; i++) { console.log(this.name); } }; print.call(cls, 3); > Bioinformatics Resources Bioinformatics Resources Bioinformatics Resources
BioinfRes SoSe18
Arrayasargumentswith`apply
● Using`apply`wecanunpackarguments,thatis,turnanarrayintoargumentsforafunc)on
● Amnemonicallowstorememberwhichoftwomethodstakesanarray:“apply”and“array”startandendwiththesamelegers
< Math.max(3, 5, 9); > 9 < Math.max([3, 5, 9]); > NaN < Math.max.apply(null, [3, 5, 9]); > 9
BioinfRes SoSe18
ArgumentsArray
● Previouslyshownwayofturning`arguments`objectintoanactualarrayshouldbeclearnow
< Array.prototype.slice.call(arguments);
BioinfRes SoSe18
CallingOneObject’sMethodsonAnotherObject
● Wecaninvokeoneobject’smethodsonanotherobjectusing`apply`and`call`orsimplybyaddingmethodstoanotherobject
< var cls = { name: 'Bioinformatics Resources', year: 2016, print: function() { console.log(this.name + ', ' + this.year); } }; var anotherCls = { name: 'Protein Prediction', year: 2016, }; anotherCls.print = cls.print; anotherCls.print(); > Protein Prediction, 2016
BioinfRes SoSe18
LateBinding
● `this`becomesboundtoanobjectattheinvoca)on)me
● Latebindingallowstouse`apply`&`call`orcopymethodsfromoneobjecttoanother
● Unless…
BioinfRes SoSe18
Func)on.prototype.bind
● `Func)on.prototype.bind`returnsanewfunc)onboundtoaspecifiedobject
● `this`keywordwillalwaysreturnboundobject< var cls = { name: 'Bioinformatics Resources', year: 2016, }; cls.print = (function() { console.log(this.name + ', ' + this.year); }).bind(cls); var anotherCls = { name: 'Protein Prediction', year: 2016, }; anotherCls.print = cls.print; anotherCls.print(); > Bioinformatics Resources, 2016
BioinfRes SoSe18
`this
● Whatwill`this`returnifafunc)onhasn’tbeenboundtoanobjectandisnotinvokedasamethodorvia`apply`or`call`?
● Bydefault`this`returnstheglobalobject
● Inthebrowserit’s`window`object
< function checkThisOut() { console.log(this); }; checkThisOut(); > Window {external: Object, chrome: Object, document: document, GoogleAnalyticsObject: "ga", gaplugins: Object…}
BioinfRes SoSe18
`this
● Inaninnerfunc)on`this`bydefaultreturnstheglobalobject
< var cls = { name: 'Bioinformatics Resources', testInnerFunc: function() { return (function() { console.log(this); }()); } }; cls.testInnerFunc(); > Window {external: Object, chrome: Object, document: document, GoogleAnalyticsObject: "ga", gaplugins: Object…}
BioinfRes SoSe18
`this`andthat
● However,wealreadyknowhowtodealwithit● Wecaneitherbindaninnerfunc)onorcache`this`inanothervariable,forexample`that`
< var cls = { name: 'Bioinformatics Resources', testInnerFunc: function() { var that = this; return (function() { console.log(that); }()); } }; cls.testInnerFunc(); > Object {name: "Bioinformatics Resources"}
BioinfRes SoSe18
ObjectsRevisited
BioinfRes SoSe18
ObjectswithSimilarBehaviour
● Wewanttohaveobjectswithsimilarbehaviour
● Wecanaddexpliciltyaddmethodstoeachobject
● Wecanaddmethodsto`Object.prototype`
● Isthereabegersolu)on?
BioinfRes SoSe18
ConstructorFunc)ons
● Constructorfunc)onsallowtocreateagroupofobjectssuchthateachobjectbelongingtoagrouphassimilarbehaviour
< function Swordsman(name, hp, damage) { this.name = name; this.hp = hp; this.attacks = 2; this.damage = damage; }; var swordsman = new Swordsman('Arthur', 100, 40); swordsman > Swordsman {name: "Arthur", hp: 100, attacks: 2, damage: 40}
BioinfRes SoSe18
ConstructorFunc)ons
● `new`keywordcreatesanewobject
● Valueofthe`prototype`propertyoftheconstructorfunc)onbecomestheprototypeofthenewobject
● `this`returnsthenewobjectinsidetheconstructorfunc)on
< Object.getPrototypeOf(swordsman) === Swordsman.prototype true
BioinfRes SoSe18
ConstructorFunc)ons
● Eachfunc)on,includingconstructorfunc)ons,has`prototype`property
● Valueof`prototype`propertyisanobject
● Thisobjectbecomestheprototypeofeveryobjectcreatedbyacorrespondingconstructorfunc)on
< Swordsman.prototype.getTotalDamage = function() { return this.attacks * this.damage; } swordsman.getTotalDamage() > 80
BioinfRes SoSe18
AddingProper)estoaPrototype
● Wecanaddproper)esofanytypeandnotjustfunc)ons
< Swordsman.prototype.house = 'Lannister'; swordsman.house > "Lannister"
BioinfRes SoSe18
NoAccessControl
● Wenowknowenoughtowriteasimplevideogame
● Inspired,wesatdowntoworkonit
● Andsuddenlywerealizethatalloftheobject’sproper)esarepublic,arevisiblefromtheoutside
● JavaScripthasnowayofdeclaringcertainproper)esasprivateorprotected,theyareallpublic
● Ourswordsman’sdamageandagackstatsareexposedtotheoutsideworld
BioinfRes SoSe18
ClosuresasaSolu)on
● Wecansolvethisproblemwithclosures
< function Swordsman(name, hp, damage) { this.name = name; this.hp = hp; var dmg = damage; var attacks = 2; this.getTotalDamage = function() { return attacks * dmg; }; }; var swordsman = new Swordsman('Arthur', 100, 40); swordsman.getTotalDamage(); > 80 < swordsman.dmg > undefined < swordsman.damage > undefined
BioinfRes SoSe18
ClosuresasaSolu)on
● `dmg`and`agacks`variablesaredefinedintheconstructor
● Thesevariablesareaccessibleinside`getTotalDamage`func)on
● ThankstoclosuresthesevariablesexistevenaQerconstructorinvoca)onhasbeencompleted
● Itisimpossibletoaccessthisvariablesfromtheoutside
● Wecanmakeproper)esandmethods”private”thisway
BioinfRes SoSe18
AccessControlVSPrototypes
● Closuresallowustolimitaccesstocertainproper)es
● Everythinghasaprice,however
● Wecan’taccesssuchproper)esinsidetheprototypemethods
● Thus,wehavetochoosebetweenaccesscontrolwithclosuresandcodereusewithprototypechains
BioinfRes SoSe18
PrototypeChain?
● Yes,achain
● Wecancreateanobjectviaaconstructorfunc)on
● Makethisobjectaprototypeofanotherobject< function Lannister() {}; Lannister.prototype.house = 'Lannister'; function Swordsman() {}; Swordsman.prototype = new Lannister; function Archer() {}; Archer.prototype = Swordsman.prototype; var swordsman = new Swordsman(); swordsman.house > "Lannister”
BioinfRes SoSe18
PrototypalInheritance
● Whenweinvokeaspecificmethodonanobject
● First,JavaScriptlooksforamethodwithagivennameintheobject
● Then,inthatobject’sprototype
● Then,inthatobject’sprototype’sprototype
● …
● Finally,in`Object.prototype`
BioinfRes SoSe18
DangersofConstructors
● Constructorfunc)onisaregularfunc)on(nospecialkeywords,nonamingrestric)ons,etc.),it’seasytomixaconstructorfunc)onandaregularfunc)on
● Error:callingaconstructorfunc)onwithout`new`(`this willnotbeboundtoanewobject)
● Error:callingaregularfunc)onthatexplicitlyreturnsanobjectwith`new`(itwills)llreturnthatobject)
BioinfRes SoSe18
DangersofConstructors
< function Constructor() { this.name = 'Bioinformatics Resources'; }; var cls = Constructor(); cls > undefined < name > "Bioinformatics Resources"
● Error:callingaconstructorfunc)onwithout`new`(`this isboundtotheglobalobject)
BioinfRes SoSe18
DangersofConstructors
< function Constructor() { return { name: 'Bioinformatics Resources’ } }; var cls = new Constructor(); Object.getPrototypeOf(cls) === Constructor.prototype; > false < Object.getPrototypeOf(cls) === Object.prototype; > true
● Error:callingaregularfunc)onthatexplicitlyreturnsanobjectwith`new`(itwills)llreturnthatobject)
BioinfRes SoSe18
WrappingUp
● 5differentwaystocallafunc)onwithrespectto`this`:- Func)oninvoca)on
- Methodinvoca)on
- Constructorinvoca)on
- Indirectinvoca)onwith`apply`and`call`
- Boundinvoca)onwith`bind`
BioinfRes SoSe18
Wrappingup
● 4waystocreateanobject:- Default`Object`constructor
- Objectliteral
- User-definedconstructor
- Closures
BioinfRes SoSe18
ConstructorvsClosure
● Closuresallowtocontrolaccess
● Prototypesallowtoreusecodeanduselessmemorybystoringproper)esandmethodsintheprototype
BioinfRes SoSe18
Object.create
● ES5addedonemorewayofcrea)nganobject
● `Object.create`takes`object1`asanargumentandreturns`object2`whoseprototypeis`object1`
● Allowstocreateobjectswithuser-madeprototypeswithoutcrea)ngconstructors
< var lannister = {name: 'Lannister'}; < var swordsman = Object.create(lannister); < Object.getPrototypeOf(swordsman) === lannister; > true < swordsman.name > "Lannister"
BioinfRes SoSe18
Whybother?
● WhydoweevenbotherwithJavaScript?
● BecauseJavaScriptallowsustoworkwiththeDOM
BioinfRes SoSe18
DocumentObjectModel
● TheDocumentObjectModel(DOM)isacross-pla^ormandlanguage-independentapplica)onprogramminginterfacethattreatsanHTML,XHTML,orXMLdocumentasatreestructurewhereineachnodeisanobjectrepresen)ngapartofthedocument.Theobjectscanbemanipulatedprogramma)callyandanyvisiblechangesoccurringasaresultmaythenbereflectedinthedisplayofthedocument.[1]
[1]Wikipedia,Document_Object_Model.Retrievedfromhgps://en.wikipedia.org/wiki/Document_Object_Model
BioinfRes SoSe18
DocumentObjectModel
BioinfRes SoSe18
TreeStructure
● EachelementisanodeintheDOMtree
● Eachdocumentelementhasanaddress
BioinfRes SoSe18
TraversingtheDOMTree
● `document`istherootelementofthetree
● foreachelement,wecangetit’schildrenwith`childNodes`
< document > #document < document.childNodes > [<!DOCTYPE html>, <html> <head> … </head> <body> … </body> </html> ] < document.childNodes[1].childNodes[2].childNodes[1] > <h1> Bioinformatics Resources </h1>
BioinfRes SoSe18
TraversingtheDOMTree
● foreachelement,wecangetit’sparentwith`parentNode`
< var h1 = document.childNodes[1].childNodes[2].childNodes[1]; h1; > <h1> Bioinformatics Resources </h1> < h1.parentNode; > <body>…</body>
BioinfRes SoSe18
Manipula)ngDOMTree
● Wecanretrieve,change,add,andremoveelements
BioinfRes SoSe18
RetrievingDOMElements
● `getElementByID`returnsanelementwithaspecifiedidor`null`
● Thisistooverboseforsuchafrequentopera)on
● MorecompactwaywithjQuery–`$('#hello')`
< document.getElementById('hello'); > <div id="hello">Hello!</div> < $('#hello') > <div id="hello">Hello!</div>
BioinfRes SoSe18
RetrievingDOMElements
● `getElementsByTagName`returnsanarrayofelementswithaspecifiedtag
● jQueryversion–`$('tag')`
● `getElementsByName`returnsanarrayofelementswithaspecifiedname(namesareusedonformelements)
● jQueryversion–`$([name='name'])`
BioinfRes SoSe18
ChangingDOMElements
● `innerText`propertyallowstochangecontentofanelement
● jQueryversion–`$('selector')`.text('newtext')`
< document.getElementById('hello').innerText = 'Hi there!’ > "Hi there!" < $('#hello').text('Hello!') > [<div id= "hello"> Hello! </div> ]
BioinfRes SoSe18
Crea)ngDOMElements
● Createanelementwith`createElement`andinsertitintotheDOMwith`appendChild`
● jQueryversion–`$('selector').append($('<tag></tag>'));`
< var btn = document.createElement('button'); document.getElementById('main').appendChild(btn); > <button></button> < $('#main').append($('<button></button>')); > <div id="main">…<button></button></div>
BioinfRes SoSe18
RemovingDOMElements
● `removeChild`removesagivenelementfromanelementitiscalledon
● jQueryversion–`$('selector').remove`
< document.getElementById('third').parentNode .removeChild(document.getElementById('third')); > <div id= "third"> 3. </div> < $('#third').remove(); > [<div id= "third"> 3. </div> ]
BioinfRes SoSe18
AspectsofaWebpage
HTML CSS
JavaScript
HTML: Content CSS: Presentation/Layout JavaScript: Behaviour
BioinfRes SoSe18
UsefulLinks
● JavaScript:hgps://www.w3schools.com/js/default.asp
● hgps://wiki.sel�tml.org/wiki/JavaScript/Tutorials
● forD3:hgps://www.dashingd3js.com/table-of-contents