ES6 principali novità introdotte – javascript

Nel 1995 da NETscape fu creato JavaScriptECMA significa European Computer Manufacturer Association ed è il corpo che fornisce le specifiche ECMAScript per le implementazioni JavaScript nei browser. Lo scopo è quello di definire degli standard per Javascript.
Così nel 1997 furono rilasciate le specifiche del linguaggio ECMAScript 1, successivamente ES2 e ES3, mentre il 4 fu studiato ma mai rilasciato, quindi nel 2009 fu rilasciato ES5 (furono introdotti i foreach, le map function e i filtri) e nel giugno del 2015 ES6.
Vedremo solo alcune delle novità introdotte da ES6, altre le tratteremo a parte, le novità sono veramente tante per parlarne tutte qui:

  • Un capitolo importante saranno le promise, chiamate tramite fetch, async-await
  • Le classi e l’ereditarietà
  • I moduli che ci consente di dividere la nostra applicazione in singoli file javascript isolati uno dall’altro non più globali come in passato

Contents

Let e const

Qui andiamo a gestire la visibilità delle variabili, con var la variabile viene vista in tutto l’ambiente in cui viene dichiarata, questo era l’unico modo prima di dichiarare una variabile. Infatti se dichiaro la variabile in un blocco in questo modo:

{
    var test = 'Massimiliano';
}

document.getElementsByTagName('body')[0].innerHTML = test;

Usciti dal blocco avremo ancora disponibile il valore della variabile. Con il let invece questo valore non sarà disponibile e lo possiamo verificare direttamente in questo modo:

{
    let test = 'Massimiliano';
}

document.getElementsByTagName('body')[0].innerHTML =
typeof test !== 'undefined' ?
test : 'Qui non si legge la variabile test perchè let';    

Questo problema possiamo averlo ad esempio in un blocco for come questo:

for(let i=0; i<10; i++){

}
console.log(i);

Finito il ciclo fuori la variabile i sarà presente e sarà 10, con let invece la variabile non risulterebbe dichiarata fuori dal ciclo e quindi javascript ci restituirà un errore, la variabile i è definita in questo modo solo all’interno delle parentesi graffe.
Altra caratteristica del var è che possiamo ridichiarare la stessa variabile in più parti del nostro codice, sia a livello globale che all’interno di blocchi, in questo modo:

var mar = "Marte";
console.log(mar);
var mar = "non è vero";
console.log(mar);

Con il let invece se ridichiaro una variabile con lo stesso nome in uno stesso campo di visibilità avrò un errore, quindi il seguente codice genererà un errore:

let mar = "Marte";
console.log(mar);
let mar = "non è vero";
console.log(mar);

Const invece, seppur funzioni allo stesso modo di let a livello di visibilità, serve per dichiarare una variabile che non può essere riassegnatanon è possibile quindi fare un nuovo assegnamento. Con const la variabile non può essere riassegnata, in questo modo il dato è protetto. Se infatti proveremo ad assegnare alla variabile un’altro valore, ci troveremo di fronte ad un errore di questo tipo: “Uncaught TypeError: Assignment to constant variable“. Facciamo un piccolo esempio:

const testC = 'Massimiliano';
console.log(testC, 'const');

Abbiamo inizializzato testC come una costante, non avremo in console alcun errore, e avremo la nostra stampa senza nessun problema, ora proviamo a cambiare il valore della variabile aggiungendo subito dopo:

testC = 'Mario';

A questo punto l’errore sarà inevitabile, non possiamo riassegnare un valore a una costante. Anche se andassimo a rinizializzare la variabile in questo modo:

var testC = 'Mario';

Ciò causerebbe un errore di questo tipo “Uncaught SyntaxError: Identifier ‘testC’ has already been declared”.
Ma attenzione le costanti non sono immutabili, infatti se abbiamo un oggetto o un array queste possono essere mutate. Se vado a creare un oggetto in questo modo:

const testC = {
    name: 'Massimiliano',
    surname: 'Salerno'
};

Non avrò la possibilità di riassegnare alla variabile l’oggetto, ma potrò modificare le proprietà dell’oggetto, infatti ad essere immodificabile è il riferimento non il valore:

