ECMAScript 6, avagy a JavaScript következő verziójának újdonságai
Persze a cím nem teljesen pontos, hiszen a JavaScript csak egy implementációja az ECMAScript szabványnak (például az ActionScript és a JScript mellett), de mivel a legnépszerűbb, ezért talán ennyi igazán megbocsájtható. A szabvány soron következő, 6-os verziója, amely idén júniusban válik véglegessé, 2009 óta az első frissítés, és számos érdekes újdonságot tartalmaz. Ebben a posztban ezek közül mutatom be a legfontosabbakat, és arra is kitérek, miként használhatjuk ezeket már ma is.
A => jelölés
A =>
egy új, rövidebb függvényjelölés (a funkciója hasonló a C#-os megfelelőjéhez). Bár a nyíllal függvényeket deklarálunk, ezek mégsem teljesen egyenértékűek a hagyományos függvényekkel. A legfontosabb különbség talán az ún. lexikális this
: a this
pointer értéke itt nem attól függ, hogy hol használjuk a függvényt, hanem attól, hol definiáltuk. Fontos még megjegyezni, hogy ezek a függvények nem használhatók konstruktorként a new
kulcsszóval, ill. az arguments
objektum sem áll a rendelkezésünkre.
Nézzünk egy tipikus példát anonim függvénnyel, először ECMAScript 5-ben:
var numbers = [1, 5, 11];
var plusOne = numbers.map(function(num) {
return num + 1;
});
Ugyanezt megtehetjük az új szintaxissal is, némileg tömörebben:
var numbers = [1, 5, 11];
var plusOne = numbers.map(num => num + 1);
A nyíl bevezetésének egyik elsődleges célja a this
használatából eredő gyakori hibák számának csökkentése, de emellett optimalizációs célokat is szolgál.
Osztályok
A JS világába más nyelvekből érkezőknek gyakran gondot okoz, hogy nincs klasszikus osztályalapú objektum-orientáció, ehelyett prototípusokkal dolgozhatunk (aminek valójában a megszokott megközelítés egy részhalmaza, tehát a nyelv kifejezőbb a hagyományos OOP nyelveknél, ennek ellenére szokatlan lehet).
Pontosan emiatt az ECMAScript 6 bevezet egy, a népszerű nyelvekből (Java, C#) már jól megszokott osztálydeklarációs szintaxist. Így most már akár ilyesmit is alkothatunk majd:
class Student extends Person {
constructor(name, school) {
super(name);
this.school = school;
}
getSchool() {
return this.school;
}
}
Az új kulcsszavak csak egyfajta vékony szintaktikai rétegként szolgálnak a prototípusok felett, de egyszerűbbé teszik a gyakori osztályminták használatát. Támogatott az öröklés, a super() hívások, konstruktorok és statikus metódusok is.
Template stringek
A JavaScriptben a string típus számos alapvető hátránnyal bír — nincsenek többsoros stringek, az alapvető formázás is nehézkes, és nincs triviális módja a stringek HTML-biztossá tételének (az injection típusú támadások elkerülése végett). Főként ezeket hivatott orvosolni ez az új nyelvi elem.
A template stringek alapvetően hagyományos testvérükhöz hasonlóan használandóak azzal a kivétellel, hogy "visszafelé-idézőjelek" (`
) közé kell tenni őket:
var message = `Hello World!`;
Fontos megjegyezni, hogy a message
változó típusa továbbra is string
, ez a szintaxis egyfajta preprocesszorként is felfogható. Nézzünk valami izgalmasabbat.
var message = `Ez egy
több
soros
szöveg.`;
A template stringek másik új tulajdonsága a dollárjel, amely helyettesítést jelöl:
var firstName = 'Gábor';
var message = `Szia, ${firstName}`;
A legerősebb újítás azonban az ún. tagek, amik tulajdonképpen függvények, melyekkel az előbb említett előfeldolgozási folyamat testreszabható. Például:
var message = myTag`ez egy szöveg`;
A myTag
itt egy általunk definiált függvény, amely a template string darabjait kapja meg paraméterül, és egy hagyományos stringet kell visszaadnia. Ez rengeteg lehetőséget rejt magában, és sok esetben biztonságosabbá teheti a kódunkat.
Szimbólumok
A szimbólumok alapvetően a privát objektumváltozók implementálására jöttek létre, amit a JavaScript fejlesztők régóta szerettek volna a nyelvben látni. Akármilyen elnevezési konvenciót is választunk, a privátként használt változók mindig hozzáférhetőek lesznek stringekkel. Nézzük az alábbi példát ECMAScript 5-ben:
function MyClass(privateData) {
this.privateData = privateData;
}
MyClass.prototype = {
getPrivateData: function() {
return this.privateData;
}
};
var c = new MyClass("valami");
Hiába szántuk a privateData
-t privátnak, az hozzáférhető lesz a c["privateData"]
szintaxison keresztül. Ez elkerülhető szimbólumokkal, amelyeket a Symbol
kulcsszóval definiálunk:
var privateData = Symbol("privateData");
function MyClass(privateData) {
this[privateData] = privateData;
}
(...)
Az egyetlen paraméter opcionális; elhagyása esetén a szimbólum azonos nevű lesz a változóval (itt elhagyhattuk volna).
Iterátorok és generátorok
Az iterátor objektum egy teljesen hagyományos objektum, amely (hasonlóan más nyelvekhez) implementálja a next()
metódust. Ennek egy két mezővel rendelkező objektumot kell visszaadnia, ezek a value
, amely az iterálandó lista következő elemét tartalmazza, a done
pedig egy boolean változó, amely akkor igaz, ha a lista végére értünk. Egy így létrehozott myIterator
nevű objektum a for..of
szintaxissal használható (a for..in
-nel analóg módon):
for (var i of iterator) {
console.log(i);
}
Iterátorokat létrehozni ez alapján viszonylag egyszerű, de fáradságos és repetitív is. Pontosan itt jönnek a képbe a generátorok. A generátor egy olyan speciális függvény, ami egy iterátort ad vissza. Ezekhez két új nyelvi elem ad segítséget: a function *
azt jelöli, hogy a függényünk egy generátor, a yield
-del pedig definiálhatjuk a next()
meghívásakor visszaadandó értéket. Például egy generátor, ami egy iterátort ad vissza a Fibonacci számsorozathoz:
var createFibonacci = function *() {
var pre = 0, cur = 1;
for (;;) {
var temp = pre;
pre = cur;
cur += temp;
yield cur;
}
}
Ezt a generátort aztán használhatjuk is, írjuk ki a sorozat első ezer tagját:
var iterator = createFibonacci();
for (var n of iterator) {
if (n > 1000)
break;
print(n);
}
Az ECMAScript 6 számos előre definiált iterátort is tartalmaz gyakran használt elemekhez (tömbök, objektumok, mapek, stb.).
Összegzés
Ez persze csak a jéghegy csúcsa, az új szabvány számos más jobbnál jobb újdonságot is tartogat, ezekről egy nagyon jó és magyarázó összefoglaló található az ingyenes Understanding ECMAScript 6 c. könyvben.
Az ECMAScript 6-ot a legújabb böngészők már részben támogatják, aki azonban már most teljeskörűen használná, annak érdekes lehet a 6to5 nevű projekt, ami az ECMAScript 6-ban megírt programokat ECMAScript 5-re írja át, így az bárhol futtathatóvá válik.