Prelegere din cadrul materiei "Dezvoltarea aplicaţiilor Web cu JavaScript" (Full-Stack Web Development) predată de Dr. Sabin Buraga (oct.2019–feb.2020).
Resurse suplimentare la https://profs.info.uaic.ro/~busaco/teach/courses/staw/web-film.html
4. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
ECMAScript 2015 (ES6)
definirea de clase – perspectiva paradigmei obiectuale
parametri cu valori implicite și parametri multipli
machete pentru șiruri de caractere (template literals)
declararea succintă a funcțiilor anonime (arrow functions)
iteratori și generatori
notificări privind rezultatul oferit de o funcție (promises)
noi tipuri de date – e.g., Set, Map, Symbol, Proxy
modularizarea codului: module + importuri
…
8. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const DIST = 7, MAXPOWER = 33;
class Robot {
constructor (distance = 0) {
this.power = 0;
this.distance = distance;
}
move () {
if (this.power < 1) {
throw new RangeError ('N-am energie');
}
this.power--;
this.distance += DIST;
}
addPower () {
if (this.power >= MAXPOWER) {
throw new RangeError ('Bateria e plină');
}
this.power++;
}
}
un robot poate fi mutat,
parcurgând o distanță
prestabilită și consumând
o unitate energică
suplimentar, poate fi
alimentat cu energie
în ES6 se pot declara
parametri cu valori implicite
9. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const DIST = 7, MAXPOWER = 33;
class Robot {
constructor (distance = 0) {
this.power = 0;
this.distance = distance;
}
move () {
if (this.power < 1) {
throw new RangeError ('N-am energie');
}
this.power--;
this.distance += DIST;
}
addPower () {
if (this.power >= MAXPOWER) {
throw new RangeError ('Bateria e plină');
}
this.power++;
}
}
// instanțiem un robot
// distanța ia valoarea implicită
let robot = new Robot ();
console.log (robot.distance);
try {
robot.addPower ();
robot.move ();
robot.move ();
} catch (e) {
console.error (e.message);
} finally {
console.log ('M-am deplasat cu '
+ robot.distance +
' metri, iar energia actuală este '
+ robot.power);
}
10. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const DIST = 7, MAXPOWER = 33;
class Robot {
constructor (distance = 0) {
this.power = 0;
this.distance = distance;
}
move () {
if (this.power < 1) {
throw new RangeError ('N-am energie');
}
this.power--;
this.distance += DIST;
}
addPower () {
if (this.power >= MAXPOWER) {
throw new RangeError ('Bateria e plină');
}
this.power++;
}
}
// instanțiem un robot
// distanța ia valoarea implicită
let robot = new Robot ();
console.log (robot.distance);
try {
robot.addPower ();
robot.move ();
robot.move ();
} catch (e) {
console.error (e.message);
} finally {
console.log ('M-am deplasat cu '
+ robot.distance +
' metri, iar energia actuală este '
+ robot.power);
}
11. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
class R2D2 extends Robot {
constructor (distance) {
super (distance * 2);
}
move () {
super.move ();
this.power++; // R2D2 nu consumă energie ;)
}
}
mai sunt permise:
extinderi de clasă via extends
acces – cu super – la membrii din clasa de bază
metode de tip get și set
metode statice specificate cu prefixul static (similar C++)
a se vedea arhiva
exemplelor
12. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// instanțiem robotul din clasa R2D2
let r2d2 = new R2D2 (15);
try {
r2d2.addPower (); // inițial, R2D2 trebuie alimentat cu energie
r2d2.move ();
} catch (e) {
console.error (e.message);
}
finally {
console.log ('Sunt R2D2, m-am deplasat cu '
+ r2d2.distance + ' metri, iar energia curentă este ' + r2d2.power);
}
de ce această
valoare?
14. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi maniere de a declara variabile
let – alternativă la var, cu vizibilitate la nivel de bloc
(mărginirea domeniului de vizibilitate – scope)
ponyfoo.com/articles/es6-let-const-and-temporal-dead-zone-in-depth
15. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
function TestareLet () {
let x = 33;
if (true) {
// variabilă diferită!
let x = 74;
console.log (x); // 74
}
console.log (x); // 33
}
function TestareVar () {
var x = 33;
if (true) {
// aceeași variabilă
var x = 74;
console.log (x); // 74
}
console.log (x); // 74
}
developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/let
20. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
destructurare pentru date de tip Array
// selectarea elementelor dorite dintr-o listă (tablou)
let [ primul, , ultimul ] = [ 'Ana', 'Bogdan', Date.now() ];
console.log (primul); // "Ana"
console.log (ultimul); // data curentă în secunde
22. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
destructurare în cazul obiectelor
// oferă – ca obiect – coordonatele geografice pentru Iași
function furnizeazăCoordonate () {
return { lat: 47.16667, long: 27.6 };
}
var { lat, long } = furnizeazăCoordonate ();
console.log (long);
23. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
destructurare în cazul obiectelor
(aici, parametri ai funcțiilor)
// furnizează un număr natural generat aleatoriu dintr-un anumit interval
function genAleator ({ min = 1, max = 300 } = { }) {
return Math.floor (Math.random () * (max - min)) + min;
}
for (let it of [1, 2, 3, 4]) { // 4 numere generate aleatoriu
console.log (genAleator ());
}
24. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
destructurare în cazul obiectelor
(aici, parametri ai funcțiilor)
// furnizează un număr natural generat aleatoriu dintr-un anumit interval
function genAleator ({ min = 1, max = 300 } = { }) {
return Math.floor (Math.random () * (max - min)) + min;
}
for (let it of [1, 2, 3, 4]) { // 4 numere generate aleatoriu
console.log (genAleator ());
}
rularea programului cu instrumentul interactiv JS Bin
25. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Machete privind substituția de valorile de bază
(template literals)
machetă = orice șir de caractere delimitat de simbolul `
(inclusiv specificat pe mai multe linii de text – multiline)
o machetă poate include expresii JavaScript specificate
cu ${…} ce vor fi înlocuite cu valoarea evaluată
26. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
var articol = { // obiect JS oferind date despre un articol
titlu: 'Machete ES6',
subiect: 'facilități privind substituția de valori',
slogan: 'Generare HTML cu JS',
termeni: [ 'ES6', 'JavaScript', 'HTML5' ]
};
var { titlu, subiect, slogan, termeni } = articol; // destructurare
var html = `<article>
<header><h1>${titlu}</h1></header>
<section>
<h2>Articol despre ${subiect}</h2>
<p>${slogan}</p>
</section>
<footer class='subsol'>
<ul>${termeni.map (termen => `<li>${termen}</li>`).join ('nttt')}</ul>
</footer>
</article>`;
console.log (html);
fiecărui element din tabloul termeni îi corespunde
o machetă a cărei valoare va fi un marcaj HTML
28. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Arrow functions
declarare succintă a unei funcții anonime
parametri => valoareOferită
nu posedă propriile valori pentru this, arguments, super
ponyfoo.com/articles/es6-arrow-functions-in-depth
developer.mozilla.org/Web/JavaScript/Reference/Functions/Arrow_functions
29. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// funcție anonimă cu un singur argument de intrare
// se întoarce valoarea unei expresii JS
console.log ( [2, 3, 5].map (număr => număr * 7) ); // [14, 21, 35]
// în JavaScript clasic (ES5):
console.log ( [2, 3, 5].map (function (număr) {
return număr * 7;
}) );
31. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
let numere = [1, 7, 50, 74, 9, 85, 51, 12, 7, 15];
// asocieri între valori și funcții
// aici, calculul pătratului fiecărei valori a elementelor din tablou
let pătrate = numere.map (val => Math.pow (val, 2));
32. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
let numere = [1, 7, 50, 74, 9, 85, 51, 12, 7, 15];
// reducerea unui tip de date structurat la o valoare scalară
// aici, suma tuturor valorilor: 311
let suma = numere.reduce ((a, b) => a + b);
33. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
let numere = [1, 7, 50, 74, 9, 85, 51, 12, 7, 15];
// filtrarea valorilor, obținând un sub-tablou
// aici, doar numerele impare: [1, 7, 9, 85, 51, 7, 15]
let impare = numere.filter (val => val % 2 === 1);
34. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
var numere = [1, 7, 50, 74, 9, 85, 51, 12, 7, 15];
const MAX = 99;
/* întoarce true dacă predicatul func are ca rezultat true
pentru orice element al colecției de date
– cuantificatorul universal oricare (all – ∀) */
const toate = (tablou, func = Boolean) => tablou.every (func);
// ce rezultă executând liniile de cod următoare?
toate (numere, număr => număr >= 18 && număr < 65);
toate (numere, număr => Math.sqrt (număr) <= MAX);
adaptare după github.com/30-seconds/30-seconds-of-code
36. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
var numere = [1, 7, 50, 74, 9, 85, 51, 12, 7, 15];
/* întoarce true dacă predicatul func are ca rezultat true
pentru măcar un element al colecției de date
– cuantificatorul existențial */
const există = (tablou, func = Boolean) => tablou.some (func);
Cum se specifică în ES6 expresia care verifică dacă există
măcar o vârstă de adult printre valorile tabloului numere?
40. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// trunchierea unui șir de caractere
const MIN = 3;
const truncȘir = (șir, număr) =>
// dacă lungimea șirului e mai mare decât
// numărul de caractere dorit
șir.length > număr ?
// înlocuim caracterele în surplus cu șirul '...'
șir.slice (0, număr > MIN ? număr - MIN : număr) + '...' : șir;
adaptare după github.com/30-seconds/30-seconds-of-code
44. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// Recurgerea la iteratori pentru a genera secvențe infinite de valori
const VAL = 7, MAX = 69;
let secvMult = { // generează o secvență de nr. multiplicate cu o valoare
[Symbol.iterator]() {
let curent = 0; // contor disponibil doar în interiorul iteratorului
return {
next () { // se expune metoda next () pentru a obține următoarea valoare
curent++;
// metoda next () va întoarce obligatoriu 2 valori
return {
done: false, // 'true' semnalează că secvența se termină
value: curent * VAL // desemnează elementul curent al secvenței
};
}
};
}
}
for (let numar of secvMult) {
if (numar > MAX) break; // secvența fiind infinită, trebuie să folosim 'break'
console.log (numar);
}
47. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Generatori
generator = tip special de iterator ce returnează g
obiecte de tip generator care ulterior pot fi iterate cu
Array.from (g) sau […g] sau for valoare of g
ponyfoo.com/articles/es6-generators-in-depth
es6-features.org/#GeneratorFunctionIteratorProtocol
49. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// declararea unui generator de identificatori numerici
function* idMaker () {
var index = 0;
while (index < 3)
yield index++;
}
const gen = idMaker ();
// obținerea unui identificator via generatorul declarat
console.log (gen.next ().value); // 0
console.log (gen.next ().value); // 1
console.log (gen.next ().value); // 2
console.log (gen.next ().value); // undefined
// iterarea valorilor de identificatori generați
for (let id of idMaker ()) {
console.log (id);
}
vezi exemplul
din arhivă
50. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// declararea unui generator de identificatori numerici
function* idMaker () {
var index = 0;
while (index < 3)
yield index++;
}
const gen = idMaker ();
// obținerea unui identificator via generatorul declarat
console.log (gen.next ().value); // 0
console.log (gen.next ().value); // 1
console.log (gen.next ().value); // 2
console.log (gen.next ().value); // undefined
// iterarea valorilor de identificatori generați
for (let id of idMaker ()) {
console.log (id);
}
function* declară un generator
apelul idMaker () nu execută corpul
funcției, ci creează un obiect generator
menit a controla execuția
instrucțiunilor din corp
51. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// generarea secvenței numerelor lui Fibonacci
let fib = function* (numere) {
let prec = 0, curent = 1;
while (numere-- > 0) {
[ prec, curent ] = [ curent, prec + curent ]; // destructurare
yield curent;
}
}
// primele 10 numere
console.log ([ ...fib (10) ]); // [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
// al doilea din secvență, apoi restul de la al patrulea încolo
let [ , n2, , ...restul ] = fib (10);
console.log (n2, restul); // 2 și [5, 8, 13, 21, 34, 55, 89]
adaptare după es6-features.org/#GeneratorMatching
52. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// generarea secvenței numerelor lui Fibonacci
let fib = function* (numere) {
let prec = 0, curent = 1;
while (numere-- > 0) {
[ prec, curent ] = [ curent, prec + curent ]; // destructurare
yield curent;
}
}
// primele 10 numere
console.log ([ ...fib (10) ]); // [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
// al doilea din secvență, apoi restul de la al patrulea încolo
let [ , n2, , ...restul ] = fib (10);
console.log (n2, restul); // 2 și [5, 8, 13, 21, 34, 55, 89]
rezultatul programului
executat de Node.js
55. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Promises
promisiune (promise) rezultat ce ar putea fi oferit
în urma execuției unei operații asincrone
represents an operation that has not completed yet,
but is expected in the future
developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Promise
exploringjs.com/es6/ch_promises.html
60. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// implementarea unui obiect Promise
var promise = new Promise (function (resolve, reject) {
// realizarea unor operații (eventual, în mod asincron)
// apoi, în funcție de ceea ce s-a întâmplat…
if (/* totul e în regulă */) {
resolve ("A mers!"); // poate fi prelucrat rezultatul cu then ()
}
else {
reject (Error ("S-a stricat")); // eroarea poate fi tratată via catch ()
}
});
specificația pentru implementarea standardizată:
promisesaplus.com
biblioteci JS: promisesaplus.com/implementations
61. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// implementarea unui obiect Promise
var promise = new Promise (function (resolve, reject) {
// realizarea unor operații (eventual, în mod asincron)
// apoi, în funcție de ceea ce s-a întâmplat…
if (/* totul e în regulă */) {
resolve ("A mers!"); // poate fi prelucrat rezultatul cu then ()
}
else {
reject (Error ("S-a stricat")); // eroarea poate fi tratată via catch ()
}
});
// utilizarea ulterioară
promise.then (function(result) {
console.log (result); // "A mers!"
}, function(err) {
console.log (err); // Error: "S-a stricat"
});
62. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
metodele then () și catch () pot fi înlănțuite
.then (onFullfilment)
.then ()
.catch ()
pending pending
settled
acțiuni asincrone
(async actions)
.then (onRejection)
.catch (onRejection)
tratarea erorilor
(error handling)
…Promise Promise
63. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
metodele then () și catch () pot fi înlănțuite
un tutorial, oferind exemple practice:
developers.google.com/web/fundamentals/primers/promises
a se studia și github.com/wbinnssmith/awesome-promises
.then (onFullfilment)
.then ()
.catch ()
pending pending
settled
acțiuni asincrone
(async actions)
.then (onRejection)
.catch (onRejection)
tratarea erorilor
(error handling)
…Promise Promise
66. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: Set
structură de date iterabilă implementând
conceptul de mulțime (un element apare o singură dată)
proprietate: size – nu se utilizează length
metode: add() delete() clear() entries()
has() forEach() keys() values()
developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Set
67. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: Map
structură de date iterabilă de tip asociere cheie—valoare
(cheile și valorile pot avea orice tip, inclusiv funcții)
proprietate: size
metode: set() get() delete() clear() entries()
has() forEach() keys() values()
developer.mozilla.org/Web/JavaScript/Reference/Global_Objects/Map
68. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: Map
desemnează o colecție
vizând manipularea tablourilor asociative
ordinea cheilor contează (e păstrată),
spre deosebire de Object
de studiat Maya Shavin, ES6: Map vs Object, What and When? (2018)
medium.com/front-end-weekly/es6-map-vs-object-what-and-when-b80621932373
69. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// instanțiem un obiect Map pentru a stoca atribute
// despre profilul unui utilizator în forma cheie-valoare
let profil = new Map();
// stabilim chei (aici, pasiune și mediu)
profil.set ('pasiune', { tip: 'muzica', gen: 'rock', stil: 'progresiv',
grupFavorit: [ 'Pink Floyd', 'Yes' ] }); // un obiect
profil.set ('mediu', 'urban');
if (profil.has ('mediu')) { // verificăm existența unei chei
profil.set ('mediu', 'cosmic');
}
// redăm la consolă valorile cheilor
console.log (profil.get ('pasiune'));
console.log (profil.get ('pasiune').grupFavorit[0]);
// iterarea cheilor & valorilor aferente
profil.forEach((val, cheie) => console.log(`cheie: ${cheie}, valoare: ${val}`));
71. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: WeakSet
similar cu Set, dar reprezintă o mulțime de obiecte și
nu de valori arbitrare având diverse tipuri de date
în contrast cu Set, obiectele de tip WeakSet nu pot fi
enumerate, iar referințele la obiecte sunt weak
– dacă nu există referințe la una dintre cheile sale,
obiectul este eliberat din memorie (garbage collection)
72. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: WeakMap
similar cu WeakSet, dar fiecare cheie trebuie să fie obiect
ponyfoo.com/articles/es6-weakmaps-sets-and-weaksets-in-depth
www.sitepoint.com/using-the-new-es6-collections-map-set-weakmap-weakset/
73. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: Symbol
un simbol este un tip de date imutabil ce poate fi folosit
ca identificator unic pentru proprietățile obiectelor
a symbol never clashes with any other property key
(symbol or string)
exploringjs.com/es6/ch_symbols.html
74. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const ST_VESEL = Symbol('😀');
const ST_TRIST = Symbol('😞');
const ST_NEUTRU = Symbol('😐');
function oferăStareComplementară (stare) {
switch (stare) {
case ST_VESEL: return ST_TRIST;
case ST_TRIST: return ST_VESEL;
default: throw new Error ('Stare de spirit necunoscută');
}
}
try {
console.log (oferăStareComplementară (ST_TRIST));
// conversia la șir de caractere trebuie realizată explicit
console.log (oferăStareComplementară (ST_VESEL).toString ());
// apelăm funcția având ca argument un simbol nedorit
console.log (oferăStareComplementară (ST_NEUTRU));
} catch (e) {
console.log (e.message);
}
75. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const ST_VESEL = Symbol('😀');
const ST_TRIST = Symbol('😞');
const ST_NEUTRU = Symbol('😐');
function oferăStareComplementară (stare) {
switch (stare) {
case ST_VESEL: return ST_TRIST;
case ST_TRIST: return ST_VESEL;
default: throw new Error ('Stare de spirit necunoscută');
}
}
try {
console.log (oferăStareComplementară (ST_TRIST));
// conversia la șir de caractere trebuie realizată explicit
console.log (oferăStareComplementară (ST_VESEL).toString ());
// apelăm funcția având ca argument un simbol nedorit
console.log (oferăStareComplementară (ST_NEUTRU));
} catch (e) {
console.log (e.message);
}
76. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Noi tipuri de date ES6: Proxy
se permite interceptarea și modificarea operațiilor
realizate de obiecte – e.g., proprietăți de tip getter
redefinirea semanticii unor construcții ale limbajului
de programare (intercession) – aspect al meta-programării
exploringjs.com/es6/ch_proxies.html
81. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Tablouri respectând un anumit tip de date
typed arrays
utile pentru a manipula în principal date binare:
întregi (cu/fără semn) cu stocare pe 8, 16, 32 de biți
Int8Array Uint8Array Int16Array Int32Array etc.
numere reale reprezentate pe 32 sau 64 de biți
Float32Array Float64Array
exploringjs.com/es6/ch_typed-arrays.html
82. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// definim o structură de date pe 24 de octeți, similară celei din limbajul C:
// struct Animal { unsigned long id; char nume[16]; float mărime }
class Animal {
constructor (mem = new ArrayBuffer (24)) { // alocăm memoria necesară
this.mem = mem;
};
// gestionarea memoriei corespunzătoare datelor de stocat (un buffer)
set mem (date) { // stocarea datelor în zona de memorie alocată
this._mem = date; // intern, vor fi folosite proprietăți „private”
this._id = new Uint32Array (this._mem, 0, 1);
this._nume = new Uint8Array (this._mem, 4, 16);
this._mărime = new Float32Array (this._mem, 20, 1);
}
get mem () { // obținerea datelor stocate
return this._mem;
}
adaptare după es6-features.org/#TypedArrays
83. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// metode setter/getter pentru fiecare membru în parte
set id (v) { this._id[0] = v; }
get id () { return this._id[0]; }
set nume (v) { this._nume = v; }
get nume () { return this._nume; }
set mărime (v) { this._mărime[0] = v; }
get mărime () { return this._mărime[0]; }
}
let tux = new Animal ();
tux.id = 69;
tux.nume = "Tux";
tux.mărime = 15.74;
console.log (`Obiectul ${tux.nume} are identificatorul ${tux.id}
și mărimea ${tux.marime}.`);
adaptare după es6-features.org/#TypedArrays
85. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Module
scop: modularizarea + reutilizarea codului-sursă
spre deosebire de JavaScript clasic, unde modularizarea
se baza pe biblioteci externe (CommonJS sau RequireJS
care adoptă AMD – Asynchronous Module Definition),
în ES6 există suport nativ
exploringjs.com/es6/ch_modules.html
86. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// --json.js--
function preiaJSON (url, procDate) { // preia de la un URL date JSON
let xhr = new XMLHttpRequest (); // procesate cu funcția procDate
xhr.onload = function () {
procDate (this.responseText)
};
xhr.open ("GET", url, true);
xhr.send ();
}
export function oferăConținut (url, procDate) {
preiaJSON (url, date => procDate (JSON.parse (date)));
}
specificarea unui modul – stocat într-un fișier conform
politicii „one module per file & one file per module” –
ce oferă (exportă) funcționalități
87. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// --json.js--
function preiaJSON (url, procDate) {
let xhr = new XMLHttpRequest ();
xhr.onload = function () {
procDate (this.responseText)
};
xhr.open ("GET", url, true);
xhr.send ();
}
export function oferăConținut (url, procDate) {
preiaJSON (url, date => procDate (JSON.parse (date)));
}
// --main.js-- (utilizarea modulului)
import { oferăConținut } from "json.js";
oferăConținut ("http://undeva.info",
date => { procesează (date); });
aici, importul este identificat prin nume (named import)
90. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Browser-ele Web moderne oferă suport complet
pentru încărcarea (a)sincronă a modulelor JS:
<script type="module" src="modul.mjs" async></script>
<script nomodule src="fallback.js"></script>
facilitate descrisă în HTML Living Standard
(15 octombrie 2019)
html.spec.whatwg.org/multipage/scripting.html
tutorial: v8.dev/features/modules
102. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Funcții asincrone (async functions)
la apelare, o funcție asincronă oferă un obiect
de tip Promise – acesta e creat la execuția funcției asincrone
este executat corpul funcției – execuția poate fi terminată
permanent via return (succes) ori throw (caz de eroare)
103. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Funcții asincrone (async functions)
la apelare, o funcție asincronă oferă un obiect
de tip Promise – acesta e creat la execuția funcției asincrone
este executat corpul funcției – execuția poate fi terminată
permanent via return (succes) ori throw (caz de eroare)
sau poate fi temporar oprită via await
(uzual, execuția va fi reluată ulterior)
104. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Funcții asincrone (async functions)
programul poate fi notificat atunci când este disponibil
rezultatul unei funcții – obiectul Promise e în starea settled
adică operația a avut loc (cu succes sau cu eroare):
se recurge la metodele then () și, eventual, catch ()
105. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
Funcții asincrone (async functions)
programul poate fi notificat atunci când este disponibil
rezultatul unei funcții – obiectul Promise e în starea settled
adică operația a avut loc (cu succes sau cu eroare):
se recurge la metodele then () și, eventual, catch ()
această notificare are loc în mod asincron
exploringjs.com/es2016-es2017/ch_async-functions.html
106. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const MAXITER = 7;
async function funcAsinc1 () {
for (let i = 1; i <= MAXITER; i++) {
console.log (`Asincron 1: ${i}`);
};
return "Java";
}
async function funcAsinc2 () {
for (let i = 1; i <= MAXITER; i++) {
console.log (`Asincron 2: ${i}`);
};
return "Script";
}
// deoarece o funcție asincronă întoarce un obiect Promise,
// putem folosi metoda then ();
// pentru a trata erorile se va recurge la catch ()
funcAsincP().then (r => console.log (`Rezultat: ${r}`));
console.log ("Program principal");
async function funcAsincP () {
// se așteaptă execuția ambelor funcții asincrone
const [rez1, rez2] = await Promise.all ([
funcAsinc1 (),
funcAsinc2 (),
]);
return rez1 + rez2;
}
107. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
const MAXITER = 7;
async function funcAsinc1 () {
for (let i = 1; i <= MAXITER; i++) {
console.log (`Asincron 1: ${i}`);
};
return "Java";
}
async function funcAsinc2 () {
for (let i = 1; i <= MAXITER; i++) {
console.log (`Asincron 2: ${i}`);
};
return "Script";
}
// deoarece o funcție asincronă întoarce un obiect Promise,
// putem folosi metoda then ();
// pentru a trata erorile se va recurge la catch ()
funcAsincP().then (r => console.log (`Rezultat: ${r}`));
console.log ("Program principal");
async function funcAsincP () {
// se așteaptă execuția ambelor funcții asincrone
const [rez1, rez2] = await Promise.all ([
funcAsinc1 (),
funcAsinc2 (),
]);
return rez1 + rez2;
}
120. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
ECMAScript 2019 (ES10)
noutate:
metoda flat() „aplatizează” (flattens) un tablou ce posedă
elemente imbricate, creând o copie a tabloului unde toate
elementele apar pe un singur nivel
flatMap() realizează în prealabil și o asociere (mapping)
tablou.flatMap(funcție) tablou.map(funcție).flat(1)
121. Dr.SabinBuragaprofs.info.uaic.ro/~busaco
// un tablou de tablouri cu nume de membri de echipe
let echipe = [ [ 'Tux', 'Pox' ], // echipa #1
[ 'Puq', [ 'Hax', 'Roa' ] ], // echipa #2
[ 'Tux', 'Roa', 'Muz' ], // echipa #3
'Foh' ]; // și un solitar
console.log (echipe);
console.log (echipe.flat ()); // aplatizăm tabloul
console.log (echipe.flat (2)); // aplatizăm în profunzime
// realizăm și o asociere cu flatMap()
console.log (echipe.flatMap (membru => ('/teams/' + membru) ));