// questo posso farlo
testC.name = 'Mario';
//questo causerebbe un errore
testC = {};

Con var l’inizializzazione delle variabili viene inoltre portata in testa (proprio come avviene per le funzioni se non le assegno a una variabile), quindi se scrivo nel seguente modo, avrò come output ‘Massimiliano’:

console.log(name);
var name = 'Massimiliano';

Con let o const invece avremo un errore ‘name is not defined‘, perchè sino a che non viene dichiarata non avremo visibilità della variabile:

console.log(name);
let name = 'Massimiliano';

Arrow Function o funzioni freccia

E questa è una delle novità più amate di ES6, si tratta di un nuovo metodo per scrivere funzioni che oltre ad essere più breve presenta grandi vantaggi. Andiamo a prendere questo semplice esempio di codice:

let newObj = {
    name : 'Massimiliano',
    surname: 'Salerno',
    array: [5, 6, 8, 9, 15],
    print: function () {
        console.log(this.name + ' ' + this.surname);
        setTimeout(function () {
            console.log('avviata la nostra funzione');
        }, 5000);
    },
    printArray: function () {
        this.array.forEach(function (ele) {
            console.log(ele);
        })
    }
};

newObj.print();
newObj.printArray()

Andiamo a definire un oggetto che ha al suo interno name, surname ed un array più due funzioni print che stampa il nome e il cognome, e un setTimeout che dopo 5 secondi va a stampare una stringa al quanto semplice ‘avviata la nostra funzione’. Mentre printArray si occuperà di fare un semplice forEach.
Ora immaginiamo di dover stampare il nostro nome e cognome all’interno del setTimeout, e immaginiamo di voler stampare ogni numero dell’array che scorriamo nel forEach accanto al nostro nome, non possiamo fare in questo modo:

let newObj = {
    name : 'Massimiliano',
    surname: 'Salerno',
    array: [5, 6, 8, 9, 15],
    print: function () {
        setTimeout(function () {
            console.log(this.name + ' ' + this.surname);
            console.log('avviata la nostra funzione');
        }, 5000);
    },
    printArray: function () {
        this.array.forEach(function (ele) {
            console.log(ele + ' ' + this.name);
        })
    }
};

newObj.print();
newObj.printArray()

Infatti non avremo la possibilità di accedere al this riferito all’oggetto, e quindi dovremmo scrivere in questo modo:

let newObj = {
    name : 'Massimiliano',
    surname: 'Salerno',
    array: [5, 6, 8, 9, 15],
    print: function () {
        setTimeout(function () {
            console.log(this.name + ' ' + this.surname);
            console.log('avviata la nostra funzione');
        }, 5000);
    },
    printArray: function () {
        this.array.forEach(function (ele) {
            console.log(ele + ' ' + this.name);
        })
    }
};

newObj.print();
newObj.printArray();

Ecco qui, che dobbiamo salvare il dato dell’oggetto in una variabile che può essere vista all’interno della funzione dichiarata nel setTimeout oppure nel foreach.
Con un sistema simile potevamo mettere in una variabile il this, in questo modo:

newObj = {
    name : 'Massimiliano',
    surname: 'Salerno',
    array: [5, 6, 8, 9, 15],
    print: function () {
        var self = this;
        setTimeout(function () {
            console.log(self.name + ' ' + self.surname);
        }, 5000);
    },
    printArray: function () {
        var self = this;
        this.array.forEach(function (ele) {
            console.log(self.name + ': '+ele);
        })
    }
};

O ancora potevamo usare il bind in questo modo:

newObj = {
    name : 'Massimiliano',
    surname: 'Salerno',
    array: [5, 6, 8, 9, 15],
    print: function () {
        setTimeout(function () {
            console.log(this.name + ' ' + this.surname);
        }.bind(this), 5000);
    },
    printArray: function () {
        this.array.forEach(function (ele) {
            console.log(this.name + ': '+ele);
        }.bind(this))
    }
};

Bene, guardate la stessa cosa fatta con le arrow functions:

