ECMAScript 6

http://mbranko.github.io/webkurs

Ovo je deo web kursa

Literatura

Sadržaj

  1. Strelica
  2. Klase
  3. Objektni literali
  4. Template stringovi
  5. Destrukturiranje
  6. Default + Rest + Spread
  7. Let + Const
  8. Iterators + For..Of
  9. Generators
  1. Unicode
  2. Modules
  3. Module Loaders
  4. Map + Set + WeakMap + WeakSet
  5. Proxies
  6. Symbols
  7. Promises
  8. Reflect API
  9. Tail Calls

#1: strelice

Strelice =>

  • skraćena sintaksa za funkcije
  • slično kao C#, Java 8, CoffeeScript
  • telo funkcije kao izraz ili kao blok naredbi
  • za razliku od funkcije, deli this sa kodom koji je okružuje

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Strelice =>


// Expression bodies
var odds = evens.map(v => v + 1);
var nums = evens.map((v, i) => v + i);
var pairs = evens.map(v => ({even: v, odd: v + 1}));

// Statement bodies
nums.forEach(v => {
  if (v % 5 === 0)
    fives.push(v);
});

// Lexical this
var bob = {
  _name: "Bob",
  _friends: [],
  printFriends() {
    this._friends.forEach(f =>
      console.log(this._name + " knows " + f));
  }
}            
          

#2: klase

Klase

  • sintaksni šećer za prototipsko nasleđivanje
  • jednostavnije za korišćenje
  • olakšava interoperabilnost
  • konstruktori, metode, statičke metode, nasleđivanje, super

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Classes

Klase


class SkinnedMesh extends THREE.Mesh {
  constructor(geometry, materials) {
    super(geometry, materials);

    this.idMatrix = SkinnedMesh.defaultMatrix();
    this.bones = [];
    this.boneMatrices = [];
    //...
  }
  update(camera) {
    //...
    super.update();
  }
  get boneCount() {
    return this.bones.length;
  }
  set matrixType(matrixType) {
    this.idMatrix = SkinnedMesh[matrixType]();
  }
  static defaultMatrix() {
    return new THREE.Matrix4();
  }
}        
          

#3: objektni literali

Unapređeni objektni literali

  • definisanje prototipa
  • skraćeno pisanje foo: foo dodela
  • definisanje metoda
  • pozivanje super
  • izračunavanje naziva osobina pomoću izraza

  • približavanje objektnih literala i deklaracija klasa

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#Object_literals

Unapređeni objektni literali


var obj = {
    // __proto__
    __proto__: theProtoObj,

    // Shorthand for ‘handler: handler’
    handler,

    // Methods
    toString() {
      // Super calls
      return "d " + super.toString();
    },

    // Computed (dynamic) property names
    [ 'prop_' + (() => 42)() ]: 42
};  
          

#4: template stringovi

Template stringovi

  • sintaksni šećer za konstrukciju stringova
  • slično string interpolaciji za Perl, Python, ...
  • dodavanje tagova za sprečavanje injection napada ili konstruisanja struktura podataka

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/template_strings

Template stringovi


// Basic literal string creation
`In JavaScript '\n' is a line-feed.`

// Multiline strings
`In JavaScript this is
 not legal.`

