La portée des variables
Où une variable existe : blocs, fonctions et le piège des globales.
Objectifs
À la fin de cette leçon, vous saurez :
- expliquer ce qu'est la portée (scope) d'une variable ;
- prédire où une variable déclarée avec
letouconstest visible ; - reconnaître la portée de fonction et le comportement historique de
var; - éviter les variables globales inutiles et le piège du shadowing.
🔗 Pour vous rafraîchir la mémoire : conditions et boucles · découper avec des fonctions
Une variable naît, vit et meurt
Créer une variable, c'est demander à l'interpréteur : « réserve-moi un nom ». Cette réservation a une durée et un périmètre : c'est sa portée. Hors de cette zone, le nom n'existe pas — y accéder provoque une erreur.
{
const prix = 10;
}
console.log(prix); // ReferenceError : prix n'existe pas ici
Les accolades { } délimitent un bloc, et let / const rendent la variable visible uniquement dans ce bloc.
La portée de bloc
Chaque bloc crée une frontière : if, for, fonction, ou simples accolades.
if (true) {
const message = "visible ici";
console.log(message); // ok
}
// console.log(message); // ReferenceError
for (let i = 0; i < 3; i++) {
// i existe à chaque tour
}
// console.log(i); // ReferenceError
C'est une protection, pas une contrainte agaçante : chaque tour de boucle peut avoir « son » i, et rien ne fuit à l'extérieur.
La portée de fonction
Une variable déclarée dans une fonction est visible partout dans cette fonction, y compris dans les blocs internes.
function total(quantite) {
const tarif = 5;
if (quantite > 0) {
return quantite * tarif; // tarif visible : même fonction
}
return 0;
}
// console.log(tarif); // ReferenceError : dehors, rien
Historiquement, var ignorait les blocs et ne connaissait que la portée de fonction — source de bugs célèbres. Le cours utilise exclusivement let et const, qui respectent les blocs ; retenez simplement que var existe dans du code ancien.
Variables globales : puissantes et dangereuses
Une variable déclarée au sommet du fichier est visible partout : c'est une globale. Pratique pour une constante partagée, redoutable dès que le programme grandit :
- n'importe quelle ligne peut la modifier, sans prévenir les autres ;
- deux morceaux de code peuvent se marcher dessus par accident ;
- relire le code devient un jeu de piste : qui change cette valeur ?
const TAUX_TVA = 0.2; // globale assumée : constante de référence
function prixTTC(ht) {
return ht * (1 + TAUX_TVA);
}
La règle : déclarer chaque variable à la portée la plus petite possible. Locale si possible, globale seulement si vraiment partagée.
Le shadowing : deux noms, deux vies
Un bloc interne peut redéclarer un nom déjà utilisé dehors : il le masque localement.
const nom = "extérieur";
function saluer() {
const nom = "intérieur"; // masque la globale DANS la fonction
console.log(nom);
}
saluer(); // "intérieur"
console.log(nom); // "extérieur" : intacte
Le code s'exécute sans erreur, mais la lecture devient piégeuse : le même mot désigne deux choses. On évite donc volontairement le shadowing.
Exercice
- Prédisez puis vérifiez : que produit ce code ?
function test() {
if (true) {
const x = 1;
}
return x;
}
console.log(test());
- Prédisez puis vérifiez la sortie :
let compteur = 0;
function incrementer() {
let compteur = 100;
compteur = compteur + 1;
}
incrementer();
console.log(compteur);
-
Réécrivez l'exercice 2 pour que l'affichage soit
1, en déplaçant une seule ligne. -
Expliquez pourquoi
for (let i...)permet trois boucles imbriquées utilisant toutes une variablei, alors qu'une seule globale provoquerait un conflit.
Résumé
- La portée est la zone du code où un nom existe.
letetconstont une portée de bloc ;var(ancien) une portée de fonction.- Une globale est visible partout : à réserver aux constantes réellement partagées.
- Le shadowing masque un nom extérieur : légal, mais à éviter pour la lisibilité.
- Règle d'or : la plus petite portée possible.
Correction disponibleCherchez d’abord par vous-même.Voir la correction
Correction
Réponses détaillées
Question 1. ReferenceError: x is not defined. x naît dans le bloc if et meurt à son accolade fermante ; le return x est dehors. La fonction plante à l'exécution — erreur dite « à l'exécution » (voir chapitre 6).
Question 2. Affichage : 0. Le compteur de la fonction est une autre variable (shadowing) : elle passe bien à 101 puis disparaît en fin de fonction. La globale n'a jamais été touchée.
Question 3. Supprimer la ligne let compteur = 100;. Alors la fonction utilise la globale visible par portée emboîtée, et compteur = compteur + 1 la fait passer à 1.
Question 4. Chaque boucle possède son propre bloc : chaque let i crée une variable distincte, vivante uniquement dans sa boucle. Aucune collision car aucune n'existe simultanément au même endroit — c'est exactement ce qu'une globale interdirait.