let newObj = {
    name : 'Massimiliano',
    surname: 'Salerno',
    array: [5, 6, 8, 9, 15],
    print: function () {
        setTimeout( () => {
            console.log(this.name + ' ' + this.surname);
        }, 5000);
    },
    printArray: function () {
        this.array.forEach(ele => {
            console.log(this.name + ': '+ ele);
        })
    }
};

Quando non ci sono parametri o quando c’è più di un parametro ci vogliono le parentesi tonde, poi c’è l’arrow function (=>) e a questo punto tra parentesi graffe mettiamo il nostro codice, potete tranquillamente vedere che ora abbiamo disponibile il nostro this. Questo perchè le funzioni arrow non hanno un this proprio ma il this dello scope dove sono dichiarate.
Se una funzione prende una sola riga posso tranquillamente togliere le parentesi graffe in questo modo:

// Funzione con nessun parametro in ingresso
var func = () => console.log('test');
// Funzione con un parametro in ingresso
var func = test => console.log(test);
// Funzione con più parametri in ingresso
var func = (test, test2) => console.log(test, test2);

Non basta questo se c’è un unica riga, e quindi non servono le parentesi graffe abbiamo automaticamente il return come in questo caso:

var func = (test, test2) => test + ' ' + test2;
console.log(func('Massimiliano', 'Salerno'));

Come vedete abbiamo evitato di scrivere function, di aggiungere le parentesi graffe e il return, tutto molto più sintetico.

Operatori spread

Questo trasforma l’elemento di un array in argomenti di una funzione o in elementi di un array. Ad esempio immaginiamo di avere un array di cose da comprare. Vogliamo passarle a una funzione e stamparle in console, possiamo fare qualcosa del genere:

var array = ['Patate', 'Zucchine', 'Carote'];
function test (){
    if(arguments.length){
        console.log('Lista della spesa');
        for(let i = 0; i < arguments.length; i++){
            console.log('Prodotto: ' + arguments[i]);
        }
    }
}

test(...array);

Abbiamo creato il nostro array e la nostra funzione che scorrerà i parametri passati tramite arguments e li stamperà in console. Per passare n parametri alla funzione test abbiamo usato l’operatore spread, la variabile array preceduta dai tre punti andrà a passare alla funzione ogni elemento come parametro.
Chiaramente l’array potrebbe essere anche più complesso, essere un array di oggetti, il risultato sarebbe lo stesso:

var array = [
    {
        name: 'Patate',
        qt: '5Kg'
    },
    {
        name: 'Zucchine',
        qt: '1Kg'
    },
    {
        name: 'Carote',
        qt: '1Kg'
    },
];
function test (){
    if(arguments.length){
        console.log('Lista della spesa');
        for(let i = 0; i < arguments.length; i++){
            console.log('Prodotto: ' + arguments[i].name);
            console.log('Quantità: ' + arguments[i].qt);
            console.log(' ');
        }
    }
}

test(...array);

Vediamo ora la seconda parte, la trasformazione in elementi dell’array. Modifichiamo il nostro codice in questa maniera:

var array = [
    {
        name: 'Patate',
        qt: '5Kg'
    },
    {
        name: 'Zucchine',
        qt: '1Kg'
    },
    {
        name: 'Carote',
        qt: '1Kg'
    },
];
var fruit = [
    {
        name: 'Fragole',
        qt: '1Kg'
    },
    {
        name: 'Banane',
        qt: '1Kg'
    },
    {
        name: 'Ciliegie',
        qt: '2Kg'
    },
];

var arrayPrint = [
    {
        name: 'Salmone',
        qt: '1Kg'
    },
    ...fruit,
    {
        name: 'Cozze',
        qt: '1Kg'
    },
    ...array
];
function test (){
    if(arguments.length){
        console.log('Lista della spesa');
        for(let i = 0; i < arguments.length; i++){
            console.log('Prodotto: ' + arguments[i].name);
            console.log('Quantità: ' + arguments[i].qt);
            console.log(' ');
        }
    }
}

test(...arrayPrint);

