Slide 1

Slide 1 text

ECMAScript Jussi Pohjolainen 1

Slide 2

Slide 2 text

Recommended Reading • Recommended reading • JavaScript: The Good Parts by Douglas Crockford • JavaScript: The Definite Guide by David Flanagan • JavaScript Patterns: Stoyan Stefanov • And Google.. 2

Slide 3

Slide 3 text

JavaScript today • EcmaScript is standardized subset of JavaScript • JavaScript is key language to implement web applications • Possible candidate for cross-platform mobile development • React, Cordova / Phonegap, Ionic • Server side development • Replacing / Complementing XML for data transfer (REST + JSON) 3

Slide 4

Slide 4 text

Rise of the Responsive Single Page App Image: http://johnpolacek.github.io/scrolldeck.js/decks/responsive/ 4

Slide 5

Slide 5 text

Responsive • Unified across experiences • Can be embedded as mobile app • Better deployment and & maintanence • Mobile users need to get access to everything Image: http://coenraets.org/blog/wp-content/uploads/2011/10/directory11.png 5

Slide 6

Slide 6 text

Single-page Applications (SPA) • Web app that fits on a single web page • Fluid UX, like desktop app • Examples like Gmail, Google maps • Html page contains mini-views (HTML Fragments) that can be loaded in the background • No reloading of the page, better UX • Requires handling of browser history, navigation and bookmarks 6

Slide 7

Slide 7 text

Rise of the REST and JSON • REST is a one way of communicating between computers over the internet • Data can be send via XML or JSON using HTTP • HTTP GET • http://something/employee/1 • Result • {id: 1, name: "jack"} • If both frontend and backend is JS, object sending and parsing extremely easy 7

Slide 8

Slide 8 text

Rise of the JS Backend: NodeJS • Open source JS runtime environment • Uses V8 (Chrome) JS engine • Additional modules on top of JS to provide functionality • Web server, system i/o, networking, ... • Lot of third party modules available 8

Slide 9

Slide 9 text

Native iOS App iOS WebView index.html app.js angularjs.js ionic.js cordova.js stylesheet.css Native Android App Android WebView index.html app.js angularjs.js ionic.js cordova.js stylesheet.css Using Cordova it's possible to access mobile device native features Web Server Node.js + Express + Mongo app.js package.json modules/express/ modules/mongodb/ MongoDB [{name: 'jack'}, {name: 'tina'}, {..}, {..}] HTTP GET (ajax) Request: http://server.com/employees/1 HTTP Response content-type: application/json {name: 'jack'} Frontend Ionic + Cordova + AngularJS Backend Node.JS + Express + Mongo HTTP POST Request: http://server.com/employees/ {name: 'amanda'} HTTP Response content-type: text/plain http://server.com/employees/3 Communication REST and JSON 9

Slide 10

Slide 10 text

Frontend 10

Slide 11

Slide 11 text

JavaScript, LiveScript, JScript, ECMAScript? • JavaScript • Developed by Netscape • Originally JavaScript, then LiveScript and then back to JavaScript. • JScript • Microsoft made their own version of the JavaScript • Lead to compatibility problems • => ECMAScript, effort to standardize different versions of the J(ava)Script 11

Slide 12

Slide 12 text

ECMAScript • ECMAScript is a scripting language, standardized by Ecma International • In Browsers, ECMAScript is commonly called JavaScript • JavaScript = Native (EcmaScript) + Host objects (browser) • Java/ECMAscript is nowdays heavily used when creating web / mobile and even Desktop - apps 12

Slide 13

Slide 13 text

Learning Path for Front-end Core EcmaScript Browser Host Objects JavaScript in Front-end HTML5 CSS Static Web-pages JavaScript Frameworks: React, AngularJS, ... 13

Slide 14

Slide 14 text

EcmaScript Versions Year Edition Naming 1997 1 .. 1998 2 .. 1999 3 Regex, better string handling, try/catch,... Abandoned 4 .. 2009 5 strict mode, getters and setters, JSON.. 2015 6 ES2015 classes, modules, arrow functions, collections ... 2016 7 ES2016 Math.pow => **, array.prototype.includes 2017 8 ES2017 await/async 14

Slide 15

Slide 15 text

From JScript to TypeScript • TypeScript is a superset of EcmaScript developed by Microsoft • It has types! • When EcmaScript 6th Edition was working progress, typescript gave already classes, modules, arrow function syntax. • Now that the 6th Ed. is ready the additional benefit using TypeScript is types (and others like interfaces, generics...) • TypeScript is compiled to EcmaScript using compiler • It's first class language in Microsoft Visual Studio and in frameworks like Angular 2.0 15

Slide 16

Slide 16 text

typescript.ts > cat typescript.ts var variable : string = "typescript"; console.log(variable); > tsc typescript.ts > cat typescript.js var variable = "typescript"; console.log(variable); Notice that compiler compiles typescript to javascript and it loses the string type because that is not part of js! 16

Slide 17

Slide 17 text

Benefit of using Compiler > 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

Slide 18

Slide 18 text

Tools for Learning EcmaScript 18

Slide 19

Slide 19 text

Choose a Code-Editor / IDE • Atom by GitHub • Customizable free editor • Built-in package manager for installing new packages • Works across operating systems: OS X, Linux or Windows • Visual Studio Code by Microsoft • In addition to Atom... • Has built-in support for JavaScript, TypeScript and Node.js • Also extensible by plug-ins • Goes beyond syntax highlighting and provides autocomplete with IntelliSense and debugger • WebStorm by JetBrains • Full IDE • Support for: Angular, React, Ionic, Cordova, React Native, Electron, Node.js .. • Debugger, Unit testing 19

Slide 20

Slide 20 text

