ECMAScriptJussiPohjolainen
1
RecommendedReading
• Recommendedreading• JavaScript:TheGoodPartsbyDouglasCrockford• JavaScript:TheDefiniteGuidebyDavidFlanagan• JavaScriptPatterns:Stoyan Stefanov
• AndGoogle..
2
JavaScripttoday
• EcmaScript isstandardizedsubsetofJavaScript• JavaScriptiskeylanguagetoimplementwebapplications• Possiblecandidateforcross-platformmobiledevelopment
• React,Cordova/Phonegap,Ionic• Serversidedevelopment• Replacing/ComplementingXMLfordatatransfer(REST+JSON)
3
RiseoftheResponsiveSinglePageApp
Image:http://johnpolacek.github.io/scrolldeck.js/decks/responsive/4
Responsive
• Unifiedacrossexperiences• Canbeembeddedasmobileapp• Betterdeploymentand&maintanence• Mobileusersneedtogetaccesstoeverything
Image:http://coenraets.org/blog/wp-content/uploads/2011/10/directory11.png 5
Single-pageApplications(SPA)
• Webappthatfitsonasinglewebpage• FluidUX,likedesktopapp• ExampleslikeGmail,Googlemaps
• Htmlpagecontainsmini-views (HTMLFragments) thatcanbeloadedinthebackground• Noreloadingofthepage,betterUX• Requireshandlingofbrowserhistory,navigationandbookmarks
6
RiseoftheRESTandJSON
• RESTisaonewayofcommunicatingbetweencomputersovertheinternet• DatacanbesendviaXMLorJSONusingHTTP• HTTPGET
• http://something/employee/1• Result
• {id: 1, name: "jack"}• IfbothfrontendandbackendisJS,objectsendingandparsingextremelyeasy
7
RiseoftheJSBackend:NodeJS
• OpensourceJSruntimeenvironment• UsesV8(Chrome)JSengine
• AdditionalmodulesontopofJStoprovidefunctionality• Webserver,systemi/o,networking,...
• Lotofthirdpartymodulesavailable
8
Native iOS App
iOS WebView
index.htmlapp.js
angularjs.jsionic.jscordova.js
stylesheet.css
Native Android App
Android WebView
index.htmlapp.js
angularjs.jsionic.jscordova.js
stylesheet.css
UsingCordovait'spossibletoaccessmobiledevicenativefeatures
WebServerNode.js+Express+Mongo
app.jspackage.json
modules/express/modules/mongodb/
MongoDB
[{name: 'jack'}, {name: 'tina'}, {..}, {..}]
HTTP GET (ajax) Request: http://server.com/employees/1
HTTP Responsecontent-type: application/json {name: 'jack'}
FrontendIonic+Cordova+AngularJS
BackendNode.JS+Express+Mongo
HTTP POST Request: http://server.com/employees/{name: 'amanda'}
HTTP Responsecontent-type: text/plainhttp://server.com/employees/3
CommunicationRESTandJSON
9
Frontend
10
JavaScript,LiveScript,JScript,ECMAScript?
• JavaScript• DevelopedbyNetscape• OriginallyJavaScript,thenLiveScriptandthenbacktoJavaScript.
• JScript• MicrosoftmadetheirownversionoftheJavaScript
• Leadtocompatibilityproblems• =>ECMAScript,efforttostandardizedifferentversionsoftheJ(ava)Script
11
ECMAScript
• ECMAScript isascriptinglanguage,standardizedbyEcmaInternational• InBrowsers,ECMAScript iscommonlycalledJavaScript
• JavaScript=Native(EcmaScript)+Hostobjects(browser)
• Java/ECMAscript isnowdays heavilyusedwhencreatingweb/mobileandevenDesktop- apps
12
LearningPathforFront-end
CoreEcmaScript
BrowserHostObjectsJavaScriptinFront-end
HTML5
CSSStatic
Web-pages
JavaScriptFrameworks:React,AngularJS,...
13
EcmaScriptVersions
Year Edition Naming
1997 1 ..
1998 2 ..
1999 3 Regex,betterstringhandling,try/catch,...
Abandoned 4 ..
2009 5 strictmode,gettersandsetters,JSON..
2015 6 ES2015 classes, modules,arrowfunctions,collections...
2016 7 ES2016 Math.pow =>**,array.prototype.includes
2017 8 ES2017 await/async
14
FromJScripttoTypeScript
• TypeScript isasuperset ofEcmaScriptdevelopedbyMicrosoft• Ithastypes!
• WhenEcmaScript6th Editionwasworkingprogress,typescriptgavealreadyclasses,modules,arrowfunctionsyntax.• Nowthatthe6th Ed.isreadytheadditionalbenefitusingTypeScriptistypes(andotherslikeinterfaces,generics...)• TypeScriptiscompiledtoEcmaScriptusingcompiler• It'sfirstclasslanguageinMicrosoftVisualStudioandinframeworkslikeAngular2.0
15
typescript.ts
> cat typescript.ts
var variable : string = "typescript";
console.log(variable);
> tsc typescript.ts
> cat typescript.js
var variable = "typescript";
console.log(variable);
Noticethatcompilercompilestypescripttojavascriptanditlosesthestringtypebecausethatisnotpartofjs!
16
BenefitofusingCompiler
> cat typescript.ts
var variable : string = "typescript";
variable = 8;
console.log(variable);
> tsc typescript.ts
typescript.ts(2,1): error TS2322: Type 'number' is not assignable to type 'string'.
17
ToolsforLearningEcmaScript
18
ChooseaCode-Editor/IDE
• AtombyGitHub• Customizablefreeeditor• Built-inpackagemanagerforinstallingnewpackages• Worksacrossoperatingsystems:OSX,LinuxorWindows
• VisualStudioCodebyMicrosoft• InadditiontoAtom...• Hasbuilt-insupport forJavaScript,TypeScriptandNode.js• Alsoextensiblebyplug-ins• GoesbeyondsyntaxhighlightingandprovidesautocompletewithIntelliSenseanddebugger
• WebStormbyJetBrains• FullIDE• Supportfor:Angular,React,Ionic,Cordova,ReactNative,Electron,Node.js..• Debugger,Unittesting
19
ChooseRuntimeEnvironment
• Forgetthebrowserfornow!• EcmaScriptisastandardandtherearemultipleimplementationsforruntimeenvironment;JavaScriptEngines• Canbetraditionalinterpreterorutilizejust-intimecompilationtobytecode
• Differentenginesavailable• V8byGoogle,powersChrome• NitrobyApple,powersSafari• ChakrabyMicrosoft,powersEdge• SpiderMonkey by MozillaFoundation,powersFirefox
• Rhino(JavaImplementation)managedbyMozillaFoundation• ...
20
RuntimeEnvironment:Node.js
• EasiestwaytouseV8JSEngineistoinstallNode.js• https://nodejs.org/en/
• Node.jsisbuiltontopofV8 andis"the"technologytousewhencreatingbackendapplicationusingJS• Alsoprovidespackageecosystem,npm(nodepackagemanager),thatcanbeusedtomanagejs-libraries
• npmisheavilyusedwhencreatingJavaScriptappstoday
• Node.js supportforES2015is99%->GoodJSenvironmentforlearningEcmaScript• http://node.green/
21
HelloWorld
22
23
24
VisualStudioCode- tips
• InstallCodeRunner- extensionforeasierrunningofnode(andother)apps• Debugging Nodeappsissupportedbydefault!• InstallNode.jsextensionpack
• ESLint• npm• JavaScriptSnippets• ...
25
Lab
26
npmpackagemanager
• Node.jscontainsanpm thatcanbeusedtoinstallvariousextensionsandpackages• Youcaninstallpackages
• local(specifictoyourapp)• ./node_modules
• global(canbeusedeverywhere)• /usr/local/lib/node_modules
• Whencreatinganodeproject,usuallyyouwillhaveafilepackage.jsondescribingtheprojectandit'sdependencies
27
Packages
28
Tryingtousepackage
29
npm init
Createspackage.json
withinformationaboutourproject
30
npm install project-name-generator --save
Now dirfordownloadedpackages
31
catpackage.json
package.jsonisupdated
32
cdnode_modules
Theproject-name-generatordependsonotherpackagewhichisdownloadedalso!
33
catproject-name-generator/package.json
34
nodemyapp.js
35
ESLint
• ESLintislintingutility(codequality)toolforJavaScript• Toinstall
• npm install --save-dev eslint• ESLintrequiresaconfigurationfile• Tocreateone,use
• ./node_modules/eslint/bin/eslint.js --init• Youcananswertoquestionsaboutstyleguideortakepopularstyleguides
36
AnsweringtoStyleGuideQuestions
37
RunningESLint
Addno-console:offtoinitfile
38
module.exports = {"env": {
"es6": true,"node": true
},"extends": "eslint:recommended","parserOptions": {
"sourceType": "module"},"rules": {
"no-console": "off","indent": [
"error",4
],"linebreak-style": [
"error","unix"
],"quotes": [
"error","double"
],"semi": [
"error","always"
]}
};
Addno-console:offtoinitfile
Lotofruleshttps://eslint.org/docs/rules/
39
VSCodehasalsoESLintpluginfor
integratinglintingincodeeditor
40
DifferentStyleGuides
• AirBnb• Google• "Standard"Style• Crockford'sCodingStandardsforJavaScript• NodeJSStyleGuide
41
HolyWaraboutStyles:Indentation
https://hackernoon.com/what-javascript-code-style-is-the-most-popular-5a3f5bec1f6f 42
HolyWaraboutStyles:Linttool?
https://hackernoon.com/what-javascript-code-style-is-the-most-popular-5a3f5bec1f6f 43
ESLint:ChoosingStyleGuide
44
StandardRules
• 2spacesforindentation• Singlequotesforstring• Nounusedvariables• Nosemicolons• ...• https://standardjs.com/
45
Lab
46
QuickintrotoECMAScript
47
References
• EcmaScript5.1LanguageSpesification• http://www.ecma-international.org/ecma-262/5.1/
• EcmaScript6LanguageSpesification(June2015)• http://www.ecma-international.org/ecma-262/6.0/index.html
• ReallygoodJavaScriptReferencefromMozilla• https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference
• W3SchoolshavelotofJSstufftoobutremember• http://meta.stackoverflow.com/questions/280478/why-not-w3schools-com
48
GrammarandTypes
49
ECMAScriptBasics
• BorrowsmostofthesyntaxfromJavabutinfluencesfromotherlanguagesalso• JavaandJavaScriptaretotallydifferentasatechnology!
• ECMAScriptiscase-sensitive• Instructionsarecalledstatements andareseparatedtypically usingsemicolon (;)• StandardJavaScriptLinteravoidssemicolonusage
50
Aboutsemicolons
• Youcanwrite• console.log("hello");• console.log("world");
• Or• console.log("hello")• console.log("world")
51
Comments
//Oneline
/*multi-line*/
/*Nonested/*comments*/allowed*/
52
Variables
• Todeclareavariableusekeywordvarorlet• var x = 99;
• Variablenaminghassomerules• muststartwithaletter,underscore(_),dollarsign
• A-Zisdifferentfroma-z(casesensitive)• Afterthefirstletter,digitscanbeused(0-9)
53
VariableScope
• Globalvariable• Declarevariableoutsideoffunction,availableeverywhere
• Localvariable• Declarevariableinsideoffunction,availableinthatfunction
• BeforeES2015,noblockstatement!
54
var globalVariable = 1;
function doIt() {
var functionVariable = 4;
if(true) {
var anotherFunctionVariable = 5;
}
console.log(functionVariable); // 4
console.log(anotherFunctionVariable); // 5
}
if(true) {
var anotherGlobalVariable = 3;
}
console.log(globalVariable); // 1
console.log(anotherGlobalVariable); // 3
doIt(); // 4
// 5
Itisglobal!
Functionscope!
55
VariableHoisting
Thiscodeisthesame...var globalVariable = "Hello";
function doIt() {
console.log(globalVariable);
if(true) {
var globalVariable = "World";
}
}
doIt();
console.log(globalVariable);
...thanthisvar globalVariable = "Hello";
function doIt() {
var globalVariable;
console.log(globalVariable);
if(true) {
globalVariable = "World";
}
}
doIt();
console.log(globalVariable);
Itishoisted!
56
VariableHoisting
function doIt() {
console.log(myVar); // undefined
if(true) {
var myVar = "Hello World";
}
}
doIt();
57
ES2015VariableHoisting:let
function doIt() {
console.log(myVar); // myVar is not defined!
if(true) {
let myVar = "Hello World";
}
}
doIt();
Itisnothoisted!
58
WordAboutES2015
• WhendevelopingtobackendusingNode.jsdevelopercanchoosetheversionofNode.jsandusefreelymostofES2015features• Onthefront-endthingsgetcomplicatedsinceusermayhavewhateverbrowser andthosemaynotsupportES2015• ES2015canbecompiledtoolderES!
59
ES2015:const
• Constantcannotbechangedthroughassignment• constvariablesarenothoisted
const PI = 3.14;
PI = 99;
console.log(PI);
60
ES2015->ES5
Object.defineProperty(typeof global === "object" ? global: window, "PI", {
value: 3.141593,
enumerable: true,
writable: false,
configurable: false
})
console.log(PI);
61
DataTypes:Primitivetypes(6)
Type Possiblevalues
boolean true orfalsenull null
undefined undefined
number 41, 3.444
string "Hello World"
symbol uniqueandimmutableinstances(ES2015)
Allotherareobjects!
62
var booleanValue = true;
var stringValue = "some text";
var undefinedValue;
var numberValue = 4;
var nullValue = null;
// boolean
console.log(typeof booleanValue)
// string
console.log(typeof stringValue)
// undefined
console.log(typeof undefinedValue)
// number
console.log(typeof numberValue)
// object
console.log(typeof nullValue)
// false
console.log(null instanceof Object)
Languagedesignerror!
63
PrimitivetypesvsObjecttypes
• Let'slookatobjectslateronmorecarefully• ObjectinESisjustavariablecontainingproperties:
• var myObject = {"name": "Jack"};• console.log(myObject.name);
• Objectsarepassedbyreference• Primitivetypesarepassedbyvalue
64
String
• Stringliteralcontainscharactersenclosedby""or''var x = "Hello World";
• InES2015alsopossibilitytousetemplateliterals:`var mystring = `Lorem ipsum dolor sit amet,
consectetur adipiscing elit. Integer quis ante at
urna commodo dapibus. Aenean blandit, neque eget pellentesque
viverra, arcu nulla volutpat justo, ut congue est odio id justo.`
• ThereisstringprimitivetypeandStringobject!• ESwillmakeautomaticcastingbetweenthesetwo,soitispossibletoaccessallthemethodsprovidedbytheString:• console.log( x.charAt(0) );
65
DataTypeConversion
5 + null // returns 5 because null is converted to 0
"5" + null // returns "5null" because null is converted to "null"
"5" + 1 // returns "51" because 1 is converted to "1"
"5" - 1 // returns 4 because "5" is converted to 5
66
AboutNumbers
• Number(value),convertsentirestring• var i = Number("12");
• parseInt(value[, radix]), convertsstartofthestring• var i = parseInt("12px”, 10);• Radix?
• 10=>integernumber,8=>octalnumber,16=>hexadecimal
• NaN (Not a Number),checkusingisNaN(variable)• Resultoferroneousoperations
67
IndexedCollection:Arrays
• Arraysareobjectsbutinadditiontheyhavemoremethodsandauto-incrementkey-values• var stuff = ["a", "b", "c"]
• Thekeysarenow0,1and2• Thelengthofthearrayis3andit'slinkedtonumericalproperties
68
Input&Output– Depends!
• InBrowsers• Input:HTMLFormsorwindow.prompt("", "");• Output:DOMmanipulation,document.write("") orwindow.alert("");
• InV8/NodeJSorRhino/Spidermonkey• OutputtoCLI:print("..");• InputfromCLI:Isnotthateasy...
• Debugging• console.log("");
69
Lab
70
ControlFlow,LoopsandIteration
71
ConditionalStatements
if (condition_1) {
statement_1;
} else if (condition_2) {
statement_2;
} else if (condition_n) {
statement_n;
} else {
statement_last;
}
72
FalseValues
let array = [false, undefined, null, 0, NaN, ""];
for(let i=0; i<array.length; i++) {
if(array[i]) {
console.log("true");
} else {
console.log("false");
}
}
73
Comparison:trueorfalse?
let x = new Boolean(false);
if(x) {
console.log("true");
} else {
console.log("false");
}
74
Comparison:trueorfalse?
let x = new Boolean(false);
if(x == false) {
console.log("true");
} else {
console.log("false");
}
75
Equality
• Strictequality• ===
• Looseequality• ==
• ES2015• Object.is
76
77
Testing
console.log(Object.is(0, -0)); // false
console.log(0 === -0); // true
console.log(Object.is(-0, -0)); // true
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
78
Testing:NaN// cast String -> Number
let variable = Number("hello world");
if(variable == NaN) { // false
console.log("0) It was not a number")
}
if(variable === NaN) { // false
console.log("1) It was not a number")
}
if(Object.is(variable, NaN)) { // true
console.log("2) It was not a number");
}
if(isNaN(variable)) { // true
console.log("3) It was not a number");
}
79
switchcase
switch (expression) {
case label_1:
statements_1
[break;]
case label_2:
statements_2
[break;]
...
default:
statements_def
[break;]
}
80
while
let i=0;
while(i < 10) {
console.log(i);
i = i + 1;
}
81
do-while
let i=0;
do {
console.log(i);
i = i + 1;
} while(i < 10);
82
for
for(let i = 0; i < 10; i = i + 1) {
console.log(i);
}
83
for...of– forarrays
let array = ["jack", "tina"];
// Traditional forfor(let i = 0; i < array.length; i++) {
console.log(array[i]);}
// for - offor(let item of array) {
console.log(item);}
84
for...of– forarrays
let array = ["jack", "tina"];
// 0 => "jack", 1 => "tina", "key" => "value"
array["key"] = "value";
// for - of
for(let item of array) {
console.log(item); // ??
}
85
for...in– forobjects
let array = ["jack", "tina"];
// 0 => "jack", 1 => "tina", "key" => "value"
array["key"] = "value";
// for - in
for(let item in array) {
console.log(item); // ??
}
86
for...in– forobjects
let object = {"key1": "value1", "key2": "value2"};
for(let key in object) {
console.log(key);
console.log(object[key])
}
87
NumbersandText
88
Aboutnumbers
• Allnumbersaredouble-precision64-bit• Largestsafeinteger:9007199254740991
• Safe?Youcandocalculationsanddisplaynumberscorrectly
• Nospecifictypeforintegers• Alsosymbolicvalues
• +Infinity, -Infinity, NaN
let largeNumber = Math.pow(2, 53) - 1;
console.log(largeNumber == Number.MAX_SAFE_INTEGER); // true
console.log(largeNumber + 1 == largeNumber + 2); // true
89
Number// Largest integer valueconsole.log(Number.MAX_SAFE_INTEGER);
// Largest floating point valueconsole.log(Number.MAX_VALUE);
// Smallest floating point valueconsole.log(Number.MIN_VALUE);
// Same valuesconsole.log(Number.POSITIVE_INFINITY) console.log(+Infinity);console.log(Infinity);
// Same valuesconsole.log(Number.NEGATIVE_INFINITY)console.log(-Infinity);
// Same valuesconsole.log(Number.NaN);console.log(NaN);
90
Number
Number.parseFloat(..)
Number.parseInt(..)
Number.isFinite(..)
Number.isInteger(..)
Number.isNaN(..)
Number.isSafeInteger(..)
91
Math
Math.PI
Math.abs(..)
Math.min(..)
Math.max(..)
Math.random()
Math.round(..)
Math.sqrt(..)
...
92
Stringobjects
• EcmaScripthasStringprimitivetypeandobject• Primitivetypeiscastedtoobjectwhenneeded
• Useprimitivetype!
• Stringobjecthasvarietymethodsthatyoucanuse
let s = new String('foo');
console.log(s); // [String: 'foo']
console.log(typeof s); // object
93
SomeStringmethods
• charAt• startsWith• endsWith• split• slice• substring• match• replace
• toLowerCase• toUpperCase• trim
94
Date,TimeandNumberformatting
• Intlnamespacehaslanguagesensitivedate,timeandnumberformatting• Forformattingdatesandtime
• Intl.DateTimeFormat• Forformattingnumbers
• Intl.NumberFormat• NotethatNode.jsisbundledonlywithEnglish!
var date = new Date();
var dateTimeFormatter = newIntl.DateTimeFormat('fi-FI');
console.log(dateTimeFormatter.format(date));
95
Lab
96
IndexedCollectionsArrays...
97
CreatinganArray
// These all are equal...
let arr1 = new Array("hello", "world");
let arr2 = Array("hello", "world");
// But this is usually preferred:
let arr3 = ["hello", "world"];
98
CreatinganArraywithgivensize
const ARRAY_LENGTH = 10;
let arr1 = new Array(ARRAY_LENGTH);
// OR
let arr2 = [];
arr2.length = ARRAY_LENGTH;
99
var stuff = ["a", "b", "c"]
console.log(stuff[0]); // a
console.log(stuff[1]); // b
console.log(stuff[2]); // c
console.log(stuff.length); // 3
// Array's length and numerical properties are connected
stuff.push("d")
console.log(stuff.length); // 4
stuff["key"] = "value";
console.log(stuff); // [ 'a', 'b', 'c', 'd', key: 'value' ]
console.log(stuff.length); // 4!
delete stuff["key"];
console.log(stuff); // [ 'a', 'b', 'c', 'd' ]
stuff[4] = "e";
console.log(stuff); // [ 'a', 'b', 'c', 'd', 'e' ]
console.log(stuff.length); // 5
stuff = ["a", "b", "c"];
stuff[9] = "e";
console.log(stuff); // [ 'a', 'b', 'c', , , , , , , 'e' ]
console.log(stuff.length); // 10
100
.length
• lengthwillreturnlastelementindex+1• Itispossibletochangelengthatruntime• Ifgivingshorterlength,thearrayistruncated(removesitems)
101
IteratingoverArrays
1. Traditionalfor2. for of
3. forEach
4. for in (DON'T)
102
forEach(EcmaScript5th Edition)
let colors = ['red', 'green', 'blue'];
colors.forEach(function(color) {
console.log(color);
});
103
ArrayMethods
• concat()• join()• push()• pop()• shift()• unshift()• slice()• splice()
• reverse()• sort()• indexOf()• forEach()• map()• filter()• every()• some()• reduce()
104
everyandsome- example
let arr = ["apple", "banana", "carrot", "apple"];
// Checks all the values, if one of them does not// match with given condition, return value is false.let returnValue1 = arr.every(function (value, index, array) {
return value.length > 1; }
); console.log(returnValue1); // true
// Checks all the values, if one of them matches with// given condition, return value is true.let returnValue2 = arr.some(function (value, index, array) {
return value === "apple"; }
);
console.log(returnValue2); // true
105
KeyedCollections:MapandSet
106
Map
• Mapobjectisasimplekey/valuemapcollection• Youcaniterateitemsininsertionorder• Keyscanbewhatevervalue• Sizeiseasilyavailable
107
Examplevar animals = new Map();
animals.set('dog', 'woof');
animals.set('cat', 'meow');
console.log(animals.size); // 2
animals.delete('dog');
console.log(animals.has('dog')) // false
for (var [key, value] of animals) {
console.log(key + ' goes ' + value);
}
animals.clear();
console.log(animals.size);
108
Set
• Uniquevalues• Insertionorderisprovided
var mySet = new Set();
mySet.add(1);
mySet.add(1);
mySet.add(2);
// 1 2
for (let item of mySet) {
console.log(item);
}
// casting
let array = Array.from(mySet);
console.log(array);
109
Lab
110
Functions
111
Functions
• FundamentalbuildingblockinEcmaScript• Setofstatementsthatperformsataskorcalculatesavalue• Functionsareobjects!
112
SimpleFunction
function doIt() {
console.log("Hello World");
}
doIt();
113
PassingArgument
function doIt(value) {
console.log(value);
}
doIt("Hello World");
114
Passingargumentsandreturningvalue
function doIt(a, b) {
return a + b;
}
console.log( doIt(5,5) );
115
PredefinedArgument
function multiply(a, b = 1) {
return a * b;
}
console.log(multiply(5));
116
Functionsareobjects
function doIt1(a, b) {
return a + b;
}
console.log( doIt1(5,5) );
// The same than
var doIt2 = new Function("a","b", "return a+b;");
console.log ( doIt2(5,5) );
117
Andbecausetheyareobjects...
let functionObject = new Function("a","b", "return a+b;");
let anotherObject = functionObject;
console.log ( functionObject(5,5) );
console.log ( anotherObject(5,5) );
118
PassingFunctionObjects
function divide(a, b, success, error) {if(b === 0) {
error("Cannot divide with zero");} else {
let result = a / b;success(result);
}}
function onSuccess(result) {console.log(result);
}
function onError(message) {console.log(message);
}
divide(5, 0, onSuccess, onError);
119
arguments
function doIt() {
for(let item of arguments) {
console.log(item)
}
}
doIt("a");
doIt("a", "b");
doIt("a", "b", "c");
Predefinedpropertyoffunctions.Youcanfetchallthe
argumentsfromthearray
120
FunctionScoping:Works!
greeting("hello world");
function greeting(msg) {
console.log(msg);
}
121
FunctionScoping:DoesnotWork!
greeting("hello world");
var greeting = function (msg) {
console.log(msg);
}
variablegreetingishoistedandthe
valueisundefined
122
AnonymousFunction
greeting("hello world");
var greeting = function (msg) {
console.log(msg);
}
Anonymousfunction
declaration
123
Rememberthis?
function divide(a, b, success, error) {if(b === 0) {
error("Cannot divide with zero");} else {
let result = a / b;success(result);
}}
function onSuccess(result) {console.log(result);
}
function onError(message) {console.log(message);
}
divide(5, 0, onSuccess, onError);
124
Rememberthis?
function divide(a, b, success, error) {if(b === 0) {
error("Cannot divide with zero");} else {
let result = a / b;success(result);
}}
function onSuccess(result) {console.log(result);
}
function onError(message) {console.log(message);
}
divide(5, 0, onSuccess, onError);
Insteadofpassingnamedfunctionswecoulduseanonymous
functions
125
Anonymousfunctions
function divide(a, b, success, error) {
if(b === 0) {
error("Cannot divide with zero");
} else {
let result = a / b;
success(result);
}
}
divide(5, 0, function(result) {
console.log(result);
}, function(message) {
console.log(message);
});
Passinganonymousfunctions
126
Pattern:AvoidGlobals
(function() {
var thisIsNotGlobalVariable = "hello";
console.log(thisIsNotGlobalVariable);
})()
127
ES2015:ArrowSyntax
function divide(a, b, success, error) {
if(b === 0) {
error("Cannot divide with zero");
} else {
let result = a / b;
success(result);
}
}
divide(5, 0, result => console.log(result),
message => console.log(message));
Passinganonymousfunctionsusingthearrowsyntax:simplersyntaxandlexicalthis
- keyword
128
Lab
129
FunctionthatreturnsaFunction
function doIt() {function hello() {
console.log("Hello World");}
return hello;}
var func = doIt();func();
130
function doIt(condition) {
let myFunc;
if(condition) {
myFunc = function() {
console.log("Hello");
}
} else {
myFunc = function() {
console.log("World");
}
}
return myFunc;
}
doIt(true)();
doIt(false)();
131
Closures
function outer() {let x = 20;function inner() {
console.log(x);
}return inner;
}
var innerFunction = outer();// is x still in memory?innerFunction();
Yes!Whenreturninginnerfunctionthatusesouterfunctionsvariables,thosevariablesarestoredin
memory.
132
Pattern:Privatemembervariables
function createObject() {let privateName = "Jack";let object = {
getName: function() {return privateName;
},setName: function(name) {
privateName = name;}
}return object;
}
var person = createObject();console.log(person.getName());person.setName("Tina");console.log(person.getName());
133
Lab
134
Objects
135
Objects
• Objectiscollectionofproperties• propertyisaassociationbetweenkeyandvalue• valuecanbeforexampleafunction->alsocalledmethod
• Objects,likefunctionsareafundamentalpartofEcmaScript• Thekeysmustbestring,ifnumbersused,itwillmakeatypecast
• Sokeyscanbewhateveriftheycanbeconvertedintoastring
136
ObjectCreation
• Objectinitializer• let o = {};
• UsingObjectconstructor• let o = new Object();
• UsingCustomconstructor• let o = new Car();
• Object.create (usedininheritance)• let dog = Object.create(animal);
137
ObjectInitializer
// Object initializer syntax {}
let object = { key: "value",
"hello": "world",
2: "another" };
console.log(object.key);
console.log(object["key"]);
console.log(object.hello);
console.log(object["2"]);
Alsopossibletoaccessusing[]syntax
Insomecases[]syntaxismandatory..ifkeyisnot
avalidjsidentifier138
ObjectConstructor
let object = new Object();
object.key = "value";
object.hello = "world";
object["2"] = "another";
Possibilitytoaddpropertiesinruntime
139
Dynamickey
let random = Math.random() * 100;
let object = {};
object.mykey = "value1"; // {mykey: "value1"}
object.random = "value2"; // {mykey: "value1", random: "value2"}
object[random] = "value3"; // {mykey: "value1", random: "value2", 46.123: "value3"}
Mustusebracketsfordynamickey!
140
EcmaScript5:Preventextensions,Seal,Freeze
Add Delete Modify
Object.preventExtensions NO YES YES
Object.seal NO NO YES
Object.freeze NO NO NO
141
PreventExtensions
var obj1 = {id: 1};
Object.preventExtensions(obj1);
obj1.name = "Jack";
obj1.id = 3;
delete obj1["id"]; Failssilentlyunlessinstrictmode
142
Seal
var obj = {id: 1};
Object.seal(obj);
obj2.name = "Jussi";
obj2.id = 4;
delete obj2["id"];
143
Freeze
var obj = {id: 1};
Object.freeze(obj);
obj.name = "Jussi";
obj.id = 4;
delete obj["id"];
144
EcmaScript5:Object.defineProperty
var obj = {};
Object.defineProperty( obj, "name", {
value: "something", // Notice: you cannot have value and get + set
get: someFunction,
set: someOtherFunction,
writable: false, // property cannot be changed
enumerable: true, // will be iterated in for in
configurable: true // can be deleted
});
console.log( obj.name );
145
Examplevar obj = {};
Object.defineProperty( obj, "name", {
value: "jeppe",
writable: false, // property cannot be changed
enumerable: false, // will NOT be iterated in for in
configurable: true // can be deleted
});
obj.name = "tina";
console.log(obj.name);
for(var key in obj) {
console.log(key);
}
Cannotchange
Nothinginhere146
ConstructorFunction
function Person(name) {
this.name = name;
}
var tina = new Person("Tina");
console.log(tina.name);
Writethefunctionnamewithcapital(convention)
Usenew– keywordtocreateobject
this referstotina
147
Whathappenshere?
function Person(name) {
this.name = name;
}
var tina = Person("Tina");
console.log(name)
Forgottousethenewword!
148
Pattern:Preventingmisuse
function Person(name) {
if(!(this instanceof Person)) {
throw new TypeError("Cannot call a constructor function without new.");
}
this.name = name;
}
var tina = Person("Tina");
Typecheckingofthis
ifnewismissing,throwerror
149
EcmaScript2015:Class
class Circle {constructor (radius) {
this.radius = radius;}
getArea() {return Math.PI * this.radius * this.radius;
}}
var c = new Circle(5);console.log(c.getArea());
150
EcmaScript2015:Class
class Circle {constructor (radius) {
this.radius = radius;}
getArea() {return Math.PI * this.radius * this.radius;
}}
var c = new Circle(5);
console.log(c.getArea());
Hasprebuiltsupportforcheckingifnewkeywordis
usedornot.Ifnewkeywordismissing,this
willfail!
151
Valuecanbeanything,likefunctions
let MyMath = {abs: function (value) {
if (value < 0) {return value * -1;
} else {return value;
}}
};
console.log ( MyMath.abs(-7) );
152
UsageofArrowFunctionandTernaryOperationlet MyMath = {
abs: (value) => value < 0 ? value * -1 : value
};
console.log ( MyMath.abs(-7) );
153
Enumerating:for...in
var object = {key1: "value1", key2: "value2"};
for (var key in object) {
console.log(key + " = " + object[key]);
}
154
Lab
155
Keywordthis
156
Keywordthis
• Node.jsisalittlebitdifferenttoEcmaScriptwhenitcomestothekeywordthis• Whenusingthisinbrowsers,youwilldifferentresultsthaninNode• OnemajordifferenceisthatNodeusesmoduleswhereonefileisonescope. Inbrowsers,thereisonescope• Fornowlet'sseehowkeywordthis behavesinbrowsers
157
Keywordthis inbrowsers
console.log(this === window);
console.log(doIt() == window);
function doIt() {
return this;
}
Botharetrue
Infunctionsandinglobal,thisreferstoaglobalmainobjectwhichiswindow
158
GlobalvariablesinBrowsers
this.variable = "Hello";console.log(window.variable);
doIt();console.log(window.name);console.log(name);
function doIt() {this.name = "Jack";
}
Youdonothavetowritethemainobject!It'sglobalvariable!
159
Bindingandkeywordthis
160
Thisshouldwork...
function Circle(radius) {this.radius = radius;this.getArea = function() {
return Math.PI * this.radius * this.radius;}
} var c = new Circle(5);console.log(c.getArea());
Wheninvokingthemethod,keywordthis is"replaced"withc - object
161
Wehaveaproblem
function Circle(radius) {this.radius = radius;this.getArea = function() {
return Math.PI * this.radius * this.radius;}
}
var c = new Circle(5);var theFunctionObject = c.getArea;console.log(theFunctionObject());
NothisdoesNOTrefertoc– anymore...itwillnot
work
162
Function:bind
function Circle(radius) {
this.radius = radius;
this.getArea = function() {
return Math.PI * this.radius * this.radius;
} } var c = new Circle(5);
var theFunctionObject = c.getArea;
var newBindedFunctionObject = theFunctionObject.bind(c);
console.log(newBindedFunctionObject());
Createcopyofthatfunctionwherethisrefers
toc
163
Example
var obj = {url: "./test.html",fetchUrl: function() {
fetchIt(this.url, whenReady);}
};
function whenReady(content) {console.log("Fetched from " + this.url);console.log("With content of " + content);
}
function fetchIt(myurl, onSuccess) {// Fetching from myurl the content, when ready invoke// the onSuccessonSuccess("<html>...</html>");
}
obj.fetchUrl();
this?NOTworking!
164
Thesamebutnowusingofanonymousfunctionsvar obj = {
url: "./test.html",fetchUrl: function() {
fetchIt(this.url, function(content) {console.log("Fetched from " + this.url);console.log("With content of " + content);
});}
};
function fetchIt(myurl, onSuccess) {// Fetching from myurl the content, when ready invoke// the onSuccessonSuccess("<html>...</html>");
}
obj.fetchUrl();
this?NOTworking!
165
Binding
var obj = {url: "./test.html",fetchUrl: function() {
fetchIt(this.url, (function(content) {console.log("Fetched from " + this.url);console.log("With content of " + content);
}).bind(this));}
};
function fetchIt(myurl, onSuccess) {// Fetching from myurl the content, when ready invoke// the onSuccessonSuccess("<html>...</html>");
}
obj.fetchUrl();
Sendacopyofthatfunction!
166
Pattern:UsingClosure
var obj = {url: "./test.html",fetchUrl: function() {
var _this = this;fetchIt(this.url, function(content) {
console.log("Fetched from " + _this.url);console.log("With content of " + content);
});}
};
function fetchIt(myurl, onSuccess) {// Fetching from myurl the content, when ready invoke// the onSuccessonSuccess("<html>...</html>");
}
obj.fetchUrl();
Itworks!
167
NoneedforPatternswhenusingArrowSyntaxvar obj = {
url: "./test.html",fetchUrl: function() {
fetchIt(this.url, (content) => {console.log("Fetched from " + this.url);console.log("With content of " + content);
});}
};
function fetchIt(myurl, onSuccess) {// Fetching from myurl the content, when ready invoke// the onSuccessonSuccess("<html>...</html>");
}
obj.fetchUrl();
Itworks!Lexicalthis
168
Lab
169
EcmaScript5:Strictmode
170
AboutStrictMode
• IntroducedinEcmaScript5,strictmodemakeschangesinnormalEcmaScriptsemantics• Differences
1. Strictmodecanrunfasterinidenticalcodethanwithoutstrict2. Silenterrors->Throwerrors(willfail)3. Prohibetssomesyntax
• Enableglobally orinfunction• Useit!
171
Silenterror
Infinity = 9;
NaN = 12;
console.log(Infinity);
console.log(NaN);Willfailbutit
issilent
172
Silenterror
var obj1 = {id: 1};
Object.preventExtensions(obj1);
obj1.name = "Jack";Willfailbutit
issilent
173
Global:Usestrict
"use strict";
var obj1 = {id: 1};
Object.preventExtensions(obj1);
obj1.name = "Jack";
TypeError:Can'taddpropertyname,objectisnotextensible
Enablestrictmode.It'sjustastring!
174
Infunctions:usestrict
function doIt() {
"use strict";
console.log("This is under strict mode");
}
Nowonlythisfunctionusesstrictmode
175
Enablingstrict
"use strict";
var obj1 = {id: 1};
Object.preventExtensions(obj1);
obj1.name = "Jack";
176
Variablewithoutvar
function doIt() {
variable = 4;
}
doIt();
console.log(variable);
Forgotthevarwordhere...itcreatesaglobal
variable!Confusing
177
Instrictmode,youhavetousethevar
"use strict";
function doIt() {
variable = 4;
}
doIt();
console.log(variable);
variableisnotdefined!
178
RegularExpressions
179
Regex
• RegularExpressions(Regex)arepatternsusedtomatchcharactercombinationsinstrings• InEcmaScript,regexareobjectsofRegExp
• var re = new RegExp('ab+c');• Alsoregexliteralavailable
• var re = /ab+c/
180
RegexLiteral:LoadedwhenScriptisloaded
var variable = "ab+c";
var regex1 = /variable/;
var regex2 = /ab+c/
console.log(regex1.test("variable"));
console.log(regex2.test("abbc"));
Botharetrue!Youcannothavedynamiccontentinregexliteral
181
SimpleRegex
var regex = /hello/;
console.log(regex.test("hello world")); // true
console.log(regex.test("world hello world")); // true
console.log(regex.test("world helxlo world")); // false
182
Begin(^)andEnd($)
var regex1 = /^hello/;
var regex2 = /hello$/;
var regex3 = /^hello$/;
console.log(regex1.test("hello world")); // true
console.log(regex2.test("world hello")); // true
console.log(regex3.test("hello")); // true
console.log(regex3.test("hellohello")); // false
183
Amount:+,*,?,{}var regex1 = /^(hello)+$/; // [1,n]var regex2 = /^(hello)*$/; // [0,n]var regex3 = /^(hello)?$/; // [0,1]var regex4 = /^(hello){0,3}$/; // [0,3]
console.log(regex1.test("")); // falseconsole.log(regex1.test("hello")); // trueconsole.log(regex1.test("hellohello")); // true
console.log(regex2.test("")); // trueconsole.log(regex2.test("hello")); // trueconsole.log(regex2.test("hellohello")); // true
console.log(regex3.test("")); // trueconsole.log(regex3.test("hello")); // trueconsole.log(regex3.test("hellohello")); // false
console.log(regex4.test("")); // trueconsole.log(regex4.test("hello")); // trueconsole.log(regex4.test("hellohello")); // true
184
OtherSpecialCharacters
Character Meaning
. Anycharacter,forexample/.n/matchesanandon
\. equals todot
x|y Or,forexample /black|white/matcheseitherblackorwhite
[xyz] or [a-z] Character set
[^abc] Negatedcharacterset,cannotbeaborc.
\d [0-9]
\D [^0-9]
\s Whitespace, space,tab...
\S Nonwhitespace
\w [a-zA-Z0-9_]
\W [^a-zA-Z0-9_]185
WorkingwithRegex
Method Meaning
exec ARegExpmethodthatreturnsarrayofinformationaboutthematch
test ARegExpmethodthatreturnstrueorfalse
match AStringmethodthatreturnsarrayofinformation aboutthematch
search AStringmethodthatreturnsindex ofthematch
replace AStringmethodthatexercutesasearchandreplacesthematchedsubstring
split AStringmethodthatbreaksastringintoanarrayofsubstrings
186
RegExpexecvstest
var regex = /hello/; // [1,n]
// [ 'hello', index: 8, input: 'testing hello does it work?' ]
console.log( regex.exec("testing hello does it work?") );
// null
console.log( regex.exec("mickeymouse") );
// false
console.log( regex.test("mickeymouse") );
// true
console.log( regex.test("hello") );
187
Stringmatch,search,replace,splitvar regex = /hello/;
var mj = "testing hello does it work?";
// [ 'hello', index: 8, input: 'testing hello does it work?' ]
console.log( mj.match(regex) );
// 8
console.log( mj.search(regex) );
// testing world does it work?
console.log( mj.replace(regex, "world") );
// [ 'testing ', ' does it work?' ]
console.log( mj.split(regex) );
188
ExampleofFlags
var regex1 = /hello/i;
var regex2 = new RegExp("hello", "i");
console.log( regex1.test("HelLo") );
console.log( regex2.test("HelLo") );
189
Lab
190
InheritanceinEcmaScript
191
AboutInheritance
• Codereuseisimportant• Inheritancecanhelp
• JavaScriptdoesnothaveclasses,sonospecialkeywordforextending• ThiscanbeveryconfusingforJava/C#developers• Objectsinheritobjects
• WellECMAScript6hasclasses.Butintheendit'sjustsyntacticsugarwhereunderneathobjectinheritesanotherobject
192
ObjectextendsObject
• InEcmaScriptobjectextendsotherobject• Everyobjecthasspecial__proto__ propertythatlinkstoobjectthatitinherites
193
(Bad)exampleof__proto__
var parent = {method1: function() { console.log("A"); }
}
var child = {__proto__: parent,method2: function() { console.log("B"); }
}
child.method1(); // Achild.method2(); // B
childextendsparent
194
__proto__
• __proto__ isdepricated,non-standard andshouldnotbeused!• Togettheparent,use
• Object.getPrototypeOf(child)• Tosettheparent,use(OnlyinEcmaScript2015!)
• Object.setPrototypeOf(child, parent)
195
Testingvar parent = {
method1: function() { console.log("A"); }
}
var child = {
method2: function() { console.log("B"); }
};
Object.setPrototypeOf(child, parent);
console.log(Object.getPrototypeOf(child) == parent); // true
child.method1(); // A
child.method2(); // B
196
Object.setPrototypeOf(child, parent)
• TheObject.setPrototypeOf alterstheobject's__proto__ andthiscanbeveryslowoperation• AlsoObject.setPrototypeOf isEcmaScript2015feature,soitwon'tworkforexampleinolderbrowsers
• Insteadofalteringobject's__proto__,createnewobjectwithdesiredparentusingObject.create(obj, parent) • SupportedfromEcmaScript5th edition->
197
Object.create(obj)
var parent = {method1: function() { console.log("A"); }
}
var child = Object.create(parent);child.method2 = function() { console.log("B"); }
console.log(Object.getPrototypeOf(child) == parent); // true
child.method1(); // Achild.method2(); // A
Nownewobjectiscreatedwhichparentis
parent
198
WorkingwithConstructors
• Whenwriting• function Animal() { }
• Twoobjectsarecreated!• 1)Animal• 2)Animal.prototype
• Thesetwoobjectsarelinkedtogether!
199
Example
function Animal() {
}
console.log(Animal instanceof Function); // true
console.log(Animal.prototype instanceof Object); // true
console.log(Animal.prototype.constructor == Animal) // true
Animal(Function– Object)
X
prototype
constructor
200
Constructorfunctionandnew
• Constructorfunctionisusedwithnew– keyword• var spot = new Animal();
• Bydefaultthespot inheritesAnimal.prototype!
Animal(Function– Object)
AnimalParent
prototype constructor
spot
__proto__
Parentobject!
201
Testing
function Animal() { }
var spot = new Animal();
console.log(spot.__proto__ == Animal.prototype);
console.log(Object.getPrototypeOf(spot) == Animal.prototype);
Non-standardway
spot extendsAnimal.prototype
202
203
Example
function Animal() { }
var animal1 = new Animal();var animal2 = new Animal();
var animal3 = new Animal();
Animal.prototype.name = "Jack";
console.log(animal1.name); // "Jack"console.log(animal2.name); // "Jack"console.log(animal3.name); // "Jack"
animal1,animal2 andanimal3 extend
Animal.prototype
204
function Animal() {}
function Dog() {}
var spot = new Dog();
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
console.log(Dog.prototype.__proto__ == Animal.prototype);
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(spot.__proto__.__proto__ == Animal.prototype); console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
EcmaScript2015Feature,canbeslow.NowDog.prototype extendsAnimal.prototype.spotextends
Dog.prototype
true
true
205
Animal.prototype
Dog.prototype
spot1
animal1
spot2 spot3
animal2
206
function Animal() {}
function Dog() {}
var spot = new Dog();
Object.setPrototypeOf(Dog.prototype, Animal.prototype);
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
UseObject.create(..) instead
207
function Animal() {}
function Dog() {}
var spot = new Dog();
Dog.prototype = Object.create(Animal.prototype);
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name);
Createsanewobject!Wehaveaproblem...
undefined
208
function Animal() {}
function Dog() {}
var spot = new Dog();
Dog.prototype = Object.create(Animal.prototype);
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name);
DogParent
spot
__proto__NowspotextendsDogParentwhichisaccessedbyDog.prototype
Dog
prototype
209
function Animal() {}
function Dog() {}
var spot = new Dog();
Dog.prototype = Object.create(Animal.prototype);
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name);
Thiscreatesanewobject!
210
function Animal() {}
function Dog() {}
var spot = new Dog();
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
ThenewObject hereisthenewobjectcreated!
211
function Animal() {}
function Dog() {}
var spot = new Dog();
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParent
spot
__proto__
Dog
prototype
newObject
__proto__
Animal.prototype
212
function Animal() {}
function Dog() {}
var spot = new Dog();
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParent
spot
__proto__
Dog
prototype
newObject
__proto__
Animal.prototype
213
function Animal() {}
function Dog() {}
var spot = new Dog();
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParent
spot
__proto__
Dog
prototype
newObject
__proto__
Animal.prototype
Dog.prototype=>newObjectnewObject.__proto__=>Animal.prototype
=true!
214
function Animal() {}
function Dog() {}
var spot = new Dog();
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParent
spot
__proto__
Dog
prototype
newObject
__proto__
Animal.prototypespot__proto=>DogParent
false!
215
Let'schangeorderfunction Animal() {}
function Dog() {}
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
var spot = new Dog();
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
Let'screatefirstthenewObjectandthencreatethespot!
216
function Animal() {}
function Dog() {}
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
var spot = new Dog();
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParentDog
prototype
217
function Animal() {}
function Dog() {}
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
var spot = new Dog();
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParentDog
prototype
newObject
__proto__
Animal.prototype
218
function Animal() {}
function Dog() {}
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
var spot = new Dog();
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
DogParent(garbagecollectorwilldeletethis)
Dog
prototype
newObject
__proto__
Animal.prototype
219
function Animal() {}
function Dog() {}
let newObject = Object.create(Animal.prototype);
Dog.prototype = newObject;
var spot = new Dog();
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
Dog
prototype
newObject
__proto__
Animal.prototypeBydefaultspotwillextend
Dog.prototypewhichisnowthenewObject
spot
__proto__
220
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
var spot = new Dog();
console.log(Object.getPrototypeOf(Dog.prototype) == Animal.prototype);
console.log(Object.getPrototypeOf(Object.getPrototypeOf(spot)) == Animal.prototype);
Animal.prototype.name = "jack";
console.log(spot.name); // "jack"
Dog
prototype
NewDogParent
__proto__
Animal.prototype
spot
__proto__
WedonotneedthenewObjectpointer
221
Object.create(..)- recap
function Animal() {}
function Dog() {}
// EcmaScript 5
// Create new object that extends Animal.prototype
Dog.prototype = Object.create(Animal.prototype);
// Now spot -> Dog.prototype -> Animal.prototype
var spot = new Dog();
console.log(spot.__proto__ == Dog.prototype); // true
console.log(spot.__proto__.__proto__ == Animal.prototype); // true
222
Animal.prototype
Dog.prototype
spot1
animal1
spot2 spot3
animal2
223
Wearenotdoneyet...
224
Constructors
function Dog() {}
var spot = new Dog();
console.log(spot.constructor == Dog);
Dog
prototype
DogParent
constructor
spot
__proto__
Youcanaskfromanobjectwhatisit'sconstructor.Theconstructorpropertyisbuiltintheparent
object
Twoobjectsarecreated!TheDogParentobjecthasaconstructor
property!
225
Constructors
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
var spot = new Dog();
console.log(spot.constructor == Dog);
Createsanewobjectwhich__proto__pointstoAnimal.protototype.The
newobjectdoesnothaveconstructorproperty!
226
Dog
prototype
(thenewobject)
__proto__
spot
__proto__
Animal
prototype
AnimalParent
constructor
console.log(spot.constructor);
Constructorpropertyisnotfoundinspot.Itwilltrytofinditinthenewobject.It'snotthereeither!ThenitwillfetchitfromtheXandendresultisthatspotiscreatedfromAnimal!
227
Dog
prototype
(thenewobject)
__proto__constructor
spot
__proto__
Animal
prototype
AnimalParent
constructor
Dog.prototype.constructor = Dog;
Let'saddthis!
228
Done!
function Animal() {}
function Dog() {}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
var spot = new Dog();
229
InvokingBaseConstructor
230
Function.call- method
function Dog(name) {this.name = name;
}
let spot = new Dog("Spot");console.log(spot.name);
let obj = {};Dog.call(obj, "Vilma");console.log(obj.name);
Youcaninvokethefunctionanddefinewhatthismeansin
runtime
thisnowreferstospot-object
231
WhenusingConstructor- functionsfunction Shape(x, y, color) {
this.x = x;
this.y = y;
this.color = color;
}
function Circle(x, y, color, radius) {
Shape.call(this, x, y, color);
this.radius = radius;
}
let circle = new Circle(0, 0, "red", 5);
console.log(circle.color);
232
EcmaScript2015:Classes
233
class Shape {constructor(x, y, color) {
this.x = x;this.y = y;this.color = color;
}}
class Rectangle extends Shape {constructor (x, y, color, width, height) {
super(x, y, color);this.width = width;this.height = height;
}}class Circle extends Shape {
constructor (x, y, color, radius) {super(x, y, color);this.radius = radius;
}}
let circle = new Circle(0,0,"red",5);console.log(circle);
Alotnicersyntaxforcreatinginheritance!
234
class Shape {constructor(x, y, color) {
this.x = x;this.y = y;this.color = color;
}}
class Rectangle extends Shape {constructor (x, y, color, width, height) {
super(x, y, color);this.width = width;this.height = height;
}}class Circle extends Shape {
constructor (x, y, color, radius) {super(x, y, color);this.radius = radius;
}}
Shape.prototype.hello = "world";
let circle = new Circle(0,0,"red",5);
console.log(circle.hello);
Butitissyntacticalsugar!!
235
Let'scompilethissyntaxtoolder
EcmaScriptà (OhDear....)
236
React- Example
• ReactisaJavaScriptframeworkforbuildingUIinfront-end• ItisdevelopedbyFacebookandverypopular
• YoucreateUIcomponentsintheframework• UsesEcmaScript2015andJSX
• CompiledtoolderEcmaScriptusingBabelsoitworksonbrowsers
class Welcome extends React.Component {
render() {
return <h1>Hello World</h1>;
}
}
237
EcmaScript2015(6th edition)
238
NewFeatures
• ArrowFunctions• Parametervalues• Objectproperties• Modules• Classes• Somenewbuiltmethods
239
ArrowFunctionslet array = [0,1,2,3,4];
array.forEach(doIt);
function doIt(value) {
console.log(value);
}
array.forEach(function(value) {
console.log(value);
});
array.forEach((value) => {
console.log(value);
});
array.forEach((value) => console.log(value) );
240
Lexicalthis
var object = {array: [0,1,2,3,4],doIt: function() {
this.array.forEach(function(value) {this.array.push(value);
});}
}
object.doIt();
Cannotreadproperty'push'ofundefined
241
Lexicalthis
var object = {
array: [0,1,2,3,4],
doIt: function() {
var _this = this;
this.array.forEach(function(value) {
_this.array.push(value);
});
}
}
object.doIt();
Itworkswhenusingclosure
242
Lexicalthis
var object = {array: [0,1,2,3,4],doIt: function() {
this.array.forEach((value) => {this.array.push(value);
});}
}
object.doIt();
Works!
243
DefaultParametervalues
function printIt(text, amount = 1) {
for(let i = 0; i < amount; i++) {
console.log(text);
}
}
printIt("text");
printIt("text", 7);
244
VariadicParameterValues
function printIt(amount, ...text) {for(let i = 0; i < amount; i++) {
for(let j = 0; j < text.length; j++) {console.log(text[i]);
}}
}
printIt(1, "text");printIt(2, "hello", "world");
245
SpreadOperator
var array1 = [ "hello", "world" ];
var array2 = [ 1, ...array1 ];
// [ 1, 'hello', 'world' ]
console.log(array2);
246
InterpolationofString
var message = "hello";
var html = `
<div>
<p>${message}</p>
</div>
`;
console.log(html);
247
ObjectProperties
let x = 0;
let y = 1;
let obj = { x, y };
console.log(obj.x);
console.log(obj.y);
248
Modules
249
AboutModules
• ModulesSystems1. AMDSpecification(RequireJS)2. CommonJSModules(NodeJS)3. ES2015officialmodule
• InEcmaScript2105forthefirsttimeit'sbuiltintolanguage.Supportisweak.• It'spossibletocompileES6ModulestoAMDorCommonJS• NodewillsupportES2015modulesintheupcomingversions• Angular2FrameworkusesES2015modules
250
ES2015Modules
251
Babel
• SinceES2015modulesupportisweak,installBabeltranspiler• TranspilerwillcompilenewES2015featurestoolderESthatyoucanuseinNodeJSorBrowsers• Toinstallglobally
• npm install -g babel-cli
252
EcmaScript2015:app.js
import { generateRandom, sum } from 'utility';
console.log(generateRandom()); // logs a random number
console.log(sum(1, 2)); // 3
253
EcmaScript2015:utility.js
function generateRandom() {
return Math.random();
}
function sum(a, b) {
return a + b;
}
export { generateRandom, sum }
254
CommonJS
255
CommonJS
• CommonJSisaprojectwiththegoalofspecifyingecosystemforJSoutsideofBrowser• WasstartedbyMozillaengineer,initalnameServerJS
• CommonJSdescribedalotofspecifications,includingmodules• ThismodulespecificationisimplementedinNodeJS• require toincludemodules• exports tomakethingsavailable
256
app.js
// import { generateRandom, sum } from 'utility';
require("./utility.js");
console.log(generateRandom()); // logs a random number
console.log(sum(1, 2)); // 3
257
utility.js
generateRandom = function() {
return Math.random();
}
sum = function (a, b) {
return a + b; }
258
ExampleModule:randomModule.js
'use strict';
/*** Returns random integer number between [min, max].
* @param {number} min* @param {number} max* @return {number}*/
module.exports = function(min, max) {return Math.floor(Math.random() * (max - min + 1)) + min;
};
UsesJSdoc
259
ExampleModule
'use strict';
var random = require("./randomModule");
console.log(random(1,10));
260
ExportingObject
'use strict';
var MyMath = {
random: function(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
},
abs: function(value) {
return (value < 0) ? value * -1: value;
}
};
module.exports = MyMath;
261
ImportingObject
'use strict';
var MyMath = require("./mathModule");
console.log(MyMath.random(1,10));
console.log(MyMath.abs(-7));
262
exportsvsmodule.export
'use strict';
module.exports.variable1 = "hello";
exports.variable2 = "world";
thesepointtothesameobject
263
exportsvsmodule.exports
'use strict';
var module = { exports: {} };
var exports = module.exports;
module.exports.variable1 = "hello";
exports.variable2 = "world";
return module.exports;
Itwillalwaysreturn
module.exports
264
WhatHappens?
'use strict';
var user = {name: "Jack"};
module.exports = user;
exports.variable = "hello";
var object = require("./randomModule");
console.log(object.name);
console.log(object.variable);
265
NowTwoDifferentObjects!
module.exports
exports
{name: "jack"}
{variable: "hello"}
266
ExceptionHandling
267
Examplefunction divide(a, b) {
if(!(typeof a == 'number' && typeof b == 'number')) {
throw "You must give number variables";
} else {
return a / b;
}
}
try {
console.log( divide(1, 5) );
console.log( divide("do", "this?") );
} catch(e) {
console.log(e);
}
268
function MustBeNumbersException(message) {
this.message = message;
this.name = "MustBeNumbersException";
}
function divide(a, b) {
if(!(typeof a == 'number' && typeof b == 'number')) {
throw new MustBeNumbersException("You must give number variables");
} else {
return a / b;
}
}
try {
console.log( divide("does not work", 0) );
} catch(e) {
console.log(e.name);
console.log(e.message);
}
Betterversion,ourown
exceptionobject
269
function MustBeNumbersException(message) {this.message = message;this.name = "MustBeNumbersException";
}
function ZeroDivisionException(message) {this.message = message;this.name = "ZeroDivisionException";
}
function divide(a, b) {if(!(typeof a == 'number' && typeof b == 'number')) {
throw new MustBeNumbersException("You must give number variables");} else if(b == 0) {
throw new ZeroDivisionException("Cannot divide with 0");} else {
return a / b;}
}
try {console.log( divide(1, 0) );
} catch(e) {console.log(e.name);console.log(e.message);
}
Bothoftheexceptionsgo
here
270
function MustBeNumbersException(message) {this.message = message;this.name = "MustBeNumbersException";
}
function ZeroDivisionException(message) {this.message = message;this.name = "ZeroDivisionException";
}
function divide(a, b) {if(!(typeof a == 'number' && typeof b == 'number')) {
throw new MustBeNumbersException("You must give number variables");} else if(b == 0) {
throw new ZeroDivisionException("Cannot divide with 0");} else {
return a / b;}
}
try {console.log( divide(1, "k") );
} catch(e) {if (e instanceof MustBeNumbersException) {
console.log("annapa numeroita.");} else if (e instanceof ZeroDivisionException) {
console.log("ei nollalla saa jakaa.");}
}
Checkingwhatexceptionwas
thrown
271
UnitTesting
272
UnitTestingFrameworks
• Mocha• Jasmine• Should• NodeUnit• jsUnit
273
Mocha
• Installglobally• npm install –globally mocha
• Createtest/test.js• Youcanruntests
• mocha test/test.js• Orifyoumodifypackage.json
• npm test
274
MyMathmodule
'use strict';
var MyMath = {
abs: function(value) {
return (value < 0) ? value * -1: value;
},
max: function(number1, number2) {
return (number1 < number2) ? number2: number1;
}
};
module.exports = MyMath;
275
test/test.jsvar assert = require('assert');var MyMath = require("../mathmodule");
describe('MyMath', function() {describe('#abs(number)', function() {
it('It should return positive values when given negative values.', function() {assert.equal(1, MyMath.abs(-1));assert.equal(2, MyMath.abs(-2));assert.equal(3, MyMath.abs(-3));
});it('It should return positive values when given positive values.', function() {
assert.equal(1, MyMath.abs(1));assert.equal(2, MyMath.abs(2));assert.equal(3, MyMath.abs(3));
});
});describe('#max(number1, number2)', function() {
it('should return number1 if number1 > number2', function() {assert.equal(2, MyMath.max(2, 1));assert.equal(3, MyMath.max(3, 1));assert.equal(4, MyMath.max(4, 1));
});});
});
276
Exceptions
describe('ExceptionTest', function() {describe('#divide(number, number)', function() {
it('Exception tests', function() {assert.throws(() => { divide(2,0) }, ZeroDivisionException);assert.throws(() => { divide("k","h") }, MustBeNumbersException);
});});
});
277
TDD
• Designthetestsfirst!• Afterthisimplementthemodule!
278
AsyncandPromises
279
AboutPromises
• Promisesanalternativetocallbacksdeliveringresultofanasynccomputation• PromisesarepartofEcmaScript2015
• Previouslyyoucouldusethemasadditionallibrary• https://promisesaplus.com/
280
Typicalasyncfunctionwithcallback
asyncFunction(arg1, arg2,
result => {
console.log(result);
});
281
Problemswithcallbacks
• Whenasyncdone,doanotherasyncmethod(chaining)->usingcallbackscanbemessy• Whatisasyncfails?Ifyouhavechainedasyncmethodsandoneofthemfails?
• Itisnotstandard,everyonecanhavetheyownversionofdoingcallbacks
282
UsingPromisesfunction promiseFunction(resolve, reject) {
// time consuming async stuffif(true) {
resolve("OK!");} else {
reject("Failed!");}
}
function onSuccess(msg) {console.log(msg);
}
function onError(msg) {console.log(msg);
}
let promise = new Promise(promiseFunction);promise.then(onSuccess, onError);promise.then(onSuccess).catch(onError);
Youcandobothhere
283
Node.JScallbacks
const fs = require('fs');
fs.readFile('mytest.json',function (error, text) {
if (error) {console.error('Error while reading config file');
} else {try {
const obj = JSON.parse(text);console.log(JSON.stringify(obj));
} catch (e) {console.error('Invalid JSON in file');
}}
});
FileI/Omodule
284
Node.JSpromise
const util = require('util');const fs = require('fs');
const promiseReadFile = util.promisify(fs.readFile);
promiseReadFile('mytest.json').then(function (text) { //
const obj = JSON.parse(text);console.log(JSON.stringify(obj));
}).catch(function (error) { //
// File read error or JSON SyntaxErrorconsole.error('An error occurred', error);
});
util.promisifyisNode8feature
285
SimpleExample
function doSomeTimeConsumingStuff() {
function asyncOperation(resolve, reject) {
setTimeout(() => resolve("Done"), 1000);
}
return new Promise(asyncOperation);
}
doSomeTimeConsumingStuff().then(result => console.log('Result: ' + result));
286
function promiseFunction(resolve, reject) {// time consuming async stuffif(true) {
resolve(4);} else {
reject("First promise failed!");}
}
function onSuccess(result) {let p = new Promise((resolve, reject) => {
// time consuming async stuffif(true) {
resolve(result + 4);} else {
reject("Second promise failed");}
} );return p;
}
function onError(msg) {console.log(msg);
}
let promise = new Promise(promiseFunction);promise.then(onSuccess).then((result) => console.log("sum = " + result)).catch(onError);
Returnspromise
Chainingwiththen
Canhandlebotherrors!
287
async
async function doIt() {let sum = 0;for(let i=0; i<10; i++) {
console.log(i);sum = sum + i;
}return sum;
}
doIt().then((result) => console.log("result = " + result));
Wheninvokingasyncfunction,endresultis
promise!
288
EcmaScript2017:async
async function doIt() {let sum = 0;for(let i=0; i<10; i++) {
console.log(i);
sum = sum + i;}return sum;
}
doIt().then((result) => console.log(result));doIt().then((result) => console.log(result));
ThedoIt– methodisrunparallel
289
EcmaScript2017:awaitfunction fetchNumber() {
function asyncOperation(resolve, reject) {
let n = Math.round(Math.random() * 10); setTimeout(() => resolve(n), 1000);
}return new Promise(asyncOperation);
}
async function doIt1() {let a = await fetchNumber();console.log(a);let b = await fetchNumber();console.log(b);
let sum = a + b;return sum;
}
doIt1().then((result) => console.log(result));
Let'swaituntilwegetthenumber
290