Abbiamo dichiarato tre array nell’ultimo però abbiamo fatto due array merge, inserendo i nostri due array tramite l’operatore spread proprio nel punto in cui volevamo aggiungere i nostri elementi.

Parametri di default alle funzioni

Ci consente di settare dei parametri di default per le nostre funzioni, quindi possiamo fare qualcosa di questo genere:

function sum(a=1, b=0){
    return a + b;
}
console.log(sum()); //1
console.log(sum(3)); //3
console.log(sum(3, 2)); //5

Senza aver settato i parametri di default, quelli non settati sarebbero stati undefined e il risultato della summa sarebbe stato un NAN.

Template Literals

Questa novità agevola di molto la gestione delle stringhe, le stringhe possono andare a capo senza problemi e la semplicità di aggiungervi variabili è impressionante.
Prima di queste novità per creare una stringa html da mettere in pagina dovevamo fare su per giù in questo modo:

var object = {
    name: 'Massimiliano',
    surname: 'Salerno'
}
var html = "<ul>" +
    "<li>"+object.name+"</li>" +
    "<li>"+object.surname+"</li>" +
    "</ul>"
console.log(sum(3, 2)); //5

Direi non proprio comodissimo, certo si poteva mettere su un unica riga tutta la stringa, ma sarebbe stata difficilmente leggibile, oppure si poteva ancora risolvere in questo modo:

var html = '<ul>';
html += ' <li>' + object.name + '</li>';
html += ' <li>' + object.surname + '</li>';
html += '</ul>';
document.getElementsByTagName('body')[0].innerHTML = html;

