ECMAScript 2015 (ES6)

Nova verzija JavaScript-a

Autor: Miroslav Popovic / @miroslavpopovic
Fork me / English version

Malo istorije

  • Brendan Eich, Netscape
  • LiveScript, 1994
  • ECMA standardizacija, 1996
  • ECMAScript 3, 1999
  • ECMAScript 4, obustavljen razvoj
  • ECMAScript 5, 2009
  • ECMAScript 5.1, 2011
  • ECMAScript 6 (Harmony, ES6, ES 2015), 2015
  • ECMAScript 7, budućnost

Block scope

ES5

                                    
function test() {
  var x = 1;
  var y = 2;

  {
    var x = 10;
    var y = 20;
  }

  console.log(x, y);
}
test();
                                    
                                

ES6

                                    
function test() {
  let x = 1;
  let y = 2;

  {
    let x = 10;
    let y = 20;
  }

  console.log(x, y);
}
test();
                                    
                                

let i const

  • let - definisanje varijabli što bliže mjestu korištenja
  • const - konstanta, nije je moguće mijenjati
                            
function test() {
  const PI = 3.141569;

  // PI = 6; -> GREŠKA

  console.log(PI);
}
                            
                        

Funkcije: default parametri

ES5

                                    
function logName(name) {
  name = name || 'Unknown';
  console.log('Name: ', name);
}

logName();
logName('JavaScript');
                                    
                                

ES6

                                    
function logName(name='Unknown') {
  console.log('Name: ', name);
}

logName();
logName('JavaScript');

//function f(x=Math.random()){...};
                                    
                                

Funkcije: rest parametri

ES5

                                    
function add(x) {
  var result = x;

  // arguments.forEach(...)
  for (var i = 1;
      i < arguments.length; i++) {
    result += arguments[i];
  }

  return result;
}

console.log(add(1, 2, 3, 4, 5));
                                    
                                

ES6

                                    
function add(x, ...numbers) {
  var result = x;

  numbers.forEach(function(y) {
    result += y;
  });

  return result;
}

console.log(add(1, 2, 3, 4, 5));
                                    
                                

spread operator

ES5

                                    
function add(x, y, z) {
  return x + y + z;
}

var numbers = [2, 4, 6];

console.log(
  add.apply(null, numbers));
                                    
                                

ES6

                                    
function add(x, y, z) {
  return x + y + z;
}

let numbers = [2, 4, 6];

console.log(add(...numbers));

// Primjer 2
let n2 =
  [1, 2, ...numbers, 7, ...[2, 3]];
console.log(n2);
// [1, 2, 2, 4, 6, 7, 2, 3]
                                    
                                

Destructuring

                            
let numbers = [10, 20];
let [a, b] = numbers;

console.log(a, b);

let position = { lat: 42.34455, lng: 17.34235 };
let {lat, lng} = position;

console.log(lat, lng);
                            
                        

Destructuring

kompleksni objekti

                            
let book = {
  title: 'Lord of the Rings',
  author: 'J.R.R. Tolkien',
  pages: 550,
  tags: ['fantasy', 'fiction'],
  price: {
    hardcover: 34.5,
    softcover: 22.5
  }
};

let {author, tags: [,tag], price: {softcover}} = book;

console.log(author, tag, softcover);
                            
                        

Destructuring

parametri funkcije

                            
let httpPost = function(url, {
    cache = true,
    contentType = 'application/json',
    timeout = 2500,
    headers = {}
  }) {
  console.log(url, cache, contentType, timeout, headers);
};

httpPost('http://google.com', {
  cache: false,
  headers: {
    Authorization: 'Bearer SOMETOKEN'
  }
});
                            
                        

Template strings

ES5

                                    
var firstName = 'Miroslav',
    lastName = 'Popovic';
var fullName =
    firstName + ' ' + lastName;

console.log(fullName);

var add = function(x, y) {
  return x + ' + ' + y +
    ' = ' + (x+y);
};

console.log(add(10, 5));
console.log('Više linija\n' +
    'sa plus operatorom');
                                    
                                

ES6

                                    
let firstName = 'Miroslav',
    lastName = 'Popovic';
let fullName =
    `${firstName} ${lastName}`;

console.log(fullName);

let add = function(x, y) {
  return `${x} + ${y} = ${x+y}`;
};

console.log(add(10, 5));
console.log(`Podrška
    za više linija sa backticks`);
                                    
                                

Prošireni object literals

                            
var obj = {
    // definisanje prototipa prilikom kreiranja objekta
    __proto__: theProtoObj,

    // prečica za ‘handler: handler’
    handler,

    // prečica za metode - 'toString: function() {}'
    toString() {
     // poziv metoda osnovne klase sa 'super'
     return 'd ' + super.toString();
    },

    // dinamička imena property-a
    [ 'prop_' + (() => 42)() ]: 42
};
                            
                        

Arrows

ES5

                                    
var square = function(x) {
  return x * x;
};
var add = function(x, y) {
  return x + y;
};
var total = function() {
  return square(add(5, 3));
};

console.log('5 * 5 = ', square(5));
console.log('2 + 3 = ', add(2, 3));
console.log(
  '(5 + 3)*(5 + 3) = ', total());
                                    
                                

ES6

                                    
let square = x => x * x;
let add = (x, y) => x + y;
let total = () => square(add(5,3));

console.log('5 * 5 = ', square(5));
console.log('2 + 3 = ', add(2, 3));
console.log(
  '(5 + 3)*(5 + 3) = ', total());
                                    
                                

