javascript / ecmascript

Vít Jouda,
Dev Center Hradec Králové,

Česká Pojišťovna

O nás

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

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

o vás

jaké programovací jazyky znáte?

jaký je váš vztah k JS?

znáte nějaký JS framework?

jste / je vaším cílem stát se profesionálním programátorem?

jaká programovací paradigmata znáte?

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

ECMAScript 5.1 (2009, 2011)
 

ECMAScript 2015 (ES 6)
 

Devstack (Node.js, Webpack...)
 

React (Facebook UI library)

č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í

Základní charakteristiky

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

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);

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

Jasmine - BDD framework pro JS

může zastávat dokumentaci

Základní datové typy

existuje 5 základních primitiv (ES 5.1)

string, number, boolean, null, undefined

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

cvičení

Vytvořte funkci (např. 'carFactory'), která na zavolání vrátí objekt reprezentující automobil.

Funkce přijímá 2 parametry,  první je vždy název automobilu, druhý je rychlost v km/h. Tyto parametry budou vloženy do objektu automobilu.

Vytvořte funkci, která přijímá N parametrů (jednotlivá vozidla tak, jak je vrací 'carFactory') a vrátí automobil s nejvyšší rychlostí.

Za použití Jasmine BDD vytvořte testy, které otestují správné chování obou metod.

scope a closure

Context (this)

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í #2

Předpokládejte objekt popisující studenta UHK v následujícím tvaru.

{
    name: 'Karel',
    surname: 'Novák',
    faculty: 'FIM',
    age: '21'
}

Vytvořte funkci, která přijímá N argumentů (studentů) a vrací průměrný věk studentů FIM.

Vytvořte funkci, která přijímá pole studentů a vrací pole řetězců ve formátu "${name} ${surname}, ${faculty}".

Funkce otestujte pomocí Jasmine BDD.

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

  1. vytvoří se prázdný objekt, jehož prototyp je nastaven na Foo.prototype
  2. zavolá se funkce Foo s tímto objektem jako kontext ('this')
  3. 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();

Cvičení #3

Pomocí prototypální dědičnosti vymodelujte vztah mezi třídou pro obecný geometrický tvar a třídami pro čtverec a kruh. Každý tvar bude mít proměnnou obsahující souřadnice jeho středu, které je možné zadat pomocí konstruktoru.

Geometrický tvar má metodu, která vrací jeho plochu spočtenou na základě parametrů daného tvaru. Tyto parametry je možno zadat pomocí konstruktoru.

Od každé třídy vytvořte jednu instanci a otestujte její správné chování pomocí JasmineBDD.

Made with Slides.com