Le variabili in javascript: differenze tra var, let, e const
Immagino già sappiate che le variabili sono dei blocchi di codice utilizzati per immagazzinare dei dati.
Fino al 2015, per creare (dichiarare) una variabile, si utilizzava la sola parola chiave var seguita dal nome della variabile.
<script>
var x=0;
</script>
Con l'introduzione dell'ultima versione di Javascript (ES6), sono stati introdotte le parole chiave let e const, in aggiunta a var.
In questo articolo, vedremo la differenza tra queste tre tipologie di keyword, e parleremo di scope di una variabile, che in italiano traduciamo con ambito o contesto: cioè definiamo in quale porzione di codice una variabile può agire:
- con scope globale (global scope) si indica tutta l'area del nostro codice
- con scope locale (local scope) in indica una porzione di codice.
All'interno degli scope locali abbiamo questi due scope
- scope funzionale (functional scope): è la porzione di codice delimitata da una funzione
- scope di blocco (block scope): è la porzione di codice delimitata dalle parentesi graffe, quindi non solo quelle delle funzioni, ma ad esempio quelle presenti negli if, o nei cicli for. Questa tipologia di scope è stata introdotta con ES6.
Ho introdotto gli scope perchè sono uno dei principali aspetti che differenziano var, let e const.
Utilizzo di VAR
Come abbiamo già detto, prima dell'introduzione di ES6, l'unico modo per dichiarare una variabile era tramite l'utilizzo della parola chiave var.
Una variabile var, dichiarata all'interno di una funzione, ha un functional scope: non è accessibile dall’esterno, può essere usata solo localmente all'interno della funzione. Il functional scope è quindi anche un local scope.
Creata invece al di fuori di una funzione, questa variabile sarà accessibile globalmente e quindi anche all'interno di una funzione. In questo caso si dice che ha un ambito globale: global scope.
Come esempio creiamo una variabile con nome "saluto", seguita una funzione con dentro una variabile con nome "hello". Questa seconda variabile non sarà accessibile dall'esterno, e per verificarlo utilizziamo il classico console.log fuori dalla funzione e verifichiamo, utilizzando gli strumenti per sviluppatore del vostro browser, cosa succede.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>test</title>
</head>
<body>
<script>
var saluto="ciao giulio";
function mioesempio(){
var hello="ciao";
}
console.log(hello);
console.log(saluto);
</script>
</body>
</html>
Ecco cosa leggiamo da terminale
Per quanto riguarda la variabile "saluto" avremo la variabile correttamente stampata
ciao giulio
Mentre per la variabile "hello" avremo un avviso che la veriabile non è definita
hello is not defined
Nei prossimi esempi, per comodità, indicherò sollo il codice contenuto nel tag <script>
Una caratteristica delle var è che queste variabili possono essere ridichiarate ed aggiornate.
Ecco un esempio di variabile ridichiarata
<script>
var saluto = "ciao giulio";
var saluto = "ciao elisa";
console.log(saluto);
</script>
Ed ecco un esempio di variabile aggiornata
<script>
var saluto = "ciao giulio";
saluto = "ciao elisa";
console.log(saluto);
</script>
In emtrambi i casi, da terminale vedremo
ciao elisa
Ultima caratteristica di una variabile di tipo var, è che ha come valore di default sempre undefined.
Guardiamo questo esempio, che è del tutto legittimo, non è un errore:
<script>
console.log(saluto);
var saluto = "ciao giulio";
</script>
Da terminale vedremo un bel
undefined
Javascript è come se leggesse quel codice così
<script>
var saluto;
console.log(saluto);
var saluto = "ciao giulio";
</script>
Quindi è possibile utilizzare una variabile var prima della sua della dichiarazione. Questa possibilità si chiama hoisting delle variabili.
Con l'ultima versione di javascript ES6, sono aggiunte state le parole chiave let e const che hanno introdotto un nuovo tipo di scope: i block scope
I block scope sono blocchi di codice delimitati dalle parentesi graffe, e non solo quelle delle funzioni. Pensiamo ad esempio alle graffe presenti negli if o nei cicli for.
Ora che abbiamo introdotto i block scope, vediamo nel dettaglio di let e const, che hanno un block scope, cioè agiscono sono all'interno del blocco entro il quale compaiono, quindi hanno un ambito locale (local scope).
Utilizzo di LET
Una variabile dichiarata tramite la parola chiave let invece è legata al blocco dentro cui è dichiarata.
Quindi, se definita all'interno delle parentesi graffe, è accessibile solo all'interno di questa. E per parentesi graffe non intendiamo solo quelle delle funzioni, ma anche a quelle presenti ad esempio negli if o nei cicli for (ecco la differenza con le var).
In questo esempio, la variabile i, dichiarata con let, avrà sempre valore 1 al di fuori di if perchè non è accessibile dall'esterno.
<script>
var i = 1;
if (true) {
let i = 3;
}
console.log(i);
</script>
Questa possibilità non esisteva con l'utilizzo di var: la variabile i verrebbe infatti sovrascritta.
Vediamo un altro esempio, con un ciclo for.
Utilizzando var, la variabile i questa dopo il ciclo varrà 10: il loop altera infatti il valore della variabile.
<script>
var i = 5;
for (var i = 0; i < 10; i++) {
// qui eseguo delle operazioni
}
console.log(i);
</script>
Invece usando let, dopo il ciclo varrà ancora 5
<script>
let i = 5;
for (let i = 0; i < 10; i++) {
// qui eseguo delle operazioni
}
console.log(i);
</script>
Vediamo altre caratteristiche di let.
Una variabile dichiarata con let, non può essere ridichiarata all’interno dello stesso scope, ma solo in un altro scope (in un blocco differente).
Ecco un esempio di variabile i ridichiarata all'interno di if, quindi in uno scope differente
<script>
let i = 1;
if (true) {
let i = 3;
}
console.log(i);
</script>
Una variabile identifcata con let può essere aggiornata
<script>
let i = 1;
i = 3;
console.log(i);
</script>
Non è consentito ridichiarare una variabile var utilizzando l'identificatore let nello stesso scope, come in questo caso
<script>
var y = 4; // consentito
let y = 7; // non consentito
</script>
Otterremmo questo errore
Uncaught SyntaxError: redeclaration of var y
Non è consentito ridichiarare una variabile let nello stesso scope, come in questo caso
<script>
let y = 4; // consentito
let y = 7; // non consentito
</script>
Otterremmo l'errore
Uncaught SyntaxError: redeclaration of let y
Mentre le var, se non dichiarate prima del loro utilizzo, sono inizializzate con un undefined, per le let non avviene questo. Se quindi le utilizziamo senza inizializzarle otterremo un errore, come in questo esempio
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>test</title>
</head>
<body>
<script>
var x = document.getElementById('demo');
x.innerHTML = nome; // ReferenceError
let nome='pippo';
</script>
<div id='demo'></div>
</body>
</html>
Ecco l'errore ottenuto
Uncaught ReferenceError: can't access lexical declaration 'nome' before initialization
Utilizzo di CONST
Questa tipologia di variabili, come le variabili let, hanno un block scope, ma, a differenza di quanto accade per let, non possono essere aggiornate o ridichiarate.
Const infatti sta per costante, quindi il suo valore non può cambiare.
Vediamo cosa succederebbe se tentassimo di aggiornare la const
<script>
const nome = "Giulio";
nome = "Davide"; // errore: Assignment to constant variable.
</script>
Otterremo l'errore
Uncaught TypeError: invalid assignment to const 'nome'
Vediamo cosa succederebbe se tentassimo di ridichiarare la const
<script>
const nome = "Giulio";
const nome= "Elisa"; // errore: Identifier 'nome' has already been declared
</script>
Otterremo l'errore
Uncaught SyntaxError: redeclaration of const nome
Ogni dichiarazione di tipo const deve quindi essere inizializzata sempre, al momento della dichiarazione.
Le variabili const hanno una peculiarità: se è vero che una variabile dichiarata con const non può essere aggiornata, le sue proprietà possono essere cambiate.
Ad esempio, dichiariamo un oggetto come questo (gli oggetti sono variabili contenitori di proprietà, cioè di elementi caratterizzati da un nome ed un valore)
<script>
const saluti = {
message: "ciao Giulio",
times: 4
}
</script>
Non possiamo aggiornare la variabile "saluti":
<script>
const saluti = {
message: "ciao Giulio",
times: 4
}
saluti = {
message: "piacere",
number: "otto"
}
</script>
Otterremo infatti questo errore
Uncaught TypeError: invalid assignment to const 'saluti'
Ma possiamo cambiare una delle sue proprietà
<script>
const saluti = {
message: "ciao Giulio",
times: 4
}
saluti.message = "ciao Elisa";
</script>
Principali differenze tra var, let e const
Facciamo un breve ripasso di quanto appreso
- Le variabili di tipo var hanno uno scope globale, o di funzione (locale), mentre quelle dichiarate con let e const hanno scope di blocco (locale).
- Le variabili var possono essere aggiornate o ridichiarate dentro il loro scope
Le variabili let possono essere aggiornate ma non ridichiarate
Le variabili const non possono essere né aggiornate né ridichiarate. - Le varabili var sono inizializzate automaticamente con undefined, mentre le variabili let e const non sono inizializzate.
- Le varabili var e let possono essere dichiarate senza essere inizializzate, const deve essere inizializzato durante la sua dichiarazione.