Le Scope ou la portée des variables
Définition d’un scope
Le scope est un des concepts clés de Javascript.
La portée ou scope, désigne l’accessibilité des variables, autrement dit : Où et quand une variable peut être utilisée par votre programme.
Nous désignons 3 types de scope
:
Le
Global Scope
1// GLOBAL SCOPE
2var animal = "Elephant";
3var population = 10;
Les variables sont déclarées dans le script en dehors d’un bloc d’instruction ou d’une fonction.
Le
Local Scope
1// FUNCTION SCOPE
2function zoo() {
3 var animal = "Tigre";
4 var population = 5;
5 console.log(animal, population);
6}
Les variables sont déclarées dans le corps de la fonction zoo
.
Le
Block Scope
, dans un bloc d’instruction(if
,else
,while
,for
.. ).
1// BLOCK SCOPE
2for(var population = 0; population <10 ; population++) {
3 console.log(animal, population);
4}
La variable population
est déclarée dans le block déclaratif de la boucle for
.
Etude de la portée des variables
Lisez le code suivant :
1var var1 = 10;
2console.log(var1);
var1
est déclaré dans le global scope. Nous pouvons afficher sa valeur sans problème avec un console.log
.
Ajoutons maintenant un block conditionnel et tentons d’accèder depuis ce block à notre variable var1
.
1var var1 = 10;
2console.log(`Global Scope 1 : ${var1}`);
3if(true) {
4 console.log(`Block Scope 1 : ${var1}`);
5 var1++;
6 console.log(`Block Scope 2 : ${var1}`);
7}
8console.log(`Global Scope 2 : ${var1}`);
La console retourne :
"Global Scope 1 : 10"
"Block Scope 1 : 10"
"Block Scope 2 : 11"
"Global Scope 2 : 11"
Observation 1
Une variable déclarée dans le Global Scope peut être lue et modifiée dans le Block Scope.
Déclarons maintenant une variable var2
dans le Block et tentons d’y accèder depuis l’extérieur.
1if(true) {
2 var var1 = 10;
3}
4console.log(`Global Scope 1 : ${var1}`);
La console retourne :
"Global Scope 1 : 10"
Observation 2
Une variable déclarée dans le Block Scope peut être lue et modifiée dans le Global Scope.
Maintenant déclarons une fonction increment
:
1var var1 = 10;
2function increment() {
3 var1++;
4}
5increment();
6console.log(`Global Scope 1 : ${var1}`);
La console retourne :
"Global Scope 1 : 11"
Observation 3
Une variable déclarée dans le Global Scope peut être lue et modifiée dans le Function Scope. C’est ce que l’on appelle un effet de bord ou side effect.
Avertissement
Attention aux effets de bord des fonctions que vous écrivez dans vos scripts. Ils peuvent complexifier leur lecture et leur débogage. Car une variable déclarée dans le Global Scope pourrait être modifiée par de nombreuses fonctions à effets de bord rendant difficile la prévision des valeurs durant le cycle de vie de votre script.
Déclarons une nouvelle variable dans le corps de la fonction.
1var var1 = 10;
2function increment() {
3 var var2 = 20;
4 var1++;
5}
6increment();
7console.log(`Global Scope 1 : ${var2}`);
La console retourne :
"Uncaught ReferenceError: var2 is not defined"
Observation 4
Une variable déclarée dans le Function Scope ne peut être lue et modifiée dans le Global Scope.
Prenons un nouveau cas de figure :
Nous déclarons var1
dans le Global Scope puis nous déclarons une nouvelle variable avec le même nom var1
dans un Block Scope.
1var var1 = 10;
2console.log(`Global Scope 1 : ${var1}`);
3if(true) {
4 var var1 = 100;
5 console.log(`Function Scope 1 : ${var1}`);
6}
7console.log(`Global Scope 2 : ${var1}`);
La console retourne :
"Global Scope 1 : 10"
"Function Scope 1 : 100"
"Global Scope 2 : 100"
Observation 5
Il n’existe pas de portée de Block pour les variables var
.
La version ECMAScript2015 a introduit dans Javascript deux nouveaux mots clés : let
et const
.
let
permet de pallier au problème soulevé dans l”Observation 5. Reprenons le code précédent et remplaçons maintenant var
par let
.
1let var1 = 10;
2console.log(`Global Scope 1 : ${var1}`);
3if(true) {
4 let var1 = 100;
5 console.log(`Function Scope 1 : ${var1}`);
6}
7console.log(`Global Scope 2 : ${var1}`);
La console retourne :
"Global Scope 1 : 10"
"Function Scope 1 : 100"
"Global Scope 2 : 10"
Observation 6
Les variables créées avec le mot clé let
appartiennent au scope dans lequel elles ont été définies. Toutefois, elles restent accessible et modifiable dans les blocks enfants.
let var1 = 10; console.log(`Global Scope 1 : ${var1}`); if(true) { var1 = 100; console.log(`Function Scope 1 : ${var1}`); } console.log(`Global Scope 2 : ${var1}`);
Note
Il faut donc privilégier l’utilisation du mot clé let
au lieu de var
afin d’éviter des désagréments.
Le mot clé const
sert à déclarer une référence constante.
Attention, une référence constante ne veut pas dire que la valeur derrière la référence est « immutable », mais que la référence elle-même est immutable.
1const a = 10;
2a++;
Nous essayons de modifier la valeur de a
déclaré pourtant comme étant une constante const
. Cela est interdit.
Toutefois :
1const a = {txt: "hello"}; //Référence r0 vers l'objet
2const b = a; //Référence r0 vers le même objet
3a.txt += " world" //Adresse 0x0002
4console.log(a); //"hello world";
5console.log(b); //"hello world";
Ici, a
est de type complexe, c’est un objet. Ce n’est pas sa valeur qui est stockée dans la variable mais une référence de l’objet, l’adresse mémoire qu’il occupe.
Ainsi, un objet peut être déclaré avec le mot clé const
et se voir ajouter, modifier, supprimer des éléments.
Nous n’allons pas tester toutes les scopes avec const
.
Voici un tableau comparatif :
Exercice
1var i = 10;
2for(var i =0;i<=5;i++) {
3 // Do Stuff
4}
5console.log(i)