Choose Runtime Environment • Forget the browser for now! • EcmaScript is a standard and there are multiple implementations for runtime environment; JavaScript Engines • Can be traditional interpreter or utilize just-in time compilation to bytecode • Different engines available • V8 by Google, powers Chrome • Nitro by Apple, powers Safari • Chakra by Microsoft, powers Edge • SpiderMonkey by Mozilla Foundation, powers Firefox • Rhino (Java Implementation) managed by Mozilla Foundation • ... 20

Slide 21

Slide 21 text

Runtime Environment: Node.js • Easiest way to use V8 JS Engine is to install Node.js • https://nodejs.org/en/ • Node.js is built on top of V8 and is "the" technology to use when creating backend application using JS • Also provides package ecosystem, npm (node package manager), that can be used to manage js-libraries • npm is heavily used when creating JavaScript apps today • Node.js support for ES2015 is 99% -> Good JS environment for learning EcmaScript • http://node.green/ 21

Slide 22

Slide 22 text

Hello World 22

Slide 23

Slide 23 text

23

Slide 24

Slide 24 text

24

Slide 25

Slide 25 text

Visual Studio Code - tips • Install Code Runner - extension for easier running of node (and other) apps • Debugging Node apps is supported by default! • Install Node.js extension pack • ESLint • npm • JavaScript Snippets • ... 25

Slide 26

Slide 26 text

Lab 26

Slide 27

Slide 27 text

npm package manager • Node.js contains a npm that can be used to install various extensions and packages • You can install packages • local (specific to your app) • ./node_modules • global (can be used everywhere) • /usr/local/lib/node_modules • When creating a node project, usually you will have a file package.json describing the project and it's dependencies 27

Slide 28

Slide 28 text

Packages 28

Slide 29

Slide 29 text

Trying to use package 29

Slide 30

Slide 30 text

npm init Creates package.json with information about our project 30

Slide 31

Slide 31 text

npm install project-name-generator --save Now dir for downloaded packages 31

Slide 32

Slide 32 text

cat package.json package.json is updated 32

Slide 33

Slide 33 text

cd node_modules The project-name- generator depends on other package which is downloaded also! 33

Slide 34

Slide 34 text

cat project-name-generator/package.json 34

Slide 35

Slide 35 text

node myapp.js 35

Slide 36

Slide 36 text

ESLint • ESLint is linting utility (code quality) tool for JavaScript • To install • npm install --save-dev eslint • ESLint requires a configuration file • To create one, use • ./node_modules/eslint/bin/eslint.js --init • You can answer to questions about style guide or take popular style guides 36

Slide 37

Slide 37 text

Answering to Style Guide Questions 37

Slide 38

Slide 38 text

Running ESLint Add no- console: off to init file 38

Slide 39

Slide 39 text

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" ] } }; Add no- console: off to init file Lot of rules https://eslint.org/docs/rules/ 39

Slide 40

Slide 40 text

VS Code has also ESLint plugin for integrating linting in code editor 40

Slide 41

Slide 41 text

Different Style Guides • AirBnb • Google • "Standard" Style • Crockford's Coding Standards for JavaScript • NodeJS Style Guide 41

Slide 42

Slide 42 text

Holy War about Styles: Indentation https://hackernoon.com/what-javascript-code-style-is-the-most-popular-5a3f5bec1f6f 42

Slide 43

Slide 43 text

Holy War about Styles: Lint tool? https://hackernoon.com/what-javascript-code-style-is-the-most-popular-5a3f5bec1f6f 43

Slide 44

Slide 44 text

ESLint: Choosing Style Guide 44

Slide 45

Slide 45 text

Standard Rules • 2 spaces for indentation • Single quotes for string • No unused variables • No semicolons • ... • https://standardjs.com/ 45

Slide 46

Slide 46 text

Lab 46

Slide 47

Slide 47 text

Quick intro to ECMAScript 47

Slide 48

Slide 48 text

References • EcmaScript 5.1 Language Spesification • http://www.ecma-international.org/ecma-262/5.1/ • EcmaScript 6 Language Spesification (June 2015) • http://www.ecma-international.org/ecma-262/6.0/index.html • Really good JavaScript Reference from Mozilla • https://developer.mozilla.org/en- US/docs/Web/JavaScript/Reference • W3Schools have lot of JS stuff too but remember • http://meta.stackoverflow.com/questions/280478/why-not- w3schools-com 48

Slide 49

Slide 49 text

Grammar and Types 49

Slide 50

Slide 50 text

ECMAScript Basics • Borrows most of the syntax from Java but influences from other languages also • Java and JavaScript are totally different as a technology! • ECMAScript is case-sensitive • Instructions are called statements and are separated typically using semicolon (;) • Standard JavaScript Linter avoids semicolon usage 50

Slide 51

Slide 51 text

About semicolons • You can write • console.log("hello"); • console.log("world"); • Or • console.log("hello") • console.log("world") 51

Slide 52

Slide 52 text

Comments // One line /* multi- line */ /* No nested /* comments */ allowed */ 52

Slide 53

Slide 53 text

Variables • To declare a variable use keyword var or let • var x = 99; • Variable naming has some rules • must start with a letter, underscore (_), dollar sign • A-Z is different from a-z (case sensitive) • After the first letter, digits can be used (0-9) 53

Slide 54

Slide 54 text

Variable Scope • Global variable • Declare variable outside of function, available everywhere • Local variable • Declare variable inside of function, available in that function • Before ES2015, no block statement! 54

Slide 55

Slide 55 text

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 It is global! Function scope! 55

Slide 56

Slide 56 text

Variable Hoisting This code is the same ... var globalVariable = "Hello"; function doIt() { console.log(globalVariable); if(true) { var globalVariable = "World"; } } doIt(); console.log(globalVariable); ... than this var globalVariable = "Hello"; function doIt() { var globalVariable; console.log(globalVariable); if(true) { globalVariable = "World"; } } doIt(); console.log(globalVariable); It is hoisted! 56

Slide 57

Slide 57 text

