Blog

Le basi di JavaScript: VAR vs LET vs CONST

Se non hai mai sentito parlare di Hosting nel linguaggio JavaScript o non conosci nel dettaglio le differenze tra Var, Let o Const, ma ti interessa particolarmente imparare Javascript… beh, ti conviene proprio continuare a leggere!

In quest’articolo parliamo di una delle domande da colloquio di lavoro come sviluppatore front end. Un argomento tanto semplice quanto di fondamentale importanza nella conoscenza di JavaScript.

Iniziamo!

Introduzione a Var

Dichiarare qualcosa usando Var era l’unico modo possibile prima dell'introduzione di ES6

La sua principale caratteristica la si ritrova nella possibilità’ di poter ridichiarare e aggiornare un valore senza problemi. 

Per entrare nel dettaglio riprendiamo la definizione ufficiale di MDN:

“The var statement declares a function-scoped or globally-scoped variable, optionally initializing it to a value.” 

Il function-scoped o scope interno della funzione, si riferisce al fatto che JavaScript crea un nuovo scope ogni qualvolta si crea una funzione. In parole povere ogni cosa dichiarata dentro una funzione non è accessibile dall’esterno.

Esempio:

 

function logSomething() {
   var something = 'prova';
   }
   console.log(something);
   //Uncaught ReferenceError: something is not defined"

Se invece di dichiarare la variabile dentro la funzione, l’avessimo fatto globalmente, ossia all’esterno del blocco, si sarebbe parlato di globally-scoped o scope globale. Essere accessibile globalmente significa poter essere letti e modificati in qualsiasi punto dello script.    
 

var something = 'prova global scope';
function logSomething() {
   var something = 'prova function scope';
   }
   console.log(something);
   // --> "prova global scope"

 

Come potete vedere, all’interno della funzione é stato possibile ridichiarare la stessa variabile, senza incorrere in nessun errore. Proprio perché Var é gestita con il function-scope e quindi lo scope della funzione é separato ed indipendente!

Un’altra caratteristica fondamentale é che tutto ciò che viene dichiarato con Var, viene gestito con un processo che prende il nome di Hoisting.

Un processo di fondamentale importanza che non tutti gli sviluppatori JavaScript alle prime armi conoscono e che, purtroppo, ha portato (insieme ad altre sue caratteristiche intrinseche) ad aumentare l’astio verso questo linguaggio di programmazione; specialmente tra chi proviene da un linguaggio Server side.

In poche parole, l’interprete di JavaScript non fa altro che portare al top dello script tutto quello che trova dichiarato con Var. Quindi, prima ancora di eseguire qualcosa, l’interprete legge lo script, cerca Var e trasferisce solo la dichiarazione e non l’inizializzazione della variabile. Cosa vuol dire?

Prendiamo il seguente esempio:
 

console.log(prova);
console.log('ancora in corso...');
// undefined (nota: no ReferenceError)
// ancora in corso...
var prova = 'prova';
console.log(prova);
console.log('ancora in corso...');
// "prova"
// ancora in corso...

 

Come puoi vedere dalla riga 1, il valore di default é sempre undefined; l’inizializzazione avviene, poi, alla riga 3 ed, infatti, il log della riga 4 stampa correttamente il valore.

Un’ultima chicca: tutto quello che viene dichiarato globalmente in JavaScript viene automaticamente aggiunto come proprietà dell’oggetto window.

Esempio:
 

var prova = 'prova';
console.log(prova);
//"prova"
console.log(window.prova)
//"prova"

 

Introduzione a Let e Const

Finora abbiamo parlato di scope globale e funzionale, cioè del corpo di una funzione. Secondo te, cosa stamperà il seguente esempio? 
 

var anni = 100;
if (anni > 12) {
   var anniTotali = anni * 7;
   console.log('Hai ${anniTotali} anni!'); // Hai 700 anni!
   }
   console.log(anniTotali) //--> ?????

 

Attenzione a non confondere il function-scope con il block scope.

La soluzione é questa: 

var anni = 100;
if (anni > 12) {
   var anniTotali = anni * 7;
   console.log('Hai ${anniTotali} anni!'); // Hai 700 anni!
   }
   console.log(anniTotali) // 700

 

La variabile anniTotali sarà accessibile esternamente perché é block scoped, ossia fa parte di uno scope delimitato da delle parentesi graffe e non da una funzione! 

È proprio per questo motivo che sono stati introdotti Let e Const.

Quindi, quali sono i loro benefici? 

Come abbiamo appena detto, Let e Const sono block-scoped… ma cos' é un blocco? Un blocco é semplicemente un set di parentesi graffe aperte e chiuse. 

Riprendiamo l’esempio di prima usando Let per dichiarare ed inizializzare anniTotali 

var anni = 100;
if (anni > 12) {
   let anniTotali = anni * 7;
   console.log('Hai ${anniTotali} anni!'); // Hai 700 anni!
   }
   console.log(anniTotali) //--> Uncaught ReferenceError: anniTotali is not defined

Ora, infatti, la variabile anniTotali genera un'eccezione in quanto risulta non definita.

