Introduction slides for ECMAScript - language. Covers features from ES5, ES2015, ES2016 and ES2017. Focus mainly on CLI - apps (not browser) and core language.
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
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
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
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
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
• 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
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
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
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
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
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
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
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
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
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
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
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
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
function, available everywhere • Local variable • Declare variable inside of function, available in that function • Before ES2015, no block statement! 54
= "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
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
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
'' 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
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
= 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
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
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
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
"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
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
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
• 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
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
"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
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
=== 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
{ 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
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
• 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
{ 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
{ 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
"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
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
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
= 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
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
= 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
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
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
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
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
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
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
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
"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
/.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
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
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
used! • To get the parent, use • Object.getPrototypeOf(child) • To set the parent, use (Only in EcmaScript 2015!) • Object.setPrototypeOf(child, parent) 195
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
} 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
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
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
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
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
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
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
== 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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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