I. ES6 : les variables▲
La portée des variables en JavaScript peut surprendre lorsqu'on est habitué à d'autres langages. Dans ce chapitre on va faire un peu le point en montrant ce qu'apporte ES6 à ce niveau avec l'introduction des mots-clés let et const.
I-A. Déclaration avec « var »▲
I-A-1. Portée des variables▲
Avec ES5 on dispose du mot-clé var pour déclarer les variables. Selon où on fait la déclaration la variable n'a pas la même portée :
- déclaration en dehors d'une fonction : portée globale, donc disponible partout ;
- déclaration dans une fonction : portée locale donc disponible uniquement dans la fonction.
Jusque-là tout semble pour le mieux dans le meilleur des mondes informatiques, mais…
Si on déclare une variable dans une instruction de bloc elle reste disponible en dehors de ce bloc :
Si vous exécutez le code ci-dessus vous allez obtenir ce résultat :
true
Autrement dit la variable adult définie dans le bloc reste disponible en dehors de ce bloc.
La portée va même sans doute plus loin que vous ne le pensez, pour une portée globale, parce que la variable est accessible dans l'objet global qui est window pour une page web :
var age =
20
;
console.log
(
age);
// 20
console.log
(
window
.
age);
// 20
Quand on utilise var on peut donc écraser une variable de l'objet global !
I-A-2. Remontée des variables▲
Pour comprendre le fonctionnement du code qu'on a vu ci-dessus il faut savoir comment procède JavaScript avec le mot-clé var. En gros il va traduire le code ainsi :
Il va remonter la déclaration de la variable au début de la fonction et donc cette variable est disponible dans toute la fonction !
Un effet détourné de cette remontée est qu'on peut utiliser une variable qui est déclarée plus tard.
I-A-3. Déclarations multiples▲
I-B. Déclaration avec « let »▲
I-B-1. Portée des variables▲
ES6 introduit le nouveau mot-clé let.
Avec le mot-clé let une variable a comme portée le bloc où elle est déclarée. |
Si on reprend le code vu ci-dessus avec let :
Cette fois on ne va rien obtenir parce qu'en dehors du bloc la variable adult n'existe pas.
D'autre part, contrairement à var, la portée ne concerne plus l'objet global :
2.
3.
4.
window
.
age =
10
;
let age =
20
;
console.log
(
age);
//20
console.log
(
window
.
age);
// 10
Ainsi on ne crée pas une propriété dans l'objet global, ce qui est plus sûr ! |
I-B-2. Pas de déclarations multiples▲
Contrairement au mot-clé var, avec let on n'a pas le droit de faire une nouvelle déclaration avec le même identifiant dans le même bloc :
Par contre, dans des blocs différents rien n'empêche d'utiliser un même identifiant même s'il vaut mieux l'éviter pour des raisons de clarté de code. |
I-C. Déclaration avec « const »▲
Avec ES6 il est maintenant possible de déclarer une constante, donc une variable dont on ne peut pas changer la valeur, avec le mot-clé const :
const maConstante =
20
;
Il faut obligatoirement donner une valeur à l'initialisation d'une constante ! |
La règle de portée est la même que pour let : le bloc de déclaration.
On ne peut pas non plus faire de nouvelle déclaration avec la même portée.
Lorsqu'on dit qu'on ne peut pas changer la valeur d'une constante il faut apporter une petite précision : c'est vrai si on a une valeur, ça ne l'est plus si on a un objet. Dans ce cas c'est la référence qu'on ne peut pas changer.
Vous avez donc le droit d'écrire ce genre de code :
2.
3.
4.
5.
const voiture =
{
marque
:
"Renault"
};
voiture.
marque =
"BMW"
;
console.log
(
voiture);
// {"marque":"BMW"}
Vous changez la valeur d'une propriété, pas la référence de l'objet.
Par contre vous n'avez pas le droit d'écrire ceci :
2.
3.
4.
5.
6.
const voiture =
{
marque
:
"Renault"
};
voiture =
{
marque
:
"Fiat"
};
Parce que là vous changez la référence.
Pour geler un objet, donc le rendre non modifiable, il faut utiliser la méthode freeze :
Object.freeze
(
voiture);
Une bonne pratique consiste à utiliser const par défaut et uniquement let quand on est sûr que la valeur de la variable doit changer (ou la référence si on a un objet).
I-D. La zone morte temporelle▲
On a vu ci-dessus que lorsqu'on utilise le mot-clé var la déclaration de la variable est « remontée » par JavaScript quel que soit l'emplacement effectif de la déclaration.
Lorsqu'on utilise let ou const ce n'est plus vrai ! |
Autrement dit, on ne peut pas utiliser une variable avant qu'elle soit déclarée avec let ou const. |
console.log
(
age);
// undefined
let age =
10
;
// idem avec const
Lorsque JavaScript analyse le code et trouve un bloc, s'il rencontre une déclaration avec let ou const, il la place dans la zone morte temporelle (temporal dead zone) où elle est inaccessible jusqu'à ce que le flot d'exécution arrive effectivement sur la déclaration.
I-E. En résumé▲
- Lorsqu'on utilise le mot-clé var la variable n'est pas limitée à son bloc de déclaration, elle est « remontée » au début du code et sa portée peut concerner l'objet global.
- L'utilisation du mot-clé let limite la portée d'une variable à son bloc de déclaration, d'autre part, elle n'atteint jamais l'objet global.
- Le mot-clé const permet de déclarer une constante avec les mêmes règles de portée que le mot-clé let.
- La zone morte temporelle stocke les déclarations effectuées avec let et const jusqu'à l'exécution du code de la déclaration.