Variable Hoisting function doIt() { console.log(myVar); // undefined if(true) { var myVar = "Hello World"; } } doIt(); 57

Slide 58

Slide 58 text

ES2015 Variable Hoisting: let function doIt() { console.log(myVar); // myVar is not defined! if(true) { let myVar = "Hello World"; } } doIt(); It is not hoisted! 58

Slide 59

Slide 59 text

Word About ES2015 • When developing to backend using Node.js developer can choose the version of Node.js and use freely most of ES2015 features • On the front-end things get complicated since user may have whatever browser and those may not support ES2015 • ES2015 can be compiled to older ES! 59

Slide 60

Slide 60 text

ES2015: const • Constant cannot be changed through assignment • const variables are not hoisted const PI = 3.14; PI = 99; console.log(PI); 60

Slide 61

Slide 61 text

ES2015 -> ES5 Object.defineProperty(typeof global === "object" ? global : window, "PI", { value: 3.141593, enumerable: true, writable: false, configurable: false }) console.log(PI); 61

Slide 62

Slide 62 text

Data Types: Primitive types (6) Type Possible values boolean true or false null null undefined undefined number 41, 3.444 string "Hello World" symbol unique and immutable instances (ES2015) All other are objects! 62

Slide 63

Slide 63 text

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) Language design error! 63

Slide 64

Slide 64 text

Primitive types vs Object types • Let's look at objects later on more carefully • Object in ES is just a variable containing properties: • var myObject = {"name": "Jack"}; • console.log(myObject.name); • Objects are passed by reference • Primitive types are passed by value 64

Slide 65

Slide 65 text

String • String literal contains characters enclosed by "" or '' var x = "Hello World"; • In ES2015 also possibility to use template literals: ` 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.` • There is string primitive type and String object! • ES will make automatic casting between these two, so it is possible to access all the methods provided by the String: • console.log( x.charAt(0) ); 65

Slide 66

Slide 66 text

Data Type Conversion 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

Slide 67

Slide 67 text

About Numbers • Number(value), converts entire string • var i = Number("12"); • parseInt(value[, radix]), converts start of the string • var i = parseInt("12px”, 10); • Radix? • 10 => integer number, 8 => octal number, 16 => hexadecimal • NaN (Not a Number), check using isNaN(variable) • Result of erroneous operations 67

Slide 68

Slide 68 text

Indexed Collection: Arrays • Arrays are objects but in addition they have more methods and auto- increment key-values • var stuff = ["a", "b", "c"] • The keys are now 0, 1 and 2 • The length of the array is 3 and it's linked to numerical properties 68

Slide 69

Slide 69 text

Input & Output – Depends! • In Browsers • Input: HTML Forms or window.prompt("", ""); • Output: DOM manipulation, document.write("") or window.alert(""); • In V8/NodeJS or Rhino/Spidermonkey • Output to CLI: print(".."); • Input from CLI: Is not that easy... • Debugging • console.log(""); 69

Slide 70

Slide 70 text

Lab 70

Slide 71

Slide 71 text

Control Flow, Loops and Iteration 71

Slide 72

Slide 72 text

Conditional Statements if (condition_1) { statement_1; } else if (condition_2) { statement_2; } else if (condition_n) { statement_n; } else { statement_last; } 72

Slide 73

Slide 73 text

False Values let array = [false, undefined, null, 0, NaN, ""]; for(let i=0; i

Slide 74

Slide 74 text

Comparison: true or false? let x = new Boolean(false); if(x) { console.log("true"); } else { console.log("false"); } 74

Slide 75

Slide 75 text

Comparison: true or false? let x = new Boolean(false); if(x == false) { console.log("true"); } else { console.log("false"); } 75

Slide 76

Slide 76 text

Equality • Strict equality • === • Loose equality • == • ES2015 • Object.is 76

Slide 77

Slide 77 text

77

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

switch case switch (expression) { case label_1: statements_1 [break;] case label_2: statements_2 [break;] ... default: statements_def [break;] } 80

Slide 81

Slide 81 text

while let i=0; while(i < 10) { console.log(i); i = i + 1; } 81

Slide 82

Slide 82 text

do-while let i=0; do { console.log(i); i = i + 1; } while(i < 10); 82

Slide 83

Slide 83 text

for for(let i = 0; i < 10; i = i + 1) { console.log(i); } 83

Slide 84

Slide 84 text

for ... of – for arrays let array = ["jack", "tina"]; // Traditional for for(let i = 0; i < array.length; i++) { console.log(array[i]); } // for - of for(let item of array) { console.log(item); } 84

Slide 85

Slide 85 text

for ... of – for arrays let array = ["jack", "tina"]; // 0 => "jack", 1 => "tina", "key" => "value" array["key"] = "value"; // for - of for(let item of array) { console.log(item); // ?? } 85

Slide 86

Slide 86 text

for ... in – for objects let array = ["jack", "tina"]; // 0 => "jack", 1 => "tina", "key" => "value" array["key"] = "value"; // for - in for(let item in array) { console.log(item); // ?? } 86

Slide 87

Slide 87 text

for ... in – for objects let object = {"key1": "value1", "key2": "value2"}; for(let key in object) { console.log(key); console.log(object[key]) } 87

Slide 88

Slide 88 text

Numbers and Text 88

Slide 89

Slide 89 text

About numbers • All numbers are double- precision 64-bit • Largest safe integer: 9007199254740991 • Safe? You can do calculations and display numbers correctly • No specific type for integers • Also symbolic values • +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

Slide 90

Slide 90 text

Number // Largest integer value console.log(Number.MAX_SAFE_INTEGER); // Largest floating point value console.log(Number.MAX_VALUE); // Smallest floating point value console.log(Number.MIN_VALUE); // Same values console.log(Number.POSITIVE_INFINITY) console.log(+Infinity); console.log(Infinity); // Same values console.log(Number.NEGATIVE_INFINITY) console.log(-Infinity); // Same values console.log(Number.NaN); console.log(NaN); 90

Slide 91

Slide 91 text

Number Number.parseFloat(..) Number.parseInt(..) Number.isFinite(..) Number.isInteger(..) Number.isNaN(..) Number.isSafeInteger(..) 91

Slide 92

Slide 92 text

Math Math.PI Math.abs(..) Math.min(..) Math.max(..) Math.random() Math.round(..) Math.sqrt(..) ... 92

Slide 93

Slide 93 text

String objects • EcmaScript has String primitive type and object • Primitive type is casted to object when needed • Use primitive type! • String object has variety methods that you can use let s = new String('foo'); console.log(s); // [String: 'foo'] console.log(typeof s); // object 93

Slide 94

Slide 94 text

Some String methods • charAt • startsWith • endsWith • split • slice • substring • match • replace • toLowerCase • toUpperCase • trim 94

Slide 95

Slide 95 text

Date, Time and Number formatting • Intl namespace has language sensitive date, time and number formatting • For formatting dates and time • Intl.DateTimeFormat • For formatting numbers • Intl.NumberFormat • Note that Node.js is bundled only with English! var date = new Date(); var dateTimeFormatter = new Intl.DateTimeFormat('fi-FI'); console.log(dateTimeFormatter.format(date)); 95

Slide 96

Slide 96 text

Lab 96

Slide 97

Slide 97 text

Indexed Collections Arrays... 97

Slide 98

Slide 98 text

Creating an Array // 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

Slide 99

Slide 99 text

Creating an Array with given size const ARRAY_LENGTH = 10; let arr1 = new Array(ARRAY_LENGTH); // OR let arr2 = []; arr2.length = ARRAY_LENGTH; 99

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

.length • length will return last element index + 1 • It is possible to change length at runtime • If giving shorter length, the array is truncated (removes items) 101

Slide 102

Slide 102 text

Iterating over Arrays 1. Traditional for 2. for of 3. forEach 4. for in (DON'T) 102

Slide 103

Slide 103 text

forEach (EcmaScript 5th Edition) let colors = ['red', 'green', 'blue']; colors.forEach(function(color) { console.log(color); }); 103

Slide 104

Slide 104 text

Array Methods • concat() • join() • push() • pop() • shift() • unshift() • slice() • splice() • reverse() • sort() • indexOf() • forEach() • map() • filter() • every() • some() • reduce() 104

Slide 105

Slide 105 text

every and some - 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

Slide 106

Slide 106 text

Keyed Collections: Map and Set 106

Slide 107

Slide 107 text

Map • Map object is a simple key/value map collection • You can iterate items in insertion order • Keys can be whatever value • Size is easily available 107

Slide 108

Slide 108 text

Example var 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

Slide 109

Slide 109 text

Set • Unique values • Insertion order is provided 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

Slide 110

Slide 110 text

Lab 110

Slide 111

Slide 111 text

Functions 111

Slide 112

Slide 112 text

Functions • Fundamental building block in EcmaScript • Set of statements that performs a task or calculates a value • Functions are objects! 112

Slide 113

Slide 113 text

Simple Function function doIt() { console.log("Hello World"); } doIt(); 113

Slide 114

Slide 114 text

Passing Argument function doIt(value) { console.log(value); } doIt("Hello World"); 114

Slide 115

Slide 115 text

Passing arguments and returning value function doIt(a, b) { return a + b; } console.log( doIt(5,5) ); 115

Slide 116

Slide 116 text

Predefined Argument function multiply(a, b = 1) { return a * b; } console.log(multiply(5)); 116

Slide 117

Slide 117 text

Functions are objects 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

Slide 118

Slide 118 text

And because they are objects... let functionObject = new Function("a","b", "return a+b;"); let anotherObject = functionObject; console.log ( functionObject(5,5) ); console.log ( anotherObject(5,5) ); 118

Slide 119

Slide 119 text

Passing Function Objects 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

Slide 120

Slide 120 text

arguments function doIt() { for(let item of arguments) { console.log(item) } } doIt("a"); doIt("a", "b"); doIt("a", "b", "c"); Predefined property of functions. You can fetch all the arguments from the array 120

Slide 121

Slide 121 text

Function Scoping: Works! greeting("hello world"); function greeting(msg) { console.log(msg); } 121

Slide 122

Slide 122 text

Function Scoping: Does not Work! greeting("hello world"); var greeting = function (msg) { console.log(msg); } variable greeting is hoisted and the value is undefined 122

Slide 123

Slide 123 text

Anonymous Function greeting("hello world"); var greeting = function (msg) { console.log(msg); } Anonymous function declaration 123

Slide 124

Slide 124 text

Remember this? 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

Slide 125

Slide 125 text

Remember this? 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); Instead of passing named functions we could use anonymous functions 125

Slide 126

Slide 126 text

Anonymous functions 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); }); Passing anonymous functions 126