Multiline arrows

ES5

                                    
var add = function(x, y) {
  var result = x + y;
  return result;
};

console.log('2 + 3 = ', add(2, 3));
                                    
                                

ES6

                                    
let add = (x, y) => {
  let result = x + y;
  return result;
};

console.log('2 + 3 = ', add(2, 3));
                                    
                                

this

ES5

                                    
var obj = {
  index: 1,

  loadData: function() {
    var self = this;

   $.get('http://ip.jsontest.com')
      .then(function(data) {
        console.log(
          'IP: ' + data.ip,
          'Index: ' + self.index)
      });
  }
};

obj.loadData();
                                    
                                

ES6

                                    
let obj = {
  index: 1,

  loadData: function() {
   $.get('http://ip.jsontest.com')
      .then((data) => {
        console.log(
          'IP: ' + data.ip,
          'Index: ' + this.index)
      });
  }
};

obj.loadData();
                                    
                                

Promises

                        
function timeout(duration = 0) {
    return new Promise((resolve, reject) => {
        setTimeout(resolve, duration);
    });
}

var p = timeout(1000).then(() => {
    return timeout(2000);
}).then(() => {
    throw new Error("hmm");
}).catch(err => {
    return Promise.all([timeout(100), timeout(200)]);
});

                        
                    

Klase

ES5

                                    
function Car(data) {
  this.model = data.model;
  this.year = data.year;
  this.wheels = data.wheels || 4;
}

Car.prototype.drive = function() {
  console.log(
    'Driving ' + this.model);
}

var yugo = new Car({
  model: 'Yugo 55', year: 1985 });

yugo.drive();
                                    
                                

ES6

                                    
class Car {
  constructor (data) {
    this.model = data.model;
    this.year = data.year;
    this.wheels = data.wheels || 4;
  }

  drive() {
    console.log(
      'Driving ' + this.model);
  }
}

let yugo = new Car({
  model: 'Yugo 55', year: 1985 });
yugo.drive();
                                    
                                

Properties

                            
class Car {
  constructor ({model, year, wheels=4}) {
    this.model = model; this.year = year; this.wheels = wheels;
  }

  get isNew() { return this._isNew; }
  set isNew(value) { this._isNew = value; }

  drive() {
    console.log(`Driving ${this.model}`); this.isNew = false;
  }
}
let yugo = new Car({ model: 'Yugo 55', year: 1985 });

yugo.drive();
console.log(yugo.isNew);
                            
                        

Naslijeđivanje

                            
class Car { ... }

class Truck extends Car {
  constructor ({model, year, wheels=6}) {
    super({model, year, wheels});
  }

  drive () {
    super.drive();
    console.log(`Driving like a boss with ${this.wheels} wheels`);
  }
}

let actros = new Truck({ model: 'Actros', year: 2005 });
actros.drive();
                            
                        
  • Napomena: koristite kompoziciju umjesto nasleđivanja (favor composition over inheritance).

Statički metodi

ES5

                                
function Car(data) {
  // ...
}

Car.drive = function(data) {
  console.log('Driving...');
}

//var yugo = new Car({
// model: 'Yugo 55', year: 1985 });
//yugo.drive();

Car.drive({ road: 'autobahn' });
                                
                            

ES6

                                
class Car {
  // ...
  static drive(data) {
    console.log('Driving...');
  }
}

//let yugo = new Car({
// model: 'Yugo 55', year: 1985 });
//yugo.drive();

Car.drive({ road: 'autobahn' });
                                
                            

Moduli

                            
// lib/math.js
export function sum(x, y) {
  return x + y;
}
export var pi = 3.141593;

// app.js
import * as math from "lib/math";
alert("2π = " + math.sum(math.pi, math.pi));

// otherApp.js
import {sum, pi} from "lib/math";
alert("2π = " + sum(pi, pi));

                            
                        

Module loader

                            
System.import('some_module')
    .then(some_module => {
      // Use some_module
    })
    .catch(error => {
      //...
    });
                            
                        
  • System je default loader
  • Kofigurabilan je
  • Može da radi sa AMD ili CommonJS modulima

Ostalo

  • tagged templates
    upper`${firstName} ${lastName}`
  • podrška za cijeli Unicode
  • binarni i oktalni literali - 0b111110111, 0o767 = 503
  • tail calls - rekurzivne funkcije ne izazivaju Stack Overflow grešku
  • Proširenje osnovne biblioteke
    Math, Array, Object, Number, String

Ostalo (nastavak)

  • Set, WeakSet, Map, WeakMap - data strukture
  • simboli - unikatne, nepromjenljive vrijednosti, mogu se koristiti kao property identifikatori
  • iteratori i for..of petlja
  • generatori
    let n = function*() { yield 1; yield 2; }
  • Proxy objekti

ECMAScript 2015 danas

Kompajleri (transpilers)

  • Traceur - prvi JS.next kompajler koji je kreirao Google
  • koristi ga Angular tim
  • podržava i proširenja, kao npr. AtScript podrška za Angular
  • Babel.js (6to5) - najbolji kompajler danas
  • koristi ga Aurelia tim
  • ...

Module loaders

  • ES6 Module Loader - polyfill
  • SystemJS - univerzalni module loader
    • ES6, AMD, CommonJS, globals
    • radi i sa Traceur i Babel.js
    • osnova za jspm package manager
  • ...

Razvojni alati

Frameworks / languages

Budućnost

Linkovi

Hvala!

Pitanja?