// String interpolation
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`

// Construct an HTTP request 
// prefix is used to interpret the replacements and construction
POST`http://foo.org/bar?a=${a}&b=${b}
     Content-Type: application/json
     X-Credentials: ${credentials}
     { "foo": ${foo},
       "bar": ${bar}}`(myOnReadyStateChangeHandler);
          

#5: destrukturiranje

Destrukturiranje prilikom dodele

  • slično kao za Python
  • fail-soft: vraća undefined za ono što ne pronađe
  • podrška za nizove i objekte

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment

Destrukturiranje prilikom dodele

// raspakivanje liste
var [a, , b] = [1,2,3];

// raspakivanje objekta
var { op: a, lhs: { op: b }, rhs: c }
       = getASTNode()

// raspakivanje objekta, uz skraćeno pisanje
var {op, lhs, rhs} = getASTNode()

// može se koristiti i kod navođenja parametara
function g({name: x}) {
  console.log(x);
}
g({name: 5})

// Fail-soft: ono što ne pronađe biće undefined
var [a] = [];
a === undefined;

// Fail-soft sa default vrednostima
var [a = 1] = [];
a === 1;

#6: default + rest + spread

Default + rest + spread

  • default: podrazumevane vrednosti parametara funkcije
  • rest: funkcije sa promenljivim brojem parametara
  • spread: konverzija niza u pojedinačne parametre prilikom poziva funkcije

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/rest_parameters
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_operator

Default + rest + spread


// default
function f(x, y=12) {
  // y je 12 ako se ne prosledi (ili se prosledi undefined)
  return x + y;
}
f(3) == 15

// rest
function f(x, ...y) {
  // y je Array
  return x * y.length;
}
f(3, "hello", true) == 6

// spread
function f(x, y, z) {
  return x + y + z;
}

// prosledi elemente niza kao pojedinačne parametre
f(...[1,2,3]) == 6
          

#7: let i const

Let i const

  • let: deklaracija promenljive
  • const: deklaracija konstante
  • opseg vidljivosti im je blok!

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

Let i const


function f() {
  {
    let x;
    {
      // ovo je OK, u ovom bloku x je novo ime
      const x = "sneaky";
      // greška, x je konstanta
      x = "foo";
    }
    // greška, već deklarisano u ovom bloku
    let x = "inner";
  }
}
          

#8: iteratori i for...of

Iteratori i for...of

  • iteratori omogućavaju iteraciju kroz proizvoljne objekte
    kao Java Iterable ili .NET IEnumerable
  • for..of je petlja za iteraciju kroz iterator
  • nije potrebno praviti niz

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of

Iteratori i for...of


let fibonacci = {
  [Symbol.iterator]() {
    let pre = 0, cur = 1;
    return {
      next() {
        [pre, cur] = [cur, pre + cur];
        return { done: false, value: cur }
      }
    }
  }
}

for (var n of fibonacci) {
  // preseci sekvencu na 1000
  if (n > 1000)
    break;
  console.log(n);
}
          

Iteratori i for...of

Iteracija je zasnovana na ovim interfejsima; dovoljan je duck-typing.


interface IteratorResult {
  done: boolean;
  value: any;
}
interface Iterator {
  next(): IteratorResult;
}
interface Iterable {
  [Symbol.iterator](): Iterator
}
          

Interfejsi definisani pomoću TypeScript-a.

#9: generatori

Generatori

  • pomažu kod rada sa velikim nizovima
  • funkcija deklarisana sa function* vraća generator
  • generator je varijanta iteratora sa funkcijama next i throw
  • yield je izraz koji vraća (deo) rezultata

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols

Generatori


var fibonacci = {
  [Symbol.iterator]: function*() {
    var pre = 0, cur = 1;
    for (;;) {
      var temp = pre;
      pre = cur;
      cur += temp;
      yield cur;
    }
  }
}

for (var n of fibonacci) {
  // preseci sekvencu na 1000
  if (n > 1000)
    break;
  console.log(n);
}
          

Generatori

Interfejs generatora je:


interface Generator extends Iterator {
  next(value?: any): IteratorResult;
  throw(exception: any);
}
          

Interfejs definisan pomoću TypeScript-a.

#10: unicode

Unicode

  • podrška za kompletni Unicode
  • u literalima i regularnim izrazima
  • novi API za 21-bitno kodiranje karaktera

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/unicode

Unicode


// isto kao kod ES5.1
"𠮷".length == 2

// novi regexp, specijalni kod 'u'
"𠮷".match(/./u)[0].length == 2

// novi oblik
"\u{20BB7}"=="𠮷"=="\uD842\uDFB7"

// nove String funkcije
"𠮷".codePointAt(0) == 0x20BB7

// for...of prolazi kroz code points
for(var c of "𠮷") {
  console.log(c);
}
          

#11: moduli

Moduli

  • podrška za module na nivou jezika
  • ugrađeno iskustvo iz AMD i CommonJS
  • asinhroni model: kod se ne izvršava dok se svi potrebni moduli ne učitaju

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export

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

Moduli


// lib/mathplusplus.js
export * from "lib/math";
export var e = 2.71828182846;
export default function(x) {
    return Math.log(x);
}

// app.js
// ln je default exported
import ln, {pi, e} from "lib/mathplusplus";
alert("2π = " + ln(e)*pi*2);
          

#12: punjači modula

Punjači modula

  • default punjač (loader) modula
  • mogu se pisati novi punjači
  • izolacija stanja, namespace-a
  • slično classloader-ima u Javi

Punjači modula


// dinamičko učitavanje – 'System' je default loader
System.import('lib/math').then(function(m) {
  alert("2π = " + m.sum(m.pi, m.pi));
});

// izolovano izvršavanje - novi punjači
var loader = new Loader({
  global: fixup(window) // zameni console.log
});
loader.eval("console.log('hello world!');");

// direktna manipulacija kešom modula
System.get('jquery');
System.set('jquery', Module({$: $}));
          

#13: map, set,
weakmap, weakset

Map, Set, WeakMap, WeakSet

  • Map, Set: uobičajene strukture podataka
  • weak: slabe reference na ključeve mape ili elemente seta
    omogućavaju garbage collection kada nema drugih referenci na te objekte

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet

Map, Set, WeakMap, WeakSet


// Set
var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;

// Map
var m = new Map();
m.set("hello", 42);
m.set(s, 34);
m.get(s) == 34;

// WeakMap
var wm = new WeakMap();
wm.set(s, { extra: 42 });
wm.size === undefined

// WeakSet
var ws = new WeakSet();
ws.add({ data: 42 });
// na dodati objekat nema drugih referenci => neće se čuvati u WeakSetu
          

#14: proxy

Proxy

  • posrednički objekti koji omogućavaju presretanje objekata

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy

Proxy


// proxy ka objektu
var target = {};
var handler = {
  get: function (receiver, name) {
    return `Hello, ${name}!`;
  }
};

var p = new Proxy(target, handler);
p.world === 'Hello, world!';

// proxy ka funkciji
var target = function () { return 'I am the target'; };
var handler = {
  apply: function (receiver, ...args) {
    return 'I am the proxy';
  }
};

var p = new Proxy(target, handler);
p() === 'I am the proxy';
          

Proxy

Postoji udica za sve meta-operacije u toku izvršavanja:


var handler =
{
  get:...,
  set:...,
  has:...,
  deleteProperty:...,
  apply:...,
  construct:...,
  getOwnPropertyDescriptor:...,
  defineProperty:...,
  getPrototypeOf:...,
  setPrototypeOf:...,
  enumerate:...,
  ownKeys:...,
  preventExtensions:...,
  isExtensible:...
}
          

#15: simboli

Simboli

  • novi primitivni tip Symbol
  • nema sintaksu za literale
  • mogu biti ključevi za objekte
  • bez kolizije sa String ključevima
  • ne pojavljuju se u for...in, for...of i Object.getOwnPropertyNames
  • zato postoji Object.getOwnPropertySymbols

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol

Simboli


var sym1 = Symbol();
var sym2 = Symbol('foo'); // foo je opcioni opis simbola
var sym3 = Symbol('foo'); // opis je koristan (samo) za debugging
sym2 === sym3; // false
          

Neka korist od simbola?

  • enums

log.levels = {
    DEBUG: Symbol('debug'),
    INFO: Symbol('info'),
    WARN: Symbol('warn'),
};
log(log.levels.DEBUG, 'debug message');
log(log.levels.INFO, 'info message');
          

Neka korist od simbola?

  • metapodaci u objektima

var size = Symbol('size');
class Collection {
    constructor() {
        this[size] = 0;
    }

    add(item) {
        this[this[size]] = item;
        this[size]++;
    }

    static sizeOf(instance) {
        return instance[size];
    }

}

var x = new Collection();
assert(Collection.sizeOf(x) === 0);
x.add('foo');
assert(Collection.sizeOf(x) === 1);
assert.deepEqual(Object.keys(x), ['0']);
assert.deepEqual(Object.getOwnPropertyNames(x), ['0']);
assert.deepEqual(Object.getOwnPropertySymbols(x), [size]);
          

#16: promises

Promises

  • preuzeto iz dosadašnjih dodatnih biblioteka

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

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

#17: reflection

Reflection

  • run-time "raspitivanje" o osobinama objekata
  • slično Java refleksiji

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect

#18: repna rekurzija

Repna rekurzija

  • repna rekurzija neće povećavati stek neograničeno
  • rekurzija je bezbedna

function factorial(n, acc = 1) {
    'use strict';
    if (n <= 1) 
        return acc;
    return factorial(n - 1, n * acc);
}

// stack overflow u većini implementacija,
// ali bezbedno u ES6
factorial(100000)
          

Kraj dela

← Početak dela

⇐ Početak kursa