Slide 127

Slide 127 text

Pattern: Avoid Globals (function() { var thisIsNotGlobalVariable = "hello"; console.log(thisIsNotGlobalVariable); })() 127

Slide 128

Slide 128 text

ES2015: Arrow Syntax 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)); Passing anonymous functions using the arrow syntax: simpler syntax and lexical this - keyword 128

Slide 129

Slide 129 text

Lab 129

Slide 130

Slide 130 text

Function that returns a Function function doIt() { function hello() { console.log("Hello World"); } return hello; } var func = doIt(); func(); 130

Slide 131

Slide 131 text

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

Slide 132

Slide 132 text

Closures function outer() { let x = 20; function inner() { console.log(x); } return inner; } var innerFunction = outer(); // is x still in memory? innerFunction(); Yes! When returning inner function that uses outer functions variables, those variables are stored in memory. 132

Slide 133

Slide 133 text

Pattern: Private member variables 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

Slide 134

Slide 134 text

Lab 134

Slide 135

Slide 135 text

Objects 135

Slide 136

Slide 136 text

Objects • Object is collection of properties • property is a association between key and value • value can be for example a function -> also called method • Objects, like functions are a fundamental part of EcmaScript • The keys must be string, if numbers used, it will make a typecast • So keys can be whatever if they can be converted into a string 136

