Back

Guide rapide de la portée globale en JavaScript

Guide rapide de la portée globale en JavaScript

Lorsque vous déclarez une variable au niveau supérieur d’un fichier JavaScript, où réside-t-elle réellement ? La réponse dépend de si vous écrivez un script classique ou un module ES—et se tromper sur ce point conduit à des bugs subtils qui sont frustrants à déboguer.

Ce guide explique comment fonctionne la portée globale JavaScript dans le développement moderne, pourquoi globalThis est le moyen fiable de référencer l’objet global, et comment var, let et const se comportent différemment au niveau supérieur.

Points clés à retenir

  • Le comportement de la portée globale diffère entre les scripts classiques et les modules ES—seul var dans les scripts classiques crée des propriétés sur l’objet global.
  • let et const créent des liaisons globales mais ne s’attachent pas à l’objet global.
  • Utilisez globalThis pour la compatibilité multi-environnements lorsque vous devez accéder à l’objet global.
  • Privilégiez les modules ES pour l’isolation automatique de la portée et pour éviter la pollution involontaire de l’espace de noms.

Qu’est-ce que la portée globale en JavaScript ?

La portée globale fait référence à la portée la plus externe dans votre environnement JavaScript. Les variables en portée globale sont accessibles depuis n’importe où dans votre code—à l’intérieur de fonctions, de blocs ou de modules imbriqués.

Mais voici la distinction critique que la plupart des tutoriels omettent : la portée de niveau supérieur en JavaScript se comporte différemment selon la façon dont votre script se charge.

Scripts classiques vs modules ES

Dans un script classique (chargé sans type="module"), les variables de niveau supérieur déclarées avec var deviennent des propriétés de l’objet global :

// classic script
var config = { debug: true }
console.log(globalThis.config) // { debug: true }

Avec les modules ES, cela change complètement. Les modules et la portée globale fonctionnent différemment par conception. Les liaisons de niveau supérieur dans un module restent dans la portée de ce module—elles ne s’attachent pas à l’objet global :

// module script (type="module")
var config = { debug: true }
console.log(globalThis.config) // undefined

Cette isolation est intentionnelle. Les modules fournissent une encapsulation, empêchant la pollution accidentelle de l’espace de noms entre les fichiers. Consultez le guide MDN sur les modules JavaScript pour une référence plus approfondie.

Comment var, let et const diffèrent au niveau supérieur

Même dans les scripts classiques, let et const se comportent différemment de var :

// classic script
var a = 1
let b = 2
const c = 3

console.log(globalThis.a) // 1
console.log(globalThis.b) // undefined
console.log(globalThis.c) // undefined

Seul var crée une propriété sur l’objet global. let et const créent tous deux des liaisons dans la portée globale qui sont accessibles dans tout votre code, mais ils ne deviennent pas des propriétés de l’objet global.

Cette distinction est importante lorsque des scripts tiers s’attendent à trouver vos variables sur l’objet global, ou lorsque vous déboguez et le vérifiez directement.

Pourquoi globalThis est le standard moderne

Différents environnements JavaScript utilisaient historiquement des noms différents pour l’objet global :

  • Les navigateurs utilisent window
  • Node.js utilise global
  • Les Web Workers utilisent self

Écrire du code multi-environnements signifiait vérifier quel global existait. Le standard globalThis résout ce problème en fournissant une référence universelle :

// Works everywhere
globalThis.sharedValue = 'accessible across environments'

L’utilisation de globalThis garantit que votre code s’exécute correctement qu’il soit exécuté dans un navigateur, Node.js, Deno ou un Web Worker. C’est l’approche correcte et indépendante de la plateforme.

Masquage de variables dans la portée globale

Une idée fausse courante : vous ne pouvez pas redéclarer une variable let ou const qui existe déjà dans la portée globale. Cependant, vous pouvez masquer les liaisons var introduites globalement avec des déclarations lexicales—y compris les liaisons var introduites dynamiquement (par exemple, via eval) dans les moteurs modernes :

var x = 1
{
  let x = 2 // shadows the global var
  console.log(x) // 2
}
console.log(x) // 1

Le let x interne crée une variable distincte qui masque temporairement le var x externe dans ce bloc. Ce sont des liaisons distinctes—modifier l’une n’affecte pas l’autre.

Fonctionnalités réservées aux modules : await au niveau supérieur

Une différence pratique avec la portée de niveau supérieur que les développeurs JavaScript devraient connaître : await au niveau supérieur ne fonctionne que dans les modules :

// Only valid in modules
const data = await fetch('/api/config').then(r => r.json())

Les scripts classiques ne prennent pas en charge cette syntaxe. Si vous avez besoin de await au niveau supérieur, vous devez utiliser type="module" sur votre balise script.

Bonnes pratiques pour la portée globale

  1. Privilégiez les modules — Ils fournissent une isolation automatique de la portée et des imports/exports explicites
  2. Utilisez globalThis — Lorsque vous avez réellement besoin de l’objet global, cela fonctionne partout
  3. Évitez var au niveau supérieur — Utilisez let ou const pour éviter la pollution involontaire de l’objet global
  4. Soyez explicite sur les globales — Si quelque chose doit être global, attachez-le intentionnellement à globalThis plutôt que de vous fier à un comportement implicite

Conclusion

La portée globale en JavaScript n’est pas aussi simple que « des variables accessibles partout ». Les scripts classiques et les modules ES gèrent les liaisons de niveau supérieur différemment, et seul var dans les scripts classiques crée des propriétés d’objet global. Utilisez globalThis pour la compatibilité multi-environnements, et privilégiez les modules pour leur encapsulation intégrée. Comprendre ces distinctions vous aide à écrire du code prévisible qui fonctionne dans différents environnements JavaScript.

FAQ

Oui, mais seulement si les deux scripts sont des scripts classiques et partagent la même portée globale. Les variables sont accessibles par leur nom entre les scripts, mais elles ne sont pas des propriétés de l'objet global. Si l'un des scripts est un module ES, les variables restent privées à ce module sauf si elles sont explicitement exportées.

Utilisez l'objet global lorsque vous devez partager des données avec des scripts que vous ne contrôlez pas, comme des outils d'analyse tiers ou du code legacy qui s'attend à des globales. Utilisez-le également pour les polyfills qui doivent être universellement disponibles. Pour le code que vous contrôlez, privilégiez les exports de modules pour une meilleure encapsulation et un suivi explicite des dépendances.

globalThis est pris en charge dans tous les environnements JavaScript modernes. Si vous devez cibler des plateformes legacy comme Internet Explorer, utilisez un polyfill ou comptez sur votre bundler/transpileur pour en fournir un.

C'est une décision de conception historique. var faisait partie de JavaScript depuis le début et a été conçu pour créer des propriétés d'objet global pour l'interopérabilité. let et const ont été introduits dans ES6 avec des règles de portée plus strictes pour éviter les pièges de la pollution globale implicite tout en permettant l'accessibilité globale.