Champ d'application des variables globales et locales

Dans cet article, vous découvrirez le champ d'application et son fonctionnement en JavaScript.

La portée est un concept fondamental en JavaScript et dans d'autres langages de programmation, qui définit le contexte dans lequel les variables sont consultées et utilisées. Il devient plus utile et applicable à votre code à mesure que vous apprenez à utiliser JavaScript et à travailler davantage avec des variables.

La portée peut vous aider à:

  • Utiliser la mémoire plus efficacement:le champ d'application ne permet de charger des variables qu'en cas de besoin. Si une variable est hors du champ d'application, vous n'avez pas besoin de la rendre disponible pour le code en cours d'exécution.
  • Trouver et corriger les bugs plus facilement:l'isolation de variables avec un champ d'application local facilite la résolution des bugs dans votre code. En effet, contrairement aux variables globales, vous pouvez vous assurer que le code provenant d'un champ d'application extérieur ne peut pas manipuler de variables à champ d'application local.
  • Créez de petits blocs de code réutilisables:par exemple, vous pouvez écrire une fonction pure qui ne dépend pas d'un champ d'application extérieur. Vous pouvez facilement déplacer une telle fonction ailleurs avec un minimum de modifications.

Qu'est-ce que le champ d'application ?

Le champ d'application d'une variable détermine l'endroit où vous pouvez l'utiliser dans le code.

JavaScript définit les variables de champ d'application global ou local:

  • Les variables ayant un champ d'application global sont disponibles à partir de tous les autres champs d'application dans le code JavaScript.
  • Les variables dont le champ d'application est local ne sont disponibles que dans un contexte local spécifique et sont créées par des mots clés, tels que var, let et const. Si vous utilisez les mots clés var, let ou const pour créer une variable dans une fonction, celle-ci a une portée locale.

Les sections suivantes de cet article traitent du bloc et de la portée lexicale:

  • Les variables de champ d'application du bloc sont disponibles localement dans un bloc, comme déterminé par l'emplacement des accolades où l'instruction de bloc est définie. Seules les variables déclarées avec les mots clés let ou const ont une portée de bloc.
  • Le champ d'application lexical utilise l'emplacement où une variable est déclarée dans le code source pour déterminer où elle est disponible. Vous utilisez des fermetures pour autoriser une fonction incluse à accéder aux variables référencées dans le champ d'application externe appelé environnement lexical.

Lorsque vous accédez à une variable dans son champ d'application, JavaScript renvoie la valeur attribuée ou génère une erreur.

Pour déclarer une variable:

  • Utilisez les mots clés var, const ou let pour déclarer des variables de portée locale ou globale.
  • Utilisez les mots clés const ou let pour déclarer des variables de portée bloc.

Lorsque vous déclarez une variable var dans une fonction, cette déclaration la met à la disposition de la fonction englobante la plus proche. Vous ne pouvez pas utiliser le mot clé var pour déclarer des variables dont le champ d'application est "bloc".

Exemples de champs d'application

Cet exemple illustre un champ d'application global, car la variable greeting est déclarée en dehors de toute fonction ou de tout bloc, ce qui rend sa valeur disponible pour tout le code du document actuel:

const greeting = 'hello';
console.log(greeting); // 'hello'

Dans l'exemple de champ d'application global, une valeur hello est attribuée à la variable greeting.

Cet exemple illustre un champ d'application local, car il déclare la variable greeting avec le mot clé let dans une fonction. La variable greeting est une variable à champ d'application local et n'est pas disponible en dehors de la fonction.

function greet() {
  let greeting = 'Hello World!';
  console.log(greeting);
}

Cet exemple illustre le champ d'application d'un bloc, car il déclare la variable greeting dans un bloc afin qu'elle ne soit accessible qu'à l'intérieur des accolades:

if (true) {
   const greeting = 'hello';
}

console.log(greeting); // ReferenceError: greeting is not defined

Notez que lorsque la fonction console.log tente de générer la valeur de la variable greeting, JavaScript renvoie un message d'erreur ReferenceError au lieu du message hello attendu. Pourquoi ?