Anche questo metodo è abbastanza confusionario, soprattutto perchè stiamo stampando solamente una lista di due elementi, senza classi, attributi o altri elementi, il tutto normalmente diventa molto più confusionario.
Con E6 abbiamo le stringhe template, grazie al carattere backtick(`), ora possiamo scrivere così:

var html = `	 	
    <ul>
    <li>Nome: ${object.name}</li> 
    <li>Cognome: ${object.surname}</li>
</ul>`;
document.getElementsByTagName('body')[0].innerHTML = html;

Tutto risulta molto più semplice e ordinato. Con Linux è semplicissimo ottenere il backtick, basta premere AltGr e  con windows invece bisognerà, tenendo premuto il tasto alt, digitare 0092, con mac invece potremmo utilizzare AltGr e 9.
Come vediamo possiamo andare a capo, mettere apici o doppi apici senza nessun problema, e posso inserire codice javascript, qualsiasi codice tra le parentesi graffe precedute da un $.
Andiamo ad aggiornare il nostro codice rendendolo più divertente, sfruttiamo il fatto di poter inserire espressioni javascript, allora facciamo una semplice addizione, modifichiamo il nostro codice in questo modo:

let object = {
    name: 'Massimiliano',
    surname: 'Salerno',
    points: 35
}
let additionalPoints = 5;
var html = `
     <ul>
     <li>Nome: ${object.name}</li>
     <li>Cognome: ${object.surname}</li>
     <li>Punteggio aggiornato: ${object.points + additionalPoints}</li>
     </ul>`;
document.getElementsByTagName('body')[0].innerHTML = html;

Abbiamo aggiunto all’oggetto un altro parametro che si chiama points e in visualizzazione abbiamo aggiunto il contenuto di una variabile con dei punti da aggiungere al punteggio realizzato sino a quel momento, questa variabile si chiama additionalPoints.
Ma ancora una volta non è finita qui, anche se ciò di cui andremo a parlare adesso penso che ci potrà essere utile ben poche volte, ma possiamo gestire la nostra stringa in questo modo:

var html = processing`
     <ul>
     <li>Nome: ${object.name}</li>
     <li>Cognome: ${object.surname}</li>
     <li>Punteggio aggiornato: ${object.point + additionalPoints}</li>
     </ul>`;
document.getElementsByTagName('body')[0].innerHTML = html;
function processing(arrayString, ...params ) {
    console.log(arrayString);
    console.log(params);
    var finalString = '';
    arrayString.forEach((ele, i) =>{
        finalString += ele;
        if(params && params[i]){
            finalString += params[i];
        }
    });
    return finalString;
}

Abbiamo passato alla funzione processing i parametri della stringa, avremo come primo parametro un array di stringhe, tutti i parametri successivi andrebbero a prendere un elemento che abbiamo inserito tra le parentesi graffe precedute dal dollaro, noi però li mettiamo tutti insieme in un array a cui diamo il nome di params.
In questo caso stiamo andando semplicemente poi a riprodurre la stringa con un for, ma potremmo fare qualsiasi operazione, avendo diviso le stringhe dai parametri inseriti.

Destrutturare un array o un oggetto

Ci consente di mettere dentro variabili gli elementi di un array o di un oggetto:

let [a, b] = ['Massimiliano', 'Salerno'];
console.log(a);
console.log(b);

In questo caso stiamo andando a dichiarare due variabili a e b e gli assegnamo i valori all’interno dell’array, quindi quando andremo a stampare a e b in console, vedremo che a ha come valore Massimiliano, mentre b avrà Salerno.
Un modo ancora più valido di destrutturare un array è il seguente:

let array = ['Massimiliano', 'Salerno', 35];
console.log(...array);

Avremo stampate in console le varie voci dell’array, quindi immaginatevi la forza di tutto ciò se dovessimo passare n parametri a una funzione.
Come dicevamo la stessa cosa si può realizzare per un oggetto. Andiamo a riprendere l’oggetto che abbiamo creato prima:

let object = {
    name: 'Massimiliano',
    surname: 'Salerno',
    point: 35
};

E ora mettiamo che ci servano di questo oggetto solo due variabili che sono nome e cognome, possiamo andarle a prenderle in questo modo:

let {name, surname} = object;
console.log(name, surname);

A questo punto avremo due variabili name e surname che avranno il valore delle proprietà all’interno dell’oggetto. Ma se volessi cambiare il nome perchè vorrei che la variabile si chiamasse lastName invece di surname? niente di più semplice:

let {name, surname : lastName} = object;
console.log(name, lastName);

Allo stesso modo potremmo fare l’inverso, avendo una serie di variabili, per metterle dentro un oggetto, prima di ES6 avremmo fatto così:

var name = 'Massimiliano';
var surname= 'Salerno';
var array= [5, 6, 8, 9, 15];
console.log({name: name, surname: surname, array: array});

Ora potremmo invece più semplicemente scrivere così:

var name = 'Massimiliano';
var surname= 'Salerno';
var array= [5, 6, 8, 9, 15];
console.log({name, surname, array});

Automaticamente il nome della variabile diventa quello della proprietà e a quest’ultima viene assegnato il valore della variabile.
Ok, ma se dovessimo prendere delle proprietà più interne dell’oggetto? proviamo a modificare in questo modo il nostro oggetto:

let object = {
    name: 'Massimiliano',
    surname: 'Salerno',
    point: 35,
    address: {
        city: 'Roma',
        address: 'Piazza Re di Roma, 3',
        cap: 00100
    }
};

let {address: {city = 'Napoli', address}} = object;
console.log(city, address);

Ora vogliamo accedere a city e address e possiamo farlo in questo modo, possiamo anche dare un valore di default a city, quindi se questa non sarà presente, automaticamente la variabile city sarà valorizzata con la stringa ‘Napoli’, per vericarlo possiamo andare a commentare la proprietà city, vedremo che sulla console avremo stampato Napoli e non più Roma.

address: {
    //city: 'Roma',
    address: 'Piazza Re di Roma, 3',
        cap: 00100
}

let {address: {city = 'Napoli', address}} = object;
console.log(city, address);

Possiamo tranquillamente aumentare i livelli di profondità senza nessun tipo di problema, in questo modo:

let object = {
    name: 'Massimiliano',
    surname: 'Salerno',
    point: 35,
    address: {
        location: {
            city: 'Roma',
            country: 'Italia'
        },
        address: 'Piazza Re di Roma, 3',
        cap: 00100
    }
};

let {address: {address, location:{city}}} = object;
console.log(city, address);

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *