Javascript Take3 – Le novità di ES6 / ECMAScript 2015 – Whois (#devlife):



Javascript Take3 – Le novità di ES6 / ECMAScript 2015 – Whois (#devlife):

1 1


XEJS3

Corso XE.Net: Javascript Take3 - Novita ES6

On Github dmorosinotto / XEJS3

Javascript Take3

Le novità di ES6 / ECMAScript 2015

by Daniele Morosinotto

Whois (#devlife):

Why JS?

 The Javascript World Domination 

ECMAScript 2015

a.k.a.

ES6

a.k.a.

Javascript Harmony (ES6/7)

Javascript History

  • Creato da Brendan Hich (Netscape) in 10 giorni nel 1996
  • Inizialmente fu battezzato come Livescript, poi Netscape ottenne i diritti esclusivi da Sun per chiamarlo Javascript
  • Introdotto ("copiato") da Microsoft in IE 3.0 con il nome di JScript
  • Standardizzato sotto il nome di ECMAScript nel 1997
  • European Computer Manufactorers Association - by TC39
    • 1999 ES3 Standardizzazione base di Javascript
    • 2009 ES5 Intoduzione Strict Mode
    • 2011 ES5.1 Piccole aggiunte al linguaggio
    • 2015 mid? ES6 = ECMA Script 2015 draft
    • da qui in avanti "dovrebbe" seguire dei rilasci annuali ES2016... (ES7 Harmony)

Current Support (Ops...)

Q: CAN BE USED TODAY?

 

TL;DR

IMHO: YES   with TS!

Who is using ES6 TODAY!

TUTTI i maggiori player e Framework Javascript stanno addottando la sintassi e le funzionalità di ES6!

ES6 "native" sample in FF

<body>
Supporto nativo per alcune funzioni di ES6 in Firefex, ma MANCANO LE <i>Class</i>!
<p>In Chrome non funziona perche NON SUPPORTA LE => <i>(Arrow function)</i>!</p>

<!--uso questo mimetype per problemi con il let -->
<script type="application/javascript;version=1.7">

TypeScript (1.5+) is ES6

//greet.ts è esattamente il codice ES6 + type annotation (che sono opzionali)
function greet(first: number|string = 1000, ...who: string[]) {
    let after: number;         
    if (typeof first !== "number") {        
        [after, who] = [5000, [first, ...who]];    
    } else {
        after = first;
    }    
    let names = who.join(' ');
    const printH1 = () => document.body.innerHTML+=`<h1>Hello ${names}</h1>`;
    setTimeout(printH1, after);    
    console.log(`Will greet #${who.length} in ${after/1000} sec`);
}

Per compilare il codice TypeScript in JS è necessario:

npm  install  typescript -g
tsc  greet.ts  --out greet.js  --target ES5

Nel file HTML si incluse semplicemente il file Javascript:

<script type="text/javascript" src="greet.js" />

SystemJS + Traceur runtime

Per inizializzare in modo semplice l'ambiente usiamo jspm

npm  install  jspm  -g
cd  my_project_dir
jspm  init  -y
  • Vengono scaricate tutte le dipendenze in jspm_packages ed inoltre viene creato in automatico il file config.js.
  • Bisogna creare un file my_startup.js per caricare e lanciare il codice ES6 esposto tramite export function greet(..){...}
//contenuto del file my_startup.js 
import {greet} from './greet';    //greet.js espone export function greet(..){...}
greet(2000,"Pippo");            //Hello Pippo         - Will greet #1 in 2 sec
greet("XE", "ES6", "rocks!");   //Hello XE ES6 rocks! - Will greet #3 in 5 sec
greet();                        //Hello               - Will greet #0 in 1 sec

Ed in fine nel file HTML bisogna includere gli script di startup:

<script src="jspm_packages/system.js" />
<script src="config.js" />
<script>
    System.import('my_startup'); //startup del nostro codice ES6
<script/>

SystemJS + Traceur Bundle

Per evitare di avere la compilazione a runtime di ES6 e rimuovere tutte le dipendenze da SystemJS e Traceur e' possibile creare un bundle con jspm ed ottenere il file build.js da usare nell'HTML

jspm  bundle-sfx  my_startup  build.js

Con ES6 volendo possiamo anche creare delle Class che riutilizzano e incapsulano meglio la nostra function greet()

Bundle with Babel js

Per semplificare la configurazione del progetto usiamo jspm con questa specifica configurazione:

jspm  init
Package.json file does not exist, create it? [yes]:
Would you like jspm to prefix the jspm package.json properties under jspm? [yes]:
Enter server baseURL (public folder path) [./]:
Enter jspm packages folder [.\jspm_packages]:
Enter config file path [.\config.js]:
Configuration file config.js doesn't exist, create it? [yes]:
Enter client baseURL (public folder URL) [/]: ./
Which ES6 transpiler would you like to use, Traceur or Babel? [traceur]: Babel
  • Vengono scaricate tutte le dipendenze in jspm_packages ed inoltre viene creato in automatico il file config.js.
  • Bisogna creare il file entry.js che contiene l'import del file great.js che espone la funzione greet(..){...}
  • Ed inifine per compilare con Babel, il file bundle.js da includere nella pagina HTML, si usa il comando:
jspm  bundle-sfx  entry  bundle.js

HowTo Generators in Babel

ATTENZIONE: Per poter usare Generators con Babel bisogna:

  • Includere nella pagina HTML lo script browser-polyfill.js da:
    .\jspm_packages\npm\babel@4.7.16\browser-polyfill.js
  • Modificare il config.js per disabilitare/commentare le babelOption runtime:
    /*"babelOptions": {
      "optional": [
        "runtime"
      ]
    },*/
  • Ed infine copiare il file external-helpers.js dalla cartella:
    jspm_packages\npm\babel@4.7.16   -->   jspm_packages\npm
    Altrimenti la compilazione del bundle.js non funziona!

NEW SYNTAX

Shorthand object initializer

Block Scope: let const

String Template ` = ALT+96

Destructuring assignment

Default parameter

Rest parameter + ...Spread

CODE PATTERN

Arrow function =>

Class

Class is only Syntactic Sugar

Module System

  • Standardizzazione della sintassi per gestire il codice JS in più file - ndr: moduli e le relative dipendenze (import, export).
  • Permette di uniformare i pattern attualmente in uso (AMD, CommonJS) tramite implementazioni del Loader - ndr: System che ha comportamento di default: caricamento asincrono!

export

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

import * RUN

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

import explicit + rename RUN

// app2.js
import { pi, sqrt as radice } from "lib/math";
alert("V²π = " + radice(pi));                    //1.7724539

export default

// lib/mathplus.js
export default function(x) {
    return Math.exp(x);
}

export * + import default

// lib/mathplusplus.js
export * from "lib/math";
import _exp from "lib/mathplus";
export const e = _exp(1);
export var exp = _exp;

import dependency tree RUN

// app3.js
import {exp, pi} from "lib/mathplusplus";
alert("e^π = " + exp(pi));                     //23.1407006

ITERATORS &   GENERATORS

Symbol

  • Sono una nuova primitiva di Javascript che permette di avere un valore univoco!
    var _secretKey = new Symbol("secret");     //name is optional
  • Può essere usata in qualsiasi oggetto come "key" (nome di una proprietà) al posto delle stringhe
  • Ci sono alcune costanti usate internamente da JS: Symbol.iterator
  • Utile ad esempio per simulare private

Iterables

  • Sono oggetti che espongono un metodo di nome Symbol.iterator e che ritorna un oggetto Iterator
    interface Iterable {
      [Symbol.iterator](): Iterator
    }

Iterator objects

  • E' un oggetto che espone un singolo metodo next() che ogni volta che viene chiamata ritorna oggetti con due proprietà:
    • value: che rappresenta il valore corrente di qualsiasi tipo
    • done: di tipo booleano per indicare con true quando sono stati esauiriti tutti i valori
interface Iterator {
  next(): IteratorResult;
}

interface IteratorResult {
  done: boolean;
  value: any;
}

for of

ESEMPI di implementazione di Iterable: Range() e fibonacci

Gli Iterator possono essere usati direttamente, ma nella maggior parte dei casi l'interfaccia viene consumata usando il nuovo ciclo for (let item of Iterable) {...}

Generators

  • Sono "pausable function" che utilizzano yield per semplificare l'implementazione di Iterators e molto altro... (ndr: observable & co-routine)

  • Implementano questa interfaccia:

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

yield REAL POWER!

La dualità dei Generator = Iterable + Observable e mettendo insieme yield + Promise = Async/Await

OTHER THINGS

Promise

  • Implementazione starndard delle Promise (nrd: "thenable") per gestire meglio esecuzione asincrona evitando "callback hell" grazie al "chaining"!
  • Rappresenta il "possibile valore futuro" di un'esecuzione asincrona (resolve), o l'eventuale errore (reject)

  • Metodi principali:

    • Promise.new (executor: (resolve, reject) => void) : Promise
    • .then ( oufullfilled, onrejected? ) : Promise
    • .catch ( onrejected ) : Promise
  • Altri metodi:

    • per risolvere immediatamente: Promise.resolve(val), Promise.reject(reason)
    • per gestire parallelismo: .all( [...promArr] ), .race( [...promArr] ), etc...
  • ESEMPI: delay, httpGET, timeout

Other Objects

  • Map : Sono dei veri dictionary che gestiscono chiavi "key" di qualunque tipo primitivo, oggetti o funzioni (reference)
  • Set : E' una collezione di elementi univoci (controllo esistenza con === uguaglianza per reference)
  • WeakMap + WeakSet : Sono come Map e Set solo che hanno la proprietà di NON mantenere un riferimento vivo all'oggetto usato come chiave, e quindi NON ci sono problemi di Garbage collection/Memory leak
let obj = {};
let dict = new Map();

dict.set(obj, 123);
dict.get(obj)        //123
dict.has(obj)        //true
dict.delete(obj);    //true
dict.has(obj);        //false

let arr = [5, 1, 5, 7, 7, 5];
let unique = [...new Set(arr)]; // [ 5, 1, 7 ]

New functions

  • Object.assign(...objs) utilissimo per fare MIXIN
  • Number.isNaN( n ) finalmente un modo per controllare NaN
  • Array.from( arrLike ) utile per DOM element o arguments
  • Array.prototype.findIndex( predicate: (item) => bool )
console.log( 
  Object.assign({}, {n: 1, s: "ciao"}, {b: true, n: 2 }) // MIXIN!!
, Number.isNaN( 0/0 )                                 //true
, Array.from( document.querySelectorAll('div') )     //Array VERO!!!
, [1,2,"ciao",true].findIndex(x => x=="ciao")         //2
);
  • Literal di tipo Binary 0b0010101 e Octal 0o723
  • e tante altre in: Math , Number , String , Reflect API, Tail Calls, etc...

Proxy & Object.Observe()

  • Attualmente non sono implementati da nessuno e potrebbero esser soggetti a cambiamenti/ridefinizioni in futuro... ma potrebbero diventare veramente Importanti per chi deve sviluppare dei Framework di Binding per gestire il "dirty checking"!

  • Permettanno di agganciare un qualsiasi oggetto ed essere notificati di tutte le modifiche che subisce ogni prorprietà, oppure di sovrapporsi all'oggetto per intercettare (e gestire) l'accesso alle proprietà anche quelle non esistenti.

let target = {};
let handler = {
    get(targetObj, propKey, receiver) {
        console.log('get ' + propKey);
        return 123;
    }
};
let proxy = new Proxy(target, handler);

> proxy.foo
    get foo
    123

Reference Links:

"The Force is strong with this one." Darth Vader

THE END

by Daniele Morosinotto

Contatti:
reveal.js