On Github dmorosinotto / XEJS3
by Daniele Morosinotto
a.k.a.
a.k.a.
NATIVE solo "qualcosa" in:
RUNTIME solo per fase sviluppo/test:
TRANSPILER verso ES5 per usarlo su tutti i Browser:
PACKAGE MANAGER per creare bundle in produzione:
TL;DR
TUTTI i maggiori player e Framework Javascript stanno addottando la sintassi e le funzionalità di ES6!
<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">
//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" />
Per inizializzare in modo semplice l'ambiente usiamo jspm
npm install jspm -g cd my_project_dir jspm init -y
//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/>
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()
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
jspm bundle-sfx entry bundle.js
ATTENZIONE: Per poter usare Generators con Babel bisogna:
.\jspm_packages\npm\babel@4.7.16\browser-polyfill.js
/*"babelOptions": { "optional": [ "runtime" ] },*/
jspm_packages\npm\babel@4.7.16 --> jspm_packages\npmAltrimenti la compilazione del bundle.js non funziona!
// lib/math.js export function sum(x, y) { return x + y; } export const pi = 3.141593; export var sqrt = Math.sqrt;
// app1.js import * as math from "lib/math"; alert("2π = " + math.sum(math.pi, math.pi)); //6.283186
// app2.js import { pi, sqrt as radice } from "lib/math"; alert("V²π = " + radice(pi)); //1.7724539
// lib/mathplus.js export default function(x) { return Math.exp(x); }
// lib/mathplusplus.js export * from "lib/math"; import _exp from "lib/mathplus"; export const e = _exp(1); export var exp = _exp;
// app3.js import {exp, pi} from "lib/mathplusplus"; alert("e^π = " + exp(pi)); //23.1407006
var _secretKey = new Symbol("secret"); //name is optional
interface Iterable { [Symbol.iterator](): Iterator }
interface Iterator { next(): IteratorResult; } interface IteratorResult { done: boolean; value: any; }
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) {...}
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); }
La dualità dei Generator = Iterable + Observable e mettendo insieme yield + Promise = Async/Await
Rappresenta il "possibile valore futuro" di un'esecuzione asincrona (resolve), o l'eventuale errore (reject)
Metodi principali:
Altri metodi:
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 ]
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 );
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