Champ d'application des variables globales et locales

Dans cet article, vous découvrirez la portée et son fonctionnement en JavaScript.

La portée est un concept fondamental de JavaScript et 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 s'applique à votre code à mesure que vous vous familiarisez avec JavaScript et que vous travaillez davantage avec des variables.

La portée peut vous aider à:

  • Utilisez la mémoire plus efficacement:le champ d'application permet de charger des variables uniquement lorsque cela est nécessaire. 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.
  • Rechercher et corriger les bugs plus facilement:isoler les variables avec un champ d'application local facilite la résolution des bugs dans votre code. En effet, contrairement aux variables globales, vous pouvez être sûr que le code provenant d'un champ d'application extérieur ne peut pas manipuler les variables de portée locale.
  • Créer 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 des variables de portée globale ou locale:

  • Les variables ayant un champ d'application global sont disponibles à partir de tous les autres champs d'application dans le code JavaScript.
  • Les variables ayant une portée locale 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, cette variable a un champ d'application local.

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

  • Les variables de champ d'application du bloc sont disponibles localement pour un bloc, comme déterminé par l'emplacement des accolades dans lesquelles 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 blocage.
  • 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 permettre à une fonction incluse d'accéder aux variables référencées dans le champ d'application externe appelé "environnement lexical".

Lorsqu'un utilisateur accède à une variable dans son champ d'application, JavaScript renvoie la valeur qui lui a été 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 à portée locale ou globale.
  • Utilisez les mots clés const ou let pour déclarer des variables dont le champ d'application est défini sur un bloc.

Lorsque vous déclarez une variable var dans une fonction, la déclaration la met à 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 le champ d'application global, car la variable greeting est déclarée en dehors de toute fonction ou 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 portée globale, une valeur hello est attribuée à la variable greeting.

Cet exemple illustre le champ d'application local, car il déclare la variable greeting avec le mot clé let dans une fonction. La variable greeting a une portée locale 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 que la variable ne soit accessible qu'entre les 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 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 du bloc. Ainsi, vous ne pouvez accéder à la variable greeting qu'entre accolades, ce qui spécifie le champ d'application du bloc.

Cet exemple corrige l'erreur, car il déplace la méthode console.log(message) 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 champ d'application

Champ d'application global

Vous pouvez accéder aux variables de portée globale depuis n'importe quel point du 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 n'importe où dans le 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 portée qui n’est pas beaucoup abordé dans cet article. Si vous créez une variable dans un module JavaScript, mais en dehors d'une fonction ou d'un bloc, elle n'a pas de champ d'application global, mais plutôt de champ d'application de module. Les variables ayant une portée module sont disponibles n'importe où dans le module actuel, mais pas à partir d'autres fichiers ou modules. Pour qu'une variable à l'échelle d'un module soit disponible pour d'autres fichiers, vous devez l'exporter depuis le module où elle est créée, puis l'import depuis le module qui doit accéder à la variable.

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, les variables sont locales pour la fonction. Vous ne pouvez donc y accéder qu'à partir de la fonction. Les variables locales sont créées au démarrage d'une fonction et sont effectivement supprimées lorsque l'exécution de la fonction se termine.

Cet exemple déclare la variable total dans la fonction addNumbers(). Vous ne pouvez accéder qu'aux variables a, b, et total 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. Cependant, 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

Bloquer le champ d'application

Les blocs sont utilisés pour regrouper une ou plusieurs instructions. Vous pouvez utiliser les mots clés const ou let pour déclarer une variable locale dont le champ d'application est défini sur "block". Notez que vous ne pouvez pas utiliser le mot clé var pour déclarer des variables ayant un champ d'application de bloc.

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

{
    const name = "Elizabeth";
}

Vous pouvez utiliser des variables à l'échelle du 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 "Bloquer". Le 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éutilisation d'un nom de variable dans un champ d'application différent

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

Cet exemple montre comment utiliser 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 n'entrent donc pas en conflit.

Fermetures et portée lexicale

Les closures désignent une fonction englobée dans laquelle une fonction interne peut accéder au champ d'application de la fonction externe, également appelée "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 la fonction. En fait, vous pouvez coder une chaîne de références à des environnements lexiques externes afin qu'une fonction soit appelée par une fonction, qui elle-même est 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, qui se ferme sur 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 le champ d'application lexical, le champ d'application est déterminé lors de la compilation du code source, et non lors de l'exécution. Pour en savoir plus sur l'environnement lexical, consultez la page Champ d'application lexical et clôture lexical.

Modules

Les modules JavaScript permettent d'organiser le code JavaScript. Utilisés correctement, ils fournissent 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 fournissent 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 de champ d'application

La portée est un concept fondamental que tout développeur JavaScript doit comprendre. Pour mieux comprendre le système de champ d'application, vous pouvez essayer d'écrire votre propre code avec 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 JavaScript est l'un des concepts les plus avancés du développement Web. Nous vous remercions donc d'avoir lu ce contenu et d'avoir pris le temps de le comprendre.

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