Une erreur est renvoyée, car la variable greeting a un champ d'application de bloc et que le bloc le plus proche fait partie de l'instruction conditionnelle if. Vous ne pouvez pas accéder aux variables let et const que vous déclarez dans un bloc depuis l'extérieur de celui-ci. Ainsi, vous ne pouvez accéder à la variable greeting qu'entre accolades, qui spécifient le champ d'application du bloc.

Cet exemple corrige l'erreur, car la méthode console.log(message) est déplacée entre les accolades. Le code mis à jour déplace la méthode console.log(message) dans le bloc.

if (true) {
   const greeting = 'hello';
   console.log(greeting);
}

Types de champs d'application

Champ d'application global

Vous pouvez accéder aux variables avec une portée globale depuis n'importe où dans le programme.

Prenons l'exemple d'un fichier HTML qui importe deux fichiers JavaScript, file-1.js et file-2.js :

<script src="file-1.js"></script>
<script src="file-2.js"></script>

Dans cet exemple, la variable globalMessage a un champ d'application global et est écrite en dehors d'une fonction. Lors de l'exécution et de l'exécution, vous pouvez accéder à la valeur de la variable globalMessage depuis n'importe quel emplacement du programme JavaScript.

Vous pouvez voir le contenu des fichiers file-1.js et file-2.js dans cet extrait de code. Notez la disponibilité de la variable globalMessage dans les deux fichiers.

// file-1.js
function hello() {
    var localMessage = 'Hello!';
}

var globalMessage = 'Hey there!';

// file-2.js
console.log(localMessage); // localMessage is not defined
console.log(globalMessage); // Hey there!

Il existe un autre type de champ d'application qui n'est pas très abordé dans cet article. Si vous créez une variable dans un module JavaScript, mais en dehors d'une fonction ou d'un bloc, son champ d'application n'est pas global, mais de module. Les variables dont le champ d'application est défini sur le module sont disponibles n'importe où dans le module actuel, mais pas depuis d'autres fichiers ou modules. Pour rendre une variable à l'échelle du module disponible pour d'autres fichiers, vous devez l'exporter depuis le module où elle a été créée, puis l'import à partir du module qui doit y accéder.

Champ d'application local et champ d'application de la fonction

Lorsque vous créez des variables dans une fonction JavaScript avec les mots clés var, let ou const, elles sont locales dans la fonction. Vous ne pouvez donc y accéder que depuis cette fonction. Les variables locales sont créées au démarrage d'une fonction et sont réellement supprimées à la fin de l'exécution de la fonction.

Cet exemple déclare la variable total dans la fonction addNumbers(). Vous ne pouvez accéder aux variables a, b, et total que dans la fonction addNumbers().

function addNumbers(a, b) {
    const total = a + b;
}

addNumbers(3, 4);

Vous pouvez utiliser les mots clés let et const pour nommer les variables. Lorsque vous utilisez le mot clé let, JavaScript peut mettre à jour la variable. Toutefois, avec le mot clé const, la variable reste constante.

var variable1 = 'Declared with var';
var variable1 = 'Redeclared with var';
variable1; // Redeclared with var

let variable2 = 'Declared with let. Cannot be redeclared.';
variable2 = 'let cannot be redeclared, but can be updated';
variable2; // let cannot be redeclared, but can be updated

const variable3 = 'Declared with const. Cannot be redeclared or updated';
variable3; // Declared with const. Cannot be redeclared or updated

Champ d'application du bloc

Les blocs sont utilisés pour regrouper une seule instruction ou un ensemble d'instructions. Vous pouvez utiliser les mots clés const ou let pour déclarer une variable locale dont la portée est définie au niveau du bloc. Notez que vous ne pouvez pas utiliser le mot clé var pour déclarer des variables dont le champ d'application est "bloc".

Par exemple, dans ce bloc, le champ d'application de la variable name et de sa valeur "Elizabeth" sont contenus entre accolades. Les variables incluses dans le champ d'application d'un bloc ne sont pas disponibles en dehors du bloc.

{
    const name = "Elizabeth";
}

