es6

Co nowego wprowadził EcmaScript 6

Z artykułu dowiesz się:

  1. Co to jest Callback Hell i jak został usunięty w ES6
  2. Czym jest ES6
  3. Zobaczysz przykłady użycia EcmaScript6

Wprowadzenie

EcmaScript6 został wprowadzony w 2015 roku, jest to specyfikacja front-endowego języka, czyli JavaScriptu. ES6 wprowadził wiele nowości dzięki którym powstały nowe możliwości jakich język ten wcześniej nie miał, udoskonalono również starą składnię podnosząc poziom syntaxu JS’a. Mimo, iż ES6 jest już bardzo dobrze wspierany przez przeglądarki, to ciągle pozostaje mały procent przeglądarek, gdzie z nowa składnia występują problemy lub nie jest wspierana.

es6-caniuse
źródło: http://caniuse.com

Dziś powstały już paczki takie jak babel który pozwala kompilować składnię ES6 na starsza specyfikacje JS’a tak aby strony z użytą składnią ES6 mogły być poprawnie wyświetlane na wszystkich przeglądarkach, ale o tym może innym razem 🙂

Nowe deklarowanie zmiennych

W specyfikacji wprowadzono dwie deklaracje zmiennych, let oraz const. Wcześniej jedyną możliwością deklaracji zmiennej było słowo kluczowe var, jednak tworzyło to wiele “problemow” na których temat zalecam poczytać np.
Tu: https://discuss.codecademy.com/t/whats-wrong-with- var/224975/2 Warto zaznaczyć ze let i const nie podlegają hoistingowi (w przeciwieństwie do var) czyli przeniesieniu deklaracji zmiennej na początek programu przed jego wykonaniem.

Console.log(x); // Output - undefined
Console.log(y); // Output - ReferenceError
Var x = “var”;
Let y = “let”;

Można to interpretować w taki sposób:

var x;
console.log(x); // Output - undefined
console.log(y); // Output - ReferenceError
x = “var”;
let y = “let”;

Zmienne let oraz const maja zasięg blokowy czyli zadeklarowane w klamrach { } nie istnieja poza nimi (w tzw. niższym zakresie). Zmienna var posiada zasięg globalny.

{
    var x="var";
    let y="let";
    const z="const";
}
console.log(x); // Output - “var”
console.log(y); // Output - ReferenceError – y nie istnieje
console.log(z); // Output - ReferenceError - z nie istnieje

Nowe typy zmiennych nie mogą ulec także podwójnej deklaracji w przeciwieństwie do zmiennych var:

// Pierwsza deklracja
var x="var";
let y="let";
const z="const";
// Druga deklaracja
var x="vvar";
let y="vlet"; // Output – SyntaxError - zmienna już
zadeklarowana
const z="vconst"; // Output – SyntaxError - zmienna już
zadeklarowana
console.log(x); // Output - "vvar"

Const czyli zmienna typu stałego, chroni wartość przypisana do danej nazwy i nie pozwala na jej zmianę:

const x="const";
x="not const"; // Output – TypeError

Nieco inaczej działa to w przypadku tablic, ponieważ zastrzegamy sobie tylko nazwę dla tablicy w przestrzeni nazw, a wartości tablicy możemy dowolnie zmieniać, dodawać.

const x=[1,2,3];
x.push(4);
x[0] = 0;
console.log(x); // Output - [0, 2, 3, 4]
x= [1,2,3]; // Output - SyntaxError

Każda próba nadpisania tablicy x da Syntaxerror

Funkcja strzałkowa => arrow function

Nowa specyfikacja przyniosła także nowy krótszy zapis funkcji
idealnie nadający się do funkcji callback.

// Stary zapis
function add(x,y){
    return x+y;
}
// Nowy zapis
const add = (x,y) => {
    return x+y;
}

Możemy jeszcze bardziej skrócić nowy zapis, jeżeli mamy jeden argument (niepotrzebne nawiasy) lub funkcja tylko coś zwraca (niepotrzebne klamry):

const add = x => x + 10;

Użycie funkcji strzałkowej nie tworzy wiązania this, które tutaj nie wskazuje miejsca, w którym został wywołany, zostaje mu przypisany kontekst zewnętrzny, czyli obiekt window.

const x = {
    name: "Mateusz",
    showName: function() {
        return `${this.name}`;
    }
};

console.log(x.showName());
// Output - "Mateusz"

const y = {
    name: "Mateusz",
    showName: () => this.name
}
console.log(y.showName())
// Output zwróci  wartość window.name

Lekarstwo na tzw. Callback hell czyli
obiekt promise.

Zacznijmy od wyjaśnienia czym jest piekło wywołań zwrotnych, czyli tzw.callback hell. Jest to po prostu wielokrotne zagnieżdżenie w sobie wywołań zwrotnych.

