
javascript / ecmascript
Vít Jouda,
Dev Center Hradec Králové,
Česká Pojišťovna

O DCHK
vývojové centrum ČP v HK (od r. cca 2003)
vývoj interních aplikací, webů, zahraniční projekty
nový framework založený na moderních technologiích
Java 8, Spring Boot, Gradle, React, Redux, Webpack, Babel, Ramda...
SOAP a REST WS, Webové aplikace, portál pro sjednání pojištění, systém správy pohledávek...
mladý kolektiv programátorů se zaměřením na adaptaci nových technologií a metodiky vývoje

JavaScript vs. ECMAScript?
JavaScript - představen spol. Sun Microsystems v r. 1995
součást prohlížeče Netscape
ECMAScript - standardizovaná verze napříč výrobci, první verze v r. 1997
Následovaly dialekty různých výrobců, např. JScript (MS, IE 3.0)
European Computer Manufacturers Association

Témata
Webová aplikace, SPA
ECMAScript 6+
Devstack (Node.js, Webpack...)
React (Facebook UI library)
Model management (Redux)
Webová aplikace
Definice
Technologie

Evoluce webových aplikací
(z pohledu DCHK)
JSP scriptlet - mix UI a aplikační logiky
Java Server Faces - komponentní FW
Spring MVC, JSPX, jQuery, Mustache.js
Spring (portlet) MVC, Angular 1.#, semi SPA
Spring Boot, React - Redux SPA, REST
Stavební bloky moderní spa
Package manager (NPM, Yarn, ...)
Transpiler (Babel, ...)
Module bundler (Webpack, Browserify, Rollup, ...)
Application FW / view layer (React, AngularJS, Vue, Ember, ...)
Model management (Redux, Flux, RxJS, ...)
CSS management (JSS, CSS modules, Sass...)
Test FW (Jest, Jasmine, Mocha, ...)

Základní charakteristiky ES
dynamicky typovaný
imperativní s deklarativními prvky
multi-paradigm
(skoro) vše je objekt
single-thread (event loop)
asynchronní (callback, Promise)
pass by value
prototypální, funkcionální, OOP

časté omyly
JS je pouze FE záležitost
JS je pomalý
s JS se nesetkám při vývoji BE aplikací
JS není modulární

Testování JS kódu
Test-Driven Development
Behaviour-Driven development
metodika vývoje SW iterační metodou založená na neprocházejících testech
metodika testování založená na specifikaci chování aplikačního kódu
Jest - BDD framework pro JS (Jasmine)
může zastávat dokumentaci

Základní konstrukce jazyka
//variable declaration
var a;
//variable definition
var b = 10;
//variable definitions can be chained
var myStr = 'abc', myNumber = 1;
//object creation
var car = new Object();
car.speed = 180;
car.color = 'blue';
//with object literal
var secondCar = {
speed: 200,
color: 'red'
};
//object properties have descriptors
Object.defineProperty(secondCar , 'type', {
enumerable: false,
get: function() {
return this._type;
},
set: function(value) {
console.log(value);
this._type = value;
}
});
secondCar.type = 'roadster';
//funtion statement, evaluated when VM resolves file
function add(a, b){
return a + b;
}
//function expression, evaluated at runtime
var add = function(a, b){
return a + b;
};
//functions are ALSO objects with operator()
add.param = 'some parameter';
//function cannot have overloaded parameters
function add(a, b){};
//ERROR - redefinition
function add(a, b, c){};
//function has implicit arguments[] parameter
function add(){
return arguments[0] + arguments[1];
};
//function can return another function
function curriedAdd(a){
return function(b) {
return a + b;
};
}
//function can also be passed as a parameter
function callMyName(getMyName){
alert(getMyName());
}
callMyName(function(){
return 'Mr. Mock';
})
//any variable can hold function
var car = {
vendor: 'Audi',
makeSound: function(){
alert('sound');
}
}
car.makeSound();
porovnání hodnot v js
Speciální operátory
typeof - vrací základní typ proměnné
instanceof - testuje přítomnost konstruktoru v prototypálním řetězci proměnné

logické hodnoty a operátory
rozlišujeme tzv. truthy a falsy hodnoty
hodnota proměnné v booleanovském kontextu (podmínky, kontruktor new Boolean(), logické operátory)
logické operátory || a && mají návratovou hodnotu
var falsyValue = 0, truthyValue = 'truthy';
var truthy = falsyValue || truthyValue;
var falsy = falsyValue && truthyValu;lze použít pro defaultování hodnot (use with caution)

trik pro převod mezi truthy a falsy hodnotami na boolean
var falsyValue = '';
var booleanValue = !!falsyValue;
alert(typeof booleanValue);
Základní datové typy
existuje několik základních primitiv
string, number, boolean, null, undefined, symbol
všechna primitiva jsou immutable
vyjma null a undefined má každé primitivum svůj wrapper
String, Number, Boolean - vulueOf() vrací obalené primitivum
všechna čísla jsou 64b floating-point