Vous pouvez utiliser des variables de portée bloc dans les instructions if, for ou while.

Notez les deux boucles for dans cet extrait de code. Une boucle for utilise le mot clé var pour déclarer la variable d'initialisation, qui incrémente les nombres 0, 1 et 2. L'autre boucle for utilise le mot clé let pour déclarer la variable d'initialisation.

for (var i = 0; i < 2; i++) {
    // ...
}

console.log(i); // 2

for (let j = 0; j < 2; j++) {
    // ...
}

console.log(j); // The j variable isn't defined.

Dans l'exemple de code précédent, vous remarquerez peut-être que la variable i de la première boucle for a fuité en dehors de la boucle for et conserve toujours une valeur 2, car le mot clé var n'utilise pas le champ d'application du bloc. Ce problème est résolu dans la deuxième boucle for, dans laquelle la variable j déclarée avec le mot clé let est limitée au bloc de la boucle for et n'existe pas une fois la boucle for terminée.

Réutiliser un nom de variable dans un champ d'application différent

Le champ d'application peut isoler une variable dans une fonction, même lorsque vous réutilisez le même nom de variable ailleurs dans un champ d'application différent.

Cet exemple vous montre comment le champ d'application vous permet de réutiliser le même nom de variable dans différentes fonctions:

function listOne() {
    let listItems = 10;
    console.log(listItems); // 10
}

function listTwo() {
   let listItems = 20;
   console.log(listItems); // 20
}

listOne();
listTwo();

Les valeurs attendues sont attribuées aux variables listItems des fonctions listOne() et listTwo(). Elles ne sont donc pas en conflit.

Fermetures et portée lexicale

Les fermetures font référence à une fonction fermée dans laquelle une fonction interne peut accéder au champ d'application de la fonction externe, également appelé environnement lexical. Ainsi, en JavaScript, vous utilisez des fermetures pour permettre aux fonctions de référencer l'environnement lexical externe, ce qui permet au code d'une fonction de référencer des variables déclarées en dehors de celle-ci. En fait, vous pouvez coder une chaîne de références à des environnements lexicals externes de sorte qu'une fonction soit appelée par une fonction, elle-même appelée par une autre fonction.

Dans cet exemple, le code forme une fermeture avec l'environnement lexical créé lorsque la fonction outer() est appelée, ce qui se ferme au-dessus de la variable hello. Ainsi, la variable hello est utilisée dans la fonction de rappel setTimeout.

function outer() {
    const hello = 'world';

    setTimeout(function () {
        console.log('Within the closure!', hello)
    }, 100);
}

outer();

Avec la portée lexicale, la portée est déterminée lors de la compilation du code source, et non lors de l'exécution. Pour en savoir plus sur l'environnement lexical, consultez Portée lexicale et fermeture.

Modules

Les modules JavaScript aident à organiser le code JavaScript. Utilisés correctement, ils offrent une structure efficace à votre codebase et facilitent la réutilisation du code. Plutôt que d'utiliser des variables globales pour partager des variables entre différents fichiers, les modules JavaScript offrent une technique pour exporter et import des variables.

// hello.js file
function hello() {
  return 'Hello world!';
}

export { hello };

// app.js file
import { hello } from './hello.js';

console.log(hello()); // Hello world!

Démonstration du visualiseur des champs d'application

Le champ d'application est un concept fondamental que tout développeur JavaScript doit comprendre. Pour mieux comprendre le système de champs d'application, vous pouvez essayer d'écrire votre propre code à l'aide de JS Scope Visualizer. La démonstration utilise des couleurs dans le code pour vous aider à visualiser les champs d'application JavaScript.

Conclusion

Cet article présente différents types de portée. Le champ d'application de JavaScript est l'un des concepts les plus avancés du développement Web. Nous sommes donc ravis que vous ayez pris le temps de comprendre ce sujet.

Le champ d'application n'est pas une fonctionnalité visible par l'utilisateur. Seul le développeur Web qui écrit le code est concerné, mais la connaissance du fonctionnement de la portée peut vous aider à corriger les bugs lorsqu'ils surviennent.