Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Introduction to ECMAScript

Introduction to ECMAScript

Introduction slides for ECMAScript - language. Covers features from ES5, ES2015, ES2016 and ES2017. Focus mainly on CLI - apps (not browser) and core language.

Avatar for Jussi Pohjolainen

Jussi Pohjolainen

September 20, 2017
Tweet

More Decks by Jussi Pohjolainen

Other Decks in Technology

Transcript

  1. 2

  2. 3

  3. Recommended Reading • Recommended reading • JavaScript: The Good Parts

    by Douglas Crockford • JavaScript: The Definite Guide by David Flanagan • JavaScript Patterns: Stoyan Stefanov • And Google.. 4
  4. 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) 5
  5. 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 7
  6. 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 8
  7. 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 9
  8. 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 10
  9. 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 11
  10. 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 13
  11. 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 14
  12. Learning Path for Front-end Core EcmaScript Browser Host Objects JavaScript

    in Front-end HTML5 CSS Static Web-pages JavaScript Frameworks: React, Angular2+, ... 15
  13. 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 2018 9 ES2018 rest/spread operator, Promise.finally, regExp 2019 10 ES2019 Array.flat, flatMap, Object.fromEntries ES.Next 16 2012 typescript
  14. 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 17
  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); Notice that compiler compiles typescript to javascript and it loses the string type because that is not part of js! 18
  16. 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'. 19
  17. 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 21
  18. 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 • ... 22
  19. 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/ 23
  20. 25

  21. 26

  22. 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 • ... 27
  23. 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 29
  24. ESLint • ESLint is linting utility (code quality) tool for

    JavaScript • To install and run • npm init @eslint/config@latest • ESLint requires a configuration file • You can answer to questions about style guide or take popular style guides 38
  25. Modify ESLint import globals from "globals"; import pluginJs from "@eslint/js";

    !!/** @type {import('eslint').Linter.Config[]} !*/ export default [ { files: ["**/*.js"], languageOptions: { sourceType: "commonjs", globals: globals.node, !// Moved inside the same object }, rules: { "no-var": "error", !// Disallow use of var eqeqeq: "error", !// Require strict equality (!!===) "no-unused-vars": "warn", !// Warn on unused variables "prefer-const": "error", !// Prefer const over let where possible "no-else-return": "error", !// Disallow return before else curly: "error", !// Enforce consistent brace style "no-multiple-empty-lines": ["error", { max: 1 }], !// Limit multiple empty lines camelcase: "error", !// Enforce camelCase naming "no-eval": "error", !// Disallow eval() }, }, pluginJs.configs.recommended, ]; 41
  26. Prettier • Let's fix style also • npm install !--save-dev

    prettier eslint-config- prettier eslint-plugin-prettier • prettier • Code Formatter • eslint-config-prettier • configuration that disables ESLint rules that might conflict with Prettier • eslint-plugin-prettier • turns Prettier rules into ESLint rules • 43
  27. Modify ESLint import globals from "globals"; import pluginJs from "@eslint/js";

    import prettierPlugin from "eslint-plugin-prettier"; import prettierConfig from "eslint-config-prettier"; export default [ { files: ["**/*.js"], languageOptions: { sourceType: "commonjs", globals: globals.node, }, plugins: { prettier: prettierPlugin, }, rules: { !// ESLint rules "no-var": "error", !// Disallow use of var eqeqeq: "error", !// Require strict equality (!!===) "no-unused-vars": "warn", !// Warn on unused variables "prefer-const": "error", !// Prefer const over let where possible "no-else-return": "error", !// Disallow return before else curly: "error", !// Enforce consistent brace style "no-multiple-empty-lines": ["error", { max: 1 }], !// Limit multiple empty lines camelcase: "error", !// Enforce camelCase naming "no-eval": "error", !// Disallow eval() !// Prettier rule integration "prettier/prettier": "error", }, }, pluginJs.configs.recommended, prettierConfig, ]; 44
  28. 45

  29. 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
  30. 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
  31. About semicolons • You can write • console.log("hello"); • console.log("world");

    • Or • console.log("hello") • console.log("world") 51
  32. Comments // One line /* multi- line */ /* No

    nested /* comments */ allowed */ 52
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. ES2015: const • Constant cannot be changed through assignment •

    const variables are not hoisted const PI = 3.14; PI = 99; console.log(PI); 60
  40. ES2015 -> ES5 Object.defineProperty(typeof global === "object" ? global :

    window, "PI", { value: 3.141593, enumerable: true, writable: false, configurable: false }) console.log(PI); 61
  41. 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
  42. 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
  43. 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
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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
  49. Conditional Statements if (condition_1) { statement_1; } else if (condition_2)

    { statement_2; } else if (condition_n) { statement_n; } else { statement_last; } 72
  50. False Values 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
  51. Comparison: true or false? let x = new Boolean(false); if(x)

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

    == false) { console.log("true"); } else { console.log("false"); } 75
  53. 77

  54. 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
  55. 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
  56. switch case switch (expression) { case label_1: statements_1 [break;] case

    label_2: statements_2 [break;] ... default: statements_def [break;] } 80
  57. for for(let i = 0; i < 10; i =

    i + 1) { console.log(i); } 83
  58. 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
  59. 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
  60. 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
  61. for ... in – for objects let object = {"key1":

    "value1", "key2": "value2"}; for(let key in object) { console.log(key); console.log(object[key]) } 87
  62. 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
  63. 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
  64. 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
  65. Some String methods • charAt • startsWith • endsWith •

    split • slice • substring • match • replace • toLowerCase • toUpperCase • trim 94
  66. 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
  67. 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
  68. Creating an Array with given size const ARRAY_LENGTH = 10;

    let arr1 = new Array(ARRAY_LENGTH); // OR let arr2 = []; arr2.length = ARRAY_LENGTH; 99
  69. 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
  70. .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
  71. forEach (EcmaScript 5th Edition) let colors = ['red', 'green', 'blue'];

    colors.forEach(function(color) { console.log(color); }); 103
  72. Array Methods • concat() • join() • push() • pop()

    • shift() • unshift() • slice() • splice() • reverse() • sort() • indexOf() • forEach() • map() • filter() • every() • some() • reduce() 104
  73. 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
  74. 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
  75. 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
  76. 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
  77. Functions • Fundamental building block in EcmaScript • Set of

    statements that performs a task or calculates a value • Functions are objects! 112
  78. Predefined Argument function multiply(a, b = 1) { return a

    * b; } console.log(multiply(5)); 116
  79. 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
  80. 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
  81. 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
  82. 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
  83. 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
  84. Anonymous Function greeting("hello world"); var greeting = function (msg) {

    console.log(msg); } Anonymous function declaration 123
  85. 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
  86. 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
  87. 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
  88. 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
  89. Function that returns a Function function doIt() { function hello()

    { console.log("Hello World"); } return hello; } var func = doIt(); func(); 130
  90. 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
  91. 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
  92. 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
  93. 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
  94. 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
  95. 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
  96. Object Constructor let object = new Object(); object.key = "value";

    object.hello = "world"; object["2"] = "another"; Possibility to add properties in runtime 139
  97. 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
  98. 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
  99. 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
  100. 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
  101. 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
  102. 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
  103. What happens here? function Person(name) { this.name = name; }

    var tina = Person("Tina"); console.log(name) Forgot to use the new word! 148
  104. 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
  105. 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
  106. 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
  107. 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
  108. Usage of Arrow Function and Ternary Operation let MyMath =

    { abs: (value) => value < 0 ? value * -1 : value }; console.log ( MyMath.abs(-7) ); 153
  109. Enumerating: for...in var object = {key1: "value1", key2: "value2"}; for

    (var key in object) { console.log(key + " = " + object[key]); } 154
  110. 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
  111. 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
  112. 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
  113. 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
  114. 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
  115. 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
  116. 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("<html>...</html>"); } obj.fetchUrl(); this? NOT working! 164
  117. 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("<html>...</html>"); } obj.fetchUrl(); this? NOT working! 165
  118. 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("<html>...</html>"); } obj.fetchUrl(); Send a copy of that function! 166
  119. 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("<html>...</html>"); } obj.fetchUrl(); It works! 167
  120. 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("<html>...</html>"); } obj.fetchUrl(); It works! Lexical this 168
  121. 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
  122. 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
  123. In functions: use strict function doIt() { "use strict"; console.log("This

    is under strict mode"); } Now only this function uses strict mode 175
  124. Variable without var function doIt() { variable = 4; }

    doIt(); console.log(variable); Forgot the var word here... it creates a global variable! Confusing 177
  125. In strict mode, you have to use the var "use

    strict"; function doIt() { variable = 4; } doIt(); console.log(variable); variable is not defined! 178
  126. 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
  127. 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
  128. 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
  129. 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
  130. 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
  131. 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
  132. 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
  133. RegExp exec vs test var regex = /hello/; // [

    '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
  134. 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
  135. Example of Flags var regex1 = /hello/i; var regex2 =

    new RegExp("hello", "i"); console.log( regex1.test("HelLo") ); console.log( regex2.test("HelLo") ); 189
  136. 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
  137. Object extends Object • In EcmaScript object extends other object

    • Every object has special __proto__ property that links to object that it inherites 193
  138. (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
  139. __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
  140. 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
  141. 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
  142. 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(); // B Now new object is created which parent is parent 198
  143. Working with Constructors • When writing • function Animal() {

    } • Two objects are created! • 1) Animal • 2) Animal.prototype • These two objects are linked together! 199
  144. 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
  145. 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
  146. 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
  147. 203

  148. 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
  149. 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
  150. 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
  151. 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
  152. 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
  153. 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
  154. 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" The newObject here is the new object created! 211
  155. 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
  156. 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
  157. 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
  158. 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
  159. 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
  160. 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
  161. 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
  162. 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
  163. 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
  164. 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
  165. 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
  166. 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
  167. Constructors function Animal() {} function Dog() {} Dog.prototype = Object.create(Animal.prototype);

    var spot = new Dog(); console.log(spot.constructor); Creates a new object which __proto__ points to Animal.protototype. The new object does not have constructor property! 226
  168. 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
  169. Dog prototype ( the new object ) __proto__ constructor spot

    __proto__ Animal prototype Animal Parent constructor Dog.prototype.constructor = Dog; Let's add this! 228
  170. 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
  171. 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
  172. 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
  173. 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
  174. 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 <h1>Hello World</h1>; } } 237
  175. New Features • Arrow Functions • Parameter values • Object

    properties • Modules • Classes • Some new built methods 239
  176. 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
  177. 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
  178. 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
  179. Lexical this var object = { array: [0,1,2,3,4], doIt: function()

    { this.array.forEach((value) => { this.array.push(value); }); } } object.doIt(); Works! 243
  180. Default Parameter values function printIt(text, amount = 1) { for(let

    i = 0; i < amount; i++) { console.log(text); } } printIt("text"); printIt("text", 7); 244
  181. 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
  182. Spread Operator var array1 = [ "hello", "world" ]; var

    array2 = [ 1, ...array1 ]; // [ 1, 'hello', 'world' ] console.log(array2); 246
  183. Interpolation of String var message = "hello"; var html =

    ` <div> <p>${message}</p> </div> `; console.log(html); 247
  184. Object Properties let x = 0; let y = 1;

    let obj = { x, y }; console.log(obj.x); console.log(obj.y); 248
  185. 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
  186. 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
  187. EcmaScript 2015: app.js import { generateRandom, sum } from 'utility';

    console.log(generateRandom()); // logs a random number console.log(sum(1, 2)); // 3 253
  188. EcmaScript 2015: utility.js function generateRandom() { return Math.random(); } function

    sum(a, b) { return a + b; } export { generateRandom, sum } 254
  189. 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
  190. app.js // import { generateRandom, sum } from 'utility'; require("./utility.js");

    console.log(generateRandom()); // logs a random number console.log(sum(1, 2)); // 3 257
  191. 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
  192. 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
  193. exports vs module.exports 'use strict'; var module = { exports:

    {} }; var exports = module.exports; console.log(module.exports) console.log(exports) exports.variable2 = "world"; return module.exports; It will always return module.exports 264
  194. 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
  195. 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
  196. 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
  197. 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
  198. 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
  199. 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
  200. 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
  201. 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
  202. 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
  203. Async vs Sync • When you execute something synchronously, you

    wait for it to finish before moving on to another task • var result = database.query("SELECT * FROM table"); • console.log("Hello World"); • When you execute something asynchronously, you can move on to another task before it finishes. • database.query("SELECT * FROM table", function(rows) { var result = rows; }); • console.log("Hello World"); • Usually when you implement something asynchronously you use threads 280
  204. Node.js and Threads • Node.js has a cross-platform library that

    abstracts apis/syscalls for asynchronous (non-blocking) input/output • So the modules you use in Node.js tend to be asynchronous • They do not block the main thread • function(parameters, callback) • When async module has done it's job, it calls the callback function • Control is returned to event loop • The loop decides which function was scheduled for execution 281
  205. Node.js and Threads • Node.js uses an • event-driven •

    non-blocking I/O • Your code runs in single thread! • "everything runs in parallel except your code" • Node is designed that your code does not run in parallel • But it is possible to create "child processes" • child_process.fork() • But for know, let's not concentrate on how to build async behaviour, let's see how to use them! 282
  206. 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/ 283
  207. 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 285
  208. 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 286
  209. 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 287
  210. 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 288
  211. Simple Example function doSomeTimeConsumingStuff() { function asyncOperation(resolve, reject) { setTimeout(()

    => resolve("Done"), 1000); } return new Promise(asyncOperation); } doSomeTimeConsumingStuff().then(result => console.log('Result: ' + result)); 289
  212. 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! 290
  213. 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! 291
  214. 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 292
  215. 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 293