L’esempio di sopra è valido per Let come per Const, generando la stessa eccezione:

var anni = 100;
if (anni > 12) {
   const anniTotali = anni * 7;
   console.log('Hai ${anniTotali} anni!'); // Hai 700 anni!
   }
   console.log(anniTotali) //--> Uncaught ReferenceError: anniTotali is not defined

Const, proprio come Let, è, infatti, block-scoped. 

La differenza tra Let e Const  é che una variabile definita con Const non può essere riassegnata o dichiarata nuovamente.

Riprendendo la definizione ufficiale di MDN:

“Constants are block-scoped, much like variables declared using the let keyword. The value of a constant can't be changed through reassignment, and it can't be redeclared.” 

Il seguente esempio chiarirà ogni dubbio:
 

const prova = 'Prova Constante';
console.log(prova); // 'Prova Constante'
prova = 'Nuovo assegnamento'; //Uncaught TypeError: Assignment to constant variable.

 

Const crea letteralmente una costante, quindi un valore che non deve cambiare nel tempo. Immaginiamo di trovarci in un progetto molto grande, in cui ci sono alcuni valori, come ad esempio delle variabili di ambiente, il basepath dei servizi REST o altre costanti come delle funzioni di utilità generale, che devono essere uguali per tutto il progetto; inoltre, normalmente le costanti sono sempre dichiarate in uppercase, quindi tutto in maiuscolo.

Prima dell’introduzione di Const, si poteva avere un risultato simile definendo una proprietà globale usando i metodi nativi degli oggetti di JavaScript, come Object.defineProperty.

Un esempio completo:

 

(function () {
   Object.defineProperty(window, "prova", {
     set: function (newValue) {
     var _this = this._prova;
     if(_this) {
       throw new Error('Questa è una costante, non puoi riassegnare il valore!');
     } else if(newValue) {
       this._prova = newValue;
     }
     },
     get: function (){
       return this._prova;
     }
   });
   prova = 'prova';
   console.log(window.prova); // "prova"
   prova = 'prova riassegnamento';
   console.log(window.prova) // Uncaught Error: Questa è una costante, non puoi riassegnare il valore!
 })();

 

senza entrare troppo nel dettaglio di questa implementazione, il metodo Set si occupa, semplicemente, di valorizzare una proprietà.

Il metodo Get invece restituisce il valore esistente… Tutto questo codice, dopo l’introduzione di ES6, viene sostituito con un semplice Const.

A questo punto, verrebbe da dire che sia Let che Const non siano soggette all’Hoisting, come si potrebbe evincere dal seguente esempio, dove proviamo a loggare a riga 5 la variabile definita con Let ottenendo quell’eccezione.

 

console.log(prova); // undefined
var prova = 'prova';
console.log(prova); // prova
console.log(provaConLet); // Uncaught ReferenceErrore: Cannot access 'provaConLet' before Initialization
let provaConLet = 'provaConLet';
console.log(provaConLet);

tuttavia non é proprio così…

L’interprete conosce tutte le variabili, anche quelle dichiarate con Const e Let, ma non permette l’accesso al loro valore prima della loro definizione. 

Questa zona viene chiamata in gergo tecnico Temporal Dead Zone.

Per provare quello che sto dicendo basta guardare il seguente esempio:

 

console.log(typeof variabileCheNonEsiste); // "undefined"
console.log(typeof prova); // cannot access 'prova' before initialization
let prova = "prova";

se la variabile prova non fosse soggetta all’hoisting avremmo avuto come risultato Undefined come a riga 1 dove proviamo a loggare una variabile mai definita.

Breve Recap generale:

Var:

  • scope funzionale (function scoped) oppure scope globale (globally-scoped);
  • Valore di default undefined;
  • Valori duplicati o dichiarazioni nuove identiche non generano errori;
  • soggette all’Hoisting e inizializzate con undefined.

Let:

  • Block scoped, la loro esistenza é limitata all’interno del blocco in cui sono dichiarate, il blocco é delimitato dalle parentesi graffe (ad esempio un loop, un if-else etc..);
  • accedere al loro valore prima della dichiarazione provoca un errore;
  • variabili duplicate nello stesso blocco generano errore;
  • non sono mai aggiunte come proprietà globali all’oggetto window.

Const:

  • Block scoped;
  • accedere al loro valore prima della dichiarazione provoca un errore;
  • variabili duplicate nello stesso blocco generano errore;
  • non possono essere dichiarate nuovamente;
  • non sono mai aggiunte come proprietà globali all’oggetto window.

Considerazione personale: L’introduzione di ES6 é un’aggiunta migliorativa del mondo JavaScript. L’utilizzo di Let e Const può solo spronare il programmatore informatico ad evitare possibili errori più o meno gravi che potrebbero verificarsi. 

Anche in fase di debugging, invece di avere valori anonimi come undefined, ci viene fornito un messaggio molto più dettagliato, ossia: “ReferenceError: x is not defined”.

Sicuramente molti developer old school o molti junior che si stanno affacciando al mondo del linguaggio JavaScript, preferiscono l’utilizzo di Var per la sua semplicità o perché non sanno nel dettaglio le sue differenze con Let e const.