pole a deklarativní prvky
//define array
var arrayObject = new Array();
var arrayLiteral = [];
//add to the end of an array
arrayLiteral.push('value');
//remove from the end of an array
var lastElement = arrayLiteral.pop();
//add to the beginning of an array
arrayLiteral.unshift('value');
//remove from the beginning of an array
var firstElement = arrayLiteral.shift();
//shallow copy array
var shallowCopy = iterableArray.slice();
iterableArray.pop();
alert(shallowCopy.length);
//iterate over array
var iterableArray = [0, 1, 2];
for(var i = 0; i < iterableArray.length; i++){
alert(iterableArray[i]);
}
//remove multiple elements from array
var toRemoveFrom = [0, 1, 2];
alert(toRemoveFrom.splice(1, 2));
alert(toRemoveFrom);
//iteration
var colors = ['red', 'green'];
colors.forEach(function(color){
alert(color);
})
//filter
var filteredColors = colors.filter(function(color){
return color === 'red';
})
//map
var mappedColors = colors.map(function(color){
return {
color: color
};
})
//reduce
var allColors = colors.reduce(function(acc, next){
return acc + next;
})
var numbers = [0, 1, 2, 3];
var oddNumbersSum = numbers
.filter(function(number){
return number % 2 === 1;
})
.reduce(function(acc, next){
return acc + next;
});
alert(oddNumbersSum);
Ne všechno je "pole"
existují array-like objekty
arguments[], DOM-method result
lze převést na Array
Array.prototype.slice.call(arguments);
cvičení
Vytvořte funkci (např. 'carFactory'), která na zavolání vrátí objekt reprezentující automobil.
Funkce přijímá 2 parametry - název automobilu a rychlost v km/h. Tyto parametry budou vloženy do objektu automobilu spolu s atributem id: integer, který bude inkrementační (obdobně jako v relační DB).
Vytvořte funkci, která přijímá N parametrů (jednotlivá vozidla tak, jak je vrací 'carFactory') a vrátí id automobilu s nejvyšší rychlostí.
Kód otestuje pomocí Jest BDD (min. 2 testy).

scope a closure

Context (this)
Prototypální dědičnost
každý objekt má svůj prototype
prototype je obyčejný JS objekt
výchozí prototyp je Object.prototype
prototypy objektu tvoří tzv. "prototype chain"
při přístupu k atributu je tento řetězec prohledáván odspoda nahoru
v devtools viditelný jako '__proto__'
protypální řetezec je vytvořen pomocí
operátoru 'new' při volání konstruktoru
metody Object.create()

konstruktor
obyčejná JS funkce, dle kovnvence začíná velkým písmenem
volá se přes operátor 'new'
za předpokladu volání 'new Foo()' se provedou následující operace
- vytvoří se prázdný objekt, jehož prototyp je nastaven na Foo.prototype
- zavolá se funkce Foo s tímto objektem jako kontext ('this')
- návratová hodnota této funkce je vrácena jako výsledek volání operátoru new (implicitně je vrácen objekt z bodu 1)

Object.create()
vytvoří nový objekt s prototypem nastaveným na první parametr
na rozdíl od 'new' nevolá žádný konstruktor
může vytvořit objekt bez prototypu - Object.create(null)

// samsungPhone
{
systemVersion: '6.1',
__proto__: phone
}
// phone
{
displayType: 'AMOLED',
cpu: {
model: 'Snapdragon 821',
cores: 8
},
__proto__: Object.prototype
}
// Object.prototype
{
...
}
var phone = {
displayType: 'AMOLED',
cpu: {
model: 'Snapdragon 821',
cores: 8
}
};
function SamsungPhone(){
this.systemVersion = '3.0';
}
SamsungPhone.prototype = phone;
var samsungPhone = new SamsungPhone();

OOP s využitím prototypální dědičnosti
function Animal(name) {
this.name = name;
}
Animal.prototype.sayYourName = function() {
console.log(this.name);
}
//older approach
function Doge(name) {
Animal.call(this, name);
}
Doge.prototype = new Animal();
Doge.constructor = Doge;
Doge.prototype.makeSound = function() {
console.log('Bark!')
}
var rex = new Doge('Rex');
//newer approach using object.create()
function Cate(name) {
Animal.call(this, name);
}
Cate.prototype = Object.create(Animal.prototype);
Cate.constructor = Cate;
Cate.prototype.makeSound = function() {
console.log('Moew!')
}
var garfield = new Cate('Garfield');
rex.sayYourName();
rex.makeSound();
console.log('-------')
garfield.sayYourName();
garfield.makeSound();
Promise
| sync | async | |
|---|---|---|
| single value | ||
| multi-value |
Result foo()
List<Result> foo()
Future<Result> foo()
src.subscribe(observer)

ES2015 promise
var promise = new Promise((resolve, reject) => {
resolve(1);
});
promise
.then((value) => {
console.log(value);
return value + 5;
})
.then(value => {
console.log(value);
});
var errPromise = new Promise((resolve, reject) => {
reject('Error');
});
errPromise
.then((value) => console.log('You should not see this message'))
.catch((err) => console.log(err));

callback hell
//example using fake API
function send(URL, data, onDone = function(responseData){}){};
send(calculateContract, formData, function(calculatedData ){
send(saveToDB, calculatedData function(savedData){
send(print, savedData, function(){
console.log('Contract printed');
});
});
});
//same example using ES2015 Promise
send(calculateContract, formData)
.then(function(calculatedData ){
return send(saveToDB, calculatedData );
})
.then(function(savedData){
return send(print, savedData);
})
.then(function(){
console.log('Contract printed');
})
.catch(function(err){
//handle error
console.log(err);
});
//...and with arrow functions
send(calculateContract, formData)
.then((calculatedData) => send(saveToDB, calculatedData))
.then((savedData) => send(print, savedData))
.then(() => console.log('Contract printed'))
.catch((err) => console.log(err));
třídy
pouze syntactic sugar nad existující prototypální dědičností
es2017 (babel stage-0)

Rest, spread, destructuring

cvičení #2
ES FIM 2018
By Vít Jouda
ES FIM 2018
ECMAscript FIM presentation 2018
- 152