Callback hell powstaje najczęściej, gdy pracujemy z asynchronicznością JS’a, dlatego ES6 wprowadziło Promisy aby pomoc usprawnić prace z kodem a zarazem utrzymać jego czytelność i jakość. Najłatwiej zasadę działania obiektu promise będzie nam zrozumieć na przykładzie:

const data = [];

function readData1(nextTask) {
    setTimeout(() => {
        data.push("data1");
        nextTask();
    }, 1000) // Symulacja wczytywania danych przez 1s
}

function readData2(nextTask) {
    setTimeout(() => {
        data.push("data2");
        nextTask();
    }, 1000)
}

function showData() {
    alert(data);
}

// Pobieramy nasze dane w ustalonej kolejnosci

readData1(function() {
    readData2(function() {
        showData(); // Powstaje tzw. callback hell
    });
});

Gdybyśmy dorzucili jeszcze parę callbackow nasz kod bardzo straciłby na
czytelności, dlatego z pomocą przychodzi obiekt promise. Zobaczmy, jak możemy przykładowo zapisać ten sam kod prościej:

const data = [];

function readData1() {
    return new Promise((resolve, reject)=>(setTimeout(() => {
        data.push("data1");
        resolve();
    }, 1000))) // Symulacja wczytywania danych przez 1s
}

function readData2() {
    return new Promise((resolve, reject)=>(setTimeout(() => {
        data.push("data2");
        resolve();
    }, 1000)))
}

// Pobieramy nasze dane w ustalonej kolejności
readData1()
    .then(readData2)
    .then(()=>{
        alert(data)
    })
    .catch(error => console.error(error))

Jak widzimy każda funkcja zwraca obiekt Promise. Gdy wykonywana jest funkcja Resolve, przechodzimy do następnej zaplanowanej funkcji. Reject to callback który służy do określenia zachowania w razie błędu, np. podczas wczytywania pliku. W razie, gdyby taki błąd wystąpił mamy przygotowaną jeszcze funkcje catch, która zareaguje w razie błędu callbackiem.
Zagadnienie związane z obietnicami jest dużo rozbudowane, przytoczyłem tylko z mniejsza czym są promisy, polecam poczytać więcej o callback hell jak i używaniu promisów.

Nareszcie Klasy

Wraz z EcmaScript6 do JS’a wprowadzono klasy, nawet nie do końca
wprowadzono, ponieważ był już to znany mechanizm w JavaScripcie. Nowa składnia dla klas pozwala nam pisać czystszy,” piękniejszy” kod.

Class Human{

// Tworzymy konstruktor dla klasy
    constructor(name, age){ 
        this.name = name;
        this.age = age;
        this.about = function() {
            console.log(‘Imie: ’ + this.name + “, wiek: ” + 
    this.age)
        }
    }
}

Ważnym aspektem nowej składni jest możliwość dodania do prototypu klasy metody bezpośrednio w klasie.

Class Human{
    constructor(name, age){
        this.name = name;
        this.age = age;
        this.about = function() {
            console.log(‘Imie: ’ + this.name + “, wiek: ” + 
            this.age);
        }
    }

    sayHi(){ // metoda ta należy do prototypu tej klasy
        Console.log(“Hi from “+this.name+”!”);
    }
}

Dodatkowo w klasach dodano także machizm dziedziczenia dzięki instrukcji extends. Funkcja super pozwala nam odwołać się do kodu klas z których dziedziczymy. Super musi być wywołane przed pierwszym użyciem this’a w konstruktorze, inaczej otrzymamy error.

Class Man extends Human{
     constructor(name, age, strength){
         super(name, age);
         this.strength = strength;
     }
 }

Operator potęgowania

Przed ES6, aby spotęgować liczbę musieliśmy użyć obiektu Math:

let pow = Math.pow (5,2);
console.log(pow) // Output – 25

//Teraz możemy osiągnąć to samo używając nowego operatora potęgowania

let pow = 5 ** 2;
console.log(pow) // Output – 25

Domyślne wartości parametrów

Webdeveloperzy końcu otrzymali możliwość definiowani domyślnych
wartości parametrów
wywołania co daje większe możliwości kontroli
błędów wykowanych brakiem informacji dostarczonych do funkcji:

const example = (x, y = 10) => {
    return x + y;
}

Reszta zmian

Nie są to wszystkie zmiany jakie oferuje nam EcmaScript6 ale na pewno jedne z najważniejszych. Po pełną specyfikację zmian jakie nastąpiły odsyłamy tutaj:
http://es6-features.org/#Constants
http://exploringjs.com/es6/

Znajomość ES6 jest dziś niezbędna by odnaleźć się w front-endzie oraz ubiegać się o prace nawet jako junior web developer.