Slide 137

Slide 137 text

Object Creation • Object initializer • let o = {}; • Using Object constructor • let o = new Object(); • Using Custom constructor • let o = new Car(); • Object.create (used in inheritance) • let dog = Object.create(animal); 137

Slide 138

Slide 138 text

Object Initializer // 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"]); Also possible to access using [] syntax In some cases [] syntax is mandatory.. if key is not a valid js identifier 138

Slide 139

Slide 139 text

Object Constructor let object = new Object(); object.key = "value"; object.hello = "world"; object["2"] = "another"; Possibility to add properties in runtime 139

Slide 140

Slide 140 text

Dynamic key 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"} Must use brackets for dynamic key! 140

Slide 141

Slide 141 text

EcmaScript 5: Prevent extensions, Seal, Freeze Add Delete Modify Object.preventExtensions NO YES YES Object.seal NO NO YES Object.freeze NO NO NO 141

Slide 142

Slide 142 text

Prevent Extensions var obj1 = {id: 1}; Object.preventExtensions(obj1); obj1.name = "Jack"; obj1.id = 3; delete obj1["id"]; Fails silently unless in strict mode 142

Slide 143

Slide 143 text

Seal var obj = {id: 1}; Object.seal(obj); obj2.name = "Jussi"; obj2.id = 4; delete obj2["id"]; 143

Slide 144

Slide 144 text

Freeze var obj = {id: 1}; Object.freeze(obj); obj.name = "Jussi"; obj.id = 4; delete obj["id"]; 144

Slide 145

Slide 145 text

EcmaScript 5: 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

Slide 146

Slide 146 text

Example var 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); } Cannot change Nothing in here 146

Slide 147

Slide 147 text

Constructor Function function Person(name) { this.name = name; } var tina = new Person("Tina"); console.log(tina.name); Write the function name with capital (convention) Use new – keyword to create object this refers to tina 147

Slide 148

Slide 148 text

What happens here? function Person(name) { this.name = name; } var tina = Person("Tina"); console.log(name) Forgot to use the new word! 148

Slide 149

Slide 149 text

Pattern: Preventing misuse function Person(name) { if(!(this instanceof Person)) { throw new TypeError("Cannot call a constructor function without new."); } this.name = name; } var tina = Person("Tina"); Type checking of this if new is missing, throw error 149

Slide 150

Slide 150 text

EcmaScript 2015: 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

Slide 151

Slide 151 text

EcmaScript 2015: 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()); Has prebuilt support for checking if new keyword is used or not. If new keyword is missing, this will fail! 151

Slide 152

Slide 152 text

Value can be anything, like functions let MyMath = { abs: function (value) { if (value < 0) { return value * -1; } else { return value; } } }; console.log ( MyMath.abs(-7) ); 152

Slide 153

Slide 153 text

Usage of Arrow Function and Ternary Operation let MyMath = { abs: (value) => value < 0 ? value * -1 : value }; console.log ( MyMath.abs(-7) ); 153

Slide 154

Slide 154 text

Enumerating: for...in var object = {key1: "value1", key2: "value2"}; for (var key in object) { console.log(key + " = " + object[key]); } 154

Slide 155

Slide 155 text

Lab 155

Slide 156

Slide 156 text

Keyword this 156

Slide 157

Slide 157 text

Keyword this • Node.js is a little bit different to EcmaScript when it comes to the keyword this • When using this in browsers, you will different results than in Node • One major difference is that Node uses modules where one file is one scope. In browsers, there is one scope • For now let's see how keyword this behaves in browsers 157

Slide 158

Slide 158 text

Keyword this in browsers console.log(this === window); console.log(doIt() == window); function doIt() { return this; } Both are true In functions and in global, this refers to a global main object which is window 158

Slide 159

Slide 159 text

Global variables in Browsers this.variable = "Hello"; console.log(window.variable); doIt(); console.log(window.name); console.log(name); function doIt() { this.name = "Jack"; } You do not have to write the main object! It's global variable! 159

Slide 160

Slide 160 text

Binding and keyword this 160

Slide 161

Slide 161 text

This should work... 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()); When invoking the method, keyword this is "replaced" with c - object 161

Slide 162

Slide 162 text

We have a problem 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()); No this does NOT refer to c – anymore... it will not work 162

Slide 163

Slide 163 text

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()); Create copy of that function where this refers to c 163

Slide 164

Slide 164 text

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 onSuccess onSuccess("..."); } obj.fetchUrl(); this? NOT working! 164

Slide 165

Slide 165 text

The same but now using of anonymous functions var 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 onSuccess onSuccess("..."); } obj.fetchUrl(); this? NOT working! 165

Slide 166

Slide 166 text

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 onSuccess onSuccess("..."); } obj.fetchUrl(); Send a copy of that function! 166

Slide 167

Slide 167 text

Pattern: Using Closure 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 onSuccess onSuccess("..."); } obj.fetchUrl(); It works! 167

Slide 168

Slide 168 text

No need for Patterns when using Arrow Syntax var 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 onSuccess onSuccess("..."); } obj.fetchUrl(); It works! Lexical this 168

Slide 169

Slide 169 text

Lab 169

Slide 170

Slide 170 text

EcmaScript 5: Strict mode 170

Slide 171

Slide 171 text

About Strict Mode • Introduced in EcmaScript 5, strict mode makes changes in normal EcmaScript semantics • Differences 1. Strict mode can run faster in identical code than without strict 2. Silent errors -> Throw errors (will fail) 3. Prohibets some syntax • Enable globally or in function • Use it! 171

Slide 172

Slide 172 text

Silent error Infinity = 9; NaN = 12; console.log(Infinity); console.log(NaN); Will fail but it is silent 172

Slide 173

Slide 173 text

Silent error var obj1 = {id: 1}; Object.preventExtensions(obj1); obj1.name = "Jack"; Will fail but it is silent 173