Oggigiorno usare Let e Const é lo standard, e poi perché non sceglierlo se a fronte di una piccola modifica il codice migliora notevolmente? 

Grazie a tutti per lettura!

Articoli correlati

Il linguaggio HTML (Hypertext Markup Language) è uno dei più conosciuti e diffusi: lo si trova infatti praticamente in tutte le pagine web esistenti. È una scelta popolare tra i principianti che si…
Essere uno sviluppatore web vuol dire imparare più linguaggi di programmazione per poter creare diversi tipi di applicazioni.  Per ogni applicazione, la maggior parte delle volte, …
Un buon programmatore, si sa, necessita di un ampio bagaglio di conoscenze per potersi districare tra le difficoltà che questo mestiere comporta. Oggi le richieste sul mercato sono molteplic…
Un fattore importante e spesso sottovalutato per avere successo nel campo del web development è la capacità di fare buone domande e sapere dove trovare aiuto all’occorrenza. Quando Google non bast…
Le tecnologie legate all’intelligenza artificiale stanno facendo progressi rapidi, suscitando al tempo stesso non poche congetture. Da scenari distopici in stile 2001: Odissea nello spazio, passando…
Il settore tech è appannaggio esclusivo della popolazione maschile? Questo preconcetto è abbastanza diffuso, ma come stanno davvero le cose? Oggigiorno il mondo tech, non solo in Italia, è in gran …

Seguici su Facebook

Scopri di più sul corso Hackademy

Inizia la tua nuova carriera nel mondo digital e tech.

Candidati ora

Scopriamo insieme se i nostri corsi fanno per te. Compila il form e aspetta la chiamata di uno dei nostri consulenti.

Pagamento rateale

Valore della rata: A PARTIRE DA 112 €/mese.

Esempio di finanziamento  

Importo finanziato: € 2440 in 24 rate da € 112 – TAN fisso 9,37% TAEG 12,57% – importo totale del credito € 2788,68.

Il costo totale del credito comprende: interessi calcolati al TAN indicato, oneri fiscali (imposta di bollo sul contratto 16,00 euro*) addebitati sulla prima rata, costo mensile di gestione pratica € 3,90, spesa di istruttoria € 0,00, spesa per invio rendicontazione periodica cartacea € 0,98 (o spesa per invio rendicontazione periodica cartacea € 0,00), imposta di bollo su rendicontazione periodica € 0,00. Modalità di rimborso obbligatoria: addebito diretto su c/c. La scadenza delle rate è determinata dal giorno della liquidazione del contratto; la data di scadenza delle rate è prevista il giorno 15 del mese. L’importo di ciascuna rata comprende una quota di capitale crescente e interessi decrescente secondo un piano di ammortamento “alla francese”. Offerta valida dal 01/07/2023 al 31/12/2023.

Messaggio pubblicitario con finalità promozionale. Per le informazioni precontrattuali richiedere sul punto vendita il documento “Informazioni europee di base sul credito ai consumatori” (SECCI) e copia del testo contrattuale. Salvo approvazione di Sella Personal Credit S.p.A. Aulab S.r.l. opera quale intermediario del credito NON in esclusiva.

* In fase di richiesta del finanziamento verrà proposta la facoltà di selezionare, in alternativa all’imposta di bollo sul contratto di 16,00 euro, l’imposta sostitutiva, pari allo 0,25% dell’importo finanziato.

Pagamento rateale

Valore della rata: A PARTIRE DA 183 €/mese.

Esempio di finanziamento 

Importo finanziato: € 3990 in 24 rate da € 183 – TAN fisso 9,37% TAEG 12,57% – importo totale del credito € 4496,56.

Il costo totale del credito comprende: interessi calcolati al TAN indicato, oneri fiscali (imposta di bollo sul contratto 16,00 euro*) addebitati sulla prima rata, costo mensile di gestione pratica € 3,90, spesa di istruttoria € 0,00, spesa per invio rendicontazione periodica cartacea € 0,98 (o spesa per invio rendicontazione periodica cartacea € 0,00), imposta di bollo su rendicontazione periodica € 0,00. Modalità di rimborso obbligatoria: addebito diretto su c/c. La scadenza delle rate è determinata dal giorno della liquidazione del contratto; la data di scadenza delle rate è prevista il giorno 15 del mese. L’importo di ciascuna rata comprende una quota di capitale crescente e interessi decrescente secondo un piano di ammortamento “alla francese”. Offerta valida dal 01/07/2023 al 31/12/2023.

Messaggio pubblicitario con finalità promozionale. Per le informazioni precontrattuali richiedere sul punto vendita il documento “Informazioni europee di base sul credito ai consumatori” (SECCI) e copia del testo contrattuale. Salvo approvazione di Sella Personal Credit S.p.A. Aulab S.r.l. opera quale intermediario del credito NON in esclusiva.

* In fase di richiesta del finanziamento verrà proposta la facoltà di selezionare, in alternativa all’imposta di bollo sul contratto di 16,00 euro, l’imposta sostitutiva, pari allo 0,25% dell’importo finanziato.