Slide 174

Slide 174 text

Global: Use strict "use strict"; var obj1 = {id: 1}; Object.preventExtensions(obj1); obj1.name = "Jack"; TypeError: Can't add property name, object is not extensible Enable strict mode. It's just a string! 174

Slide 175

Slide 175 text

In functions: use strict function doIt() { "use strict"; console.log("This is under strict mode"); } Now only this function uses strict mode 175

Slide 176

Slide 176 text

Enabling strict "use strict"; var obj1 = {id: 1}; Object.preventExtensions(obj1); obj1.name = "Jack"; 176

Slide 177

Slide 177 text

Variable without var function doIt() { variable = 4; } doIt(); console.log(variable); Forgot the var word here... it creates a global variable! Confusing 177

Slide 178

Slide 178 text

In strict mode, you have to use the var "use strict"; function doIt() { variable = 4; } doIt(); console.log(variable); variable is not defined! 178

Slide 179

Slide 179 text

Regular Expressions 179

Slide 180

Slide 180 text

Regex • Regular Expressions (Regex) are patterns used to match character combinations in strings • In EcmaScript, regex are objects of RegExp • var re = new RegExp('ab+c'); • Also regex literal available • var re = /ab+c/ 180

Slide 181

Slide 181 text

Regex Literal: Loaded when Script is loaded var variable = "ab+c"; var regex1 = /variable/; var regex2 = /ab+c/ console.log(regex1.test("variable")); console.log(regex2.test("abbc")); Both are true! You cannot have dynamic content in regex literal 181

Slide 182

Slide 182 text

Simple Regex 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

Slide 183

Slide 183 text

Begin (^) and End ($) 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

Slide 184

Slide 184 text

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("")); // false console.log(regex1.test("hello")); // true console.log(regex1.test("hellohello")); // true console.log(regex2.test("")); // true console.log(regex2.test("hello")); // true console.log(regex2.test("hellohello")); // true console.log(regex3.test("")); // true console.log(regex3.test("hello")); // true console.log(regex3.test("hellohello")); // false console.log(regex4.test("")); // true console.log(regex4.test("hello")); // true console.log(regex4.test("hellohello")); // true 184

Slide 185

Slide 185 text

Other Special Characters Character Meaning . Any character, for example /.n/ matches an and on \. equals to dot x|y Or, for example /black|white/ matches either black or white [xyz] or [a-z] Character set [^abc] Negated character set, cannot be a b or c. \d [0-9] \D [^0-9] \s Whitespace, space, tab ... \S Non whitespace \w [a-zA-Z0-9_] \W [^a-zA-Z0-9_] 185

Slide 186

Slide 186 text

Working with Regex Method Meaning exec A RegExp method that returns array of information about the match test A RegExp method that returns true or false match A String method that returns array of information about the match search A String method that returns index of the match replace A String method that exercutes a search and replaces the matched substring split A String method that breaks a string into an array of substrings 186

Slide 187

Slide 187 text

RegExp exec vs test 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

Slide 188

Slide 188 text

String match, search, replace, split var 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

Slide 189

Slide 189 text

Example of Flags var regex1 = /hello/i; var regex2 = new RegExp("hello", "i"); console.log( regex1.test("HelLo") ); console.log( regex2.test("HelLo") ); 189

Slide 190

Slide 190 text

Lab 190

Slide 191

Slide 191 text

Inheritance in EcmaScript 191

Slide 192

Slide 192 text

About Inheritance • Code reuse is important • Inheritance can help • JavaScript does not have classes, so no special keyword for extending • This can be very confusing for Java/C# developers • Objects inherit objects • Well ECMAScript 6 has classes. But in the end it's just syntactic sugar where underneath object inherites another object 192

Slide 193

Slide 193 text

Object extends Object • In EcmaScript object extends other object • Every object has special __proto__ property that links to object that it inherites 193

Slide 194

Slide 194 text

(Bad) example of __proto__ var parent = { method1: function() { console.log("A"); } } var child = { __proto__: parent, method2: function() { console.log("B"); } } child.method1(); // A child.method2(); // B child extends parent 194

Slide 195

Slide 195 text

__proto__ • __proto__ is depricated, non-standard and should not be used! • To get the parent, use • Object.getPrototypeOf(child) • To set the parent, use (Only in EcmaScript 2015!) • Object.setPrototypeOf(child, parent) 195

Slide 196

Slide 196 text

Testing var 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

Slide 197

Slide 197 text

Object.setPrototypeOf(child, parent) • The Object.setPrototypeOf alters the object's __proto__ and this can be very slow operation • Also Object.setPrototypeOf is EcmaScript 2015 feature, so it won't work for example in older browsers • Instead of altering object's __proto__, create new object with desired parent using Object.create(obj, parent) • Supported from EcmaScript 5th edition -> 197

Slide 198

Slide 198 text

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(); // A child.method2(); // A Now new object is created which parent is parent 198

Slide 199

Slide 199 text

Working with Constructors • When writing • function Animal() { } • Two objects are created! • 1) Animal • 2) Animal.prototype • These two objects are linked together! 199

Slide 200

Slide 200 text

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

Slide 201

Slide 201 text

Constructor function and new • Constructor function is used with new – keyword • var spot = new Animal(); • By default the spot inherites Animal.prototype! Animal (Function – Object) Animal Parent prototype constructor spot __proto__ Parent object! 201

Slide 202

Slide 202 text

Testing function Animal() { } var spot = new Animal(); console.log(spot.__proto__ == Animal.prototype); console.log(Object.getPrototypeOf(spot) == Animal.prototype); Non-standard way spot extends Animal.prototype 202

Slide 203

Slide 203 text

203

Slide 204

Slide 204 text

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 and animal3 extend Animal.prototype 204

Slide 205

Slide 205 text

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" EcmaScript 2015 Feature, can be slow. Now Dog.prototype extends Animal.prototype. spot extends Dog.prototype true true 205

Slide 206

Slide 206 text

Animal.prototype Dog.prototype spot1 animal1 spot2 spot3 animal2 206

Slide 207

Slide 207 text

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" Use Object.create(..) instead 207

Slide 208

Slide 208 text

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); Creates a new object! We have a problem ... undefined 208

Slide 209

Slide 209 text

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); Dog Parent spot __proto__ Now spot extends Dog Parent which is accessed by Dog.prototype Dog prototype 209

Slide 210

Slide 210 text

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); This creates a new object! 210

Slide 211

Slide 211 text

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" The newObject here is the new object created! 211

Slide 212

Slide 212 text

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" Dog Parent spot __proto__ Dog prototype newObject __proto__ Animal.prototype 212

Slide 213

Slide 213 text

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" Dog Parent spot __proto__ Dog prototype newObject __proto__ Animal.prototype 213

Slide 214

Slide 214 text

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" Dog Parent spot __proto__ Dog prototype newObject __proto__ Animal.prototype Dog.prototype => newObject newObject.__proto__ => Animal.prototype = true! 214

Slide 215

Slide 215 text

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" Dog Parent spot __proto__ Dog prototype newObject __proto__ Animal.prototype spot__proto => Dog Parent false! 215

Slide 216

Slide 216 text

Let's change order 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" Let's create first the newObject and then create the spot! 216

Slide 217

Slide 217 text

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 Parent Dog prototype 217

Slide 218

Slide 218 text

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 Parent Dog prototype newObject __proto__ Animal.prototype 218

Slide 219

Slide 219 text

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 Parent (garbage collector will delete this) Dog prototype newObject __proto__ Animal.prototype 219

Slide 220

Slide 220 text

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.prototype By default spot will extend Dog.prototype which is now the newObject spot __proto__ 220

Slide 221

Slide 221 text

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 New Dog Parent __proto__ Animal.prototype spot __proto__ We do not need the newObject pointer 221

Slide 222

Slide 222 text

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

Slide 223

Slide 223 text

Animal.prototype Dog.prototype spot1 animal1 spot2 spot3 animal2 223

Slide 224

Slide 224 text

We are not done yet... 224

Slide 225

Slide 225 text

Constructors function Dog() {} var spot = new Dog(); console.log(spot.constructor == Dog); Dog prototype Dog Parent constructor spot __proto__ You can ask from an object what is it's constructor. The constructor property is built in the parent object Two objects are created! The Dog Parent object has a constructor property! 225

Slide 226

Slide 226 text

Constructors function Animal() {} function Dog() {} Dog.prototype = Object.create(Animal.prototype); var spot = new Dog(); console.log(spot.constructor == Dog); Creates a new object which __proto__ points to Animal.protototype. The new object does not have constructor property! 226

Slide 227

Slide 227 text

Dog prototype ( the new object ) __proto__ spot __proto__ Animal prototype Animal Parent constructor console.log(spot.constructor); Constructor property is not found in spot. It will try to find it in the new object. It's not there either! Then it will fetch it from the X and end result is that spot is created from Animal! 227

Slide 228

Slide 228 text

Dog prototype ( the new object ) __proto__ constructor spot __proto__ Animal prototype Animal Parent constructor Dog.prototype.constructor = Dog; Let's add this! 228

Slide 229

Slide 229 text

Done! function Animal() {} function Dog() {} Dog.prototype = Object.create(Animal.prototype); Dog.prototype.constructor = Dog; var spot = new Dog(); 229

Slide 230

Slide 230 text

Invoking Base Constructor 230

Slide 231

Slide 231 text

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); You can invoke the function and define what this means in runtime this now refers to spot-object 231

Slide 232

Slide 232 text

When using Constructor - functions function 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

Slide 233

Slide 233 text

EcmaScript 2015: Classes 233

Slide 234

Slide 234 text

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); A lot nicer syntax for creating inheritance! 234

Slide 235

Slide 235 text

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); But it is syntactical sugar!! 235

Slide 236

Slide 236 text

Let's compile this syntax to older EcmaScript à (Oh Dear....) 236

Slide 237

Slide 237 text

React - Example • React is a JavaScript framework for building UI in front-end • It is developed by Facebook and very popular • You create UI components in the framework • Uses EcmaScript 2015 and JSX • Compiled to older EcmaScript using Babel so it works on browsers class Welcome extends React.Component { render() { return

Hello World

; } } 237

Slide 238

Slide 238 text

EcmaScript 2015 (6th edition) 238

Slide 239

Slide 239 text

New Features • Arrow Functions • Parameter values • Object properties • Modules • Classes • Some new built methods 239

Slide 240

Slide 240 text

Arrow Functions let 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

Slide 241

Slide 241 text

Lexical this var object = { array: [0,1,2,3,4], doIt: function() { this.array.forEach(function(value) { this.array.push(value); }); } } object.doIt(); Cannot read property 'push' of undefined 241

Slide 242

Slide 242 text

Lexical this var object = { array: [0,1,2,3,4], doIt: function() { var _this = this; this.array.forEach(function(value) { _this.array.push(value); }); } } object.doIt(); It works when using closure 242

Slide 243

Slide 243 text

Lexical this var object = { array: [0,1,2,3,4], doIt: function() { this.array.forEach((value) => { this.array.push(value); }); } } object.doIt(); Works! 243

Slide 244

Slide 244 text

Default Parameter values function printIt(text, amount = 1) { for(let i = 0; i < amount; i++) { console.log(text); } } printIt("text"); printIt("text", 7); 244

Slide 245

Slide 245 text

Variadic Parameter Values 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

Slide 246

Slide 246 text

Spread Operator var array1 = [ "hello", "world" ]; var array2 = [ 1, ...array1 ]; // [ 1, 'hello', 'world' ] console.log(array2); 246

Slide 247

Slide 247 text

Interpolation of String var message = "hello"; var html = `

${message}

`; console.log(html); 247

Slide 248

Slide 248 text

Object Properties let x = 0; let y = 1; let obj = { x, y }; console.log(obj.x); console.log(obj.y); 248

Slide 249

Slide 249 text

Modules 249

Slide 250

Slide 250 text

About Modules • Modules Systems 1. AMD Specification (RequireJS) 2. CommonJS Modules (NodeJS) 3. ES2015 official module • In EcmaScript 2105 for the first time it's built into language. Support is weak. • It's possible to compile ES6 Modules to AMD or CommonJS • Node will support ES2015 modules in the upcoming versions • Angular2 Framework uses ES2015 modules 250

Slide 251

Slide 251 text

ES2015 Modules 251

Slide 252

Slide 252 text

Babel • Since ES2015 module support is weak, install Babel transpiler • Transpiler will compile new ES2015 features to older ES that you can use in NodeJS or Browsers • To install globally • npm install -g babel-cli 252

Slide 253

Slide 253 text

EcmaScript 2015: app.js import { generateRandom, sum } from 'utility'; console.log(generateRandom()); // logs a random number console.log(sum(1, 2)); // 3 253

Slide 254

Slide 254 text

EcmaScript 2015: utility.js function generateRandom() { return Math.random(); } function sum(a, b) { return a + b; } export { generateRandom, sum } 254

Slide 255

Slide 255 text

CommonJS 255

Slide 256

Slide 256 text

CommonJS • CommonJS is a project with the goal of specifying ecosystem for JS outside of Browser • Was started by Mozilla engineer, inital name ServerJS • CommonJS described a lot of specifications, including modules • This module specification is implemented in NodeJS • require to include modules • exports to make things available 256

Slide 257

Slide 257 text

app.js // import { generateRandom, sum } from 'utility'; require("./utility.js"); console.log(generateRandom()); // logs a random number console.log(sum(1, 2)); // 3 257

Slide 258

Slide 258 text

utility.js generateRandom = function() { return Math.random(); } sum = function (a, b) { return a + b; } 258

Slide 259

Slide 259 text

Example Module: 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; }; Uses JSdoc 259

Slide 260

Slide 260 text

Example Module 'use strict'; var random = require("./randomModule"); console.log(random(1,10)); 260

Slide 261

Slide 261 text

Exporting Object '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

Slide 262

Slide 262 text

Importing Object 'use strict'; var MyMath = require("./mathModule"); console.log(MyMath.random(1,10)); console.log(MyMath.abs(-7)); 262

Slide 263

Slide 263 text

exports vs module.export 'use strict'; module.exports.variable1 = "hello"; exports.variable2 = "world"; these point to the same object 263

Slide 264

Slide 264 text

exports vs module.exports 'use strict'; var module = { exports: {} }; var exports = module.exports; module.exports.variable1 = "hello"; exports.variable2 = "world"; return module.exports; It will always return module.exports 264

Slide 265

Slide 265 text

What Happens? '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

Slide 266

Slide 266 text

Now Two Different Objects! module.exports exports {name: "jack"} {variable: "hello"} 266

Slide 267

Slide 267 text

Exception Handling 267

Slide 268

Slide 268 text

Example function 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

Slide 269

Slide 269 text

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); } Better version, our own exception object 269

Slide 270

Slide 270 text

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); } Both of the exceptions go here 270

Slide 271

Slide 271 text

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."); } } Checking what exception was thrown 271

Slide 272

Slide 272 text

Unit Testing 272

Slide 273

Slide 273 text

Unit Testing Frameworks • Mocha • Jasmine • Should • NodeUnit • jsUnit 273

Slide 274

Slide 274 text

Mocha • Install globally • npm install –globally mocha • Create test/test.js • You can run tests • mocha test/test.js • Or if you modify package.json • npm test 274

Slide 275

Slide 275 text

MyMath module '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

Slide 276

Slide 276 text

test/test.js var 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

Slide 277

Slide 277 text

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

Slide 278

Slide 278 text

TDD • Design the tests first! • After this implement the module! 278

Slide 279

Slide 279 text

Async and Promises 279

Slide 280

Slide 280 text

About Promises • Promises an alternative to callbacks delivering result of an async computation • Promises are part of EcmaScript 2015 • Previously you could use them as additional library • https://promisesaplus.com/ 280

Slide 281

Slide 281 text

Typical async function with callback asyncFunction(arg1, arg2, result => { console.log(result); }); 281

Slide 282

Slide 282 text

Problems with callbacks • When async done, do another async method (chaining) -> using callbacks can be messy • What is async fails? If you have chained async methods and one of them fails? • It is not standard, everyone can have they own version of doing callbacks 282

Slide 283

Slide 283 text

Using Promises function promiseFunction(resolve, reject) { // time consuming async stuff if(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); You can do both here 283

Slide 284

Slide 284 text

Node.JS callbacks 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'); } } } ); File I/O module 284

Slide 285

Slide 285 text

Node.JS promise 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 SyntaxError console.error('An error occurred', error); }); util.promisify is Node 8 feature 285

Slide 286

Slide 286 text

Simple Example function doSomeTimeConsumingStuff() { function asyncOperation(resolve, reject) { setTimeout(() => resolve("Done"), 1000); } return new Promise(asyncOperation); } doSomeTimeConsumingStuff().then(result => console.log('Result: ' + result)); 286

Slide 287

Slide 287 text

function promiseFunction(resolve, reject) { // time consuming async stuff if(true) { resolve(4); } else { reject("First promise failed!"); } } function onSuccess(result) { let p = new Promise((resolve, reject) => { // time consuming async stuff if(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); Returns promise Chaining with then Can handle both errors! 287

Slide 288

Slide 288 text

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)); When invoking async function, end result is promise! 288

Slide 289

Slide 289 text

EcmaScript 2017: 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)); The doIt – method is run parallel 289

Slide 290

Slide 290 text

EcmaScript 2017: await function 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's wait until we get the number 290