Menu
Français

let, const ou var en JavaScript : quel choix faire ?

Les trois façons de déclarer une variable en JavaScript — et pourquoi le code moderne privilégie const par défaut, let quand c'est nécessaire, et var quasiment jamais.

Trois mots-clés, un seul rôle

En JavaScript, il existe trois façons de déclarer une variable : var, let et const. Toutes associent un nom à une valeur, mais elles diffèrent par leur portée, leurs règles de réaffectation et leur comportement avant même que la déclaration ne soit exécutée. Dans le code moderne, on utilise const la plupart du temps, let quand la valeur doit changer, et var quasiment jamais.

En résumé :

index.js
Output
Click Run to see the output here.

Le reste de cette page explique pourquoi ces trois lignes se comportent ainsi.

const : le choix par défaut

const crée une liaison qu'on ne peut pas réassigner. Dès que tu écris const x = 5, impossible de faire x = 6 plus loin — le moteur te balance une TypeError.

index.js
Output
Click Run to see the output here.

Et c'est tout. Dans un programme bien conçu, la plupart des variables n'ont pas besoin d'être réaffectées, donc const couvre l'écrasante majorité des cas. En dégainant const par défaut, les endroits où une valeur change vraiment ressortent tout de suite.

Attention à un piège classique : const verrouille la liaison, pas la valeur. Si la valeur est un objet ou un tableau, son contenu reste modifiable :

index.js
Output
Click Run to see the output here.

const veut dire « ce nom pointe toujours vers cet objet ». Ça ne veut pas dire « cet objet ne change jamais ». Si tu as vraiment besoin de figer l'objet lui-même, l'outil qu'il te faut c'est Object.freeze(user). Mais dans la pratique, la plupart du code s'appuie simplement sur la convention qui veut qu'on ne mute pas un objet déclaré en const.

let : quand la réaffectation est vraiment nécessaire

let fonctionne exactement comme const, à une différence près : tu peux réaffecter la variable. Sers-t'en pour les compteurs, les accumulateurs, les variables de boucle, et partout où la valeur évolue réellement au fil du temps.

index.js
Output
Click Run to see the output here.

Si tu te retrouves à écrire let sans jamais réassigner la variable, passe-la en const. Sur la plupart des projets, le linter te le rappellera de toute façon.

La portée de bloc en JavaScript

let et const ont tous les deux une portée de bloc. Un bloc, c'est tout ce qui se trouve entre { et } : le corps d'un if, d'une boucle for, d'une fonction, ou même un simple bloc { ... } isolé. Une variable déclarée à l'intérieur d'un bloc n'existe tout simplement pas en dehors.

index.js
Output
Click Run to see the output here.

C'est exactement ce qu'on veut. Chaque variable reste cantonnée à la portion de code qui la concerne, et les collisions de noms accidentelles deviennent impossibles.

var, lui, ne fait pas ça — et c'est la principale raison pour laquelle on l'évite.

var : portée de fonction et mauvaises surprises

var est attaché à la fonction la plus proche, pas au bloc le plus proche. Autrement dit, un var déclaré à l'intérieur d'un if ou d'un for fuit dans la fonction qui l'englobe :

index.js
Output
Click Run to see the output here.

Cette portée permissive est à l'origine de toute une série de bugs classiques en JavaScript — le plus célèbre étant celui des boucles où chaque itération partage le même var i, si bien que tous les callbacks finissent par voir la dernière valeur.

var autorise aussi la redéclaration d'un même nom dans la même portée sans broncher, ce qui masque les fautes de frappe :

index.js
Output
Click Run to see the output here.

Le code moderne utilise quasiment toujours let et const. On croise encore var dans le code legacy, dans de vieilles réponses sur Stack Overflow, ou dans des scripts qui doivent tourner sur des environnements vraiment anciens.

Le hoisting et la Temporal Dead Zone

Les trois déclarations subissent le hoisting — le moteur connaît leur existence avant même d'exécuter le code du bloc — mais leur comportement diffère avant la ligne de déclaration.

var est hoisté et initialisé à undefined. Tu peux donc y faire référence avant la ligne var sans déclencher d'erreur :

index.js
Output
Click Run to see the output here.

let et const sont hoistés, mais pas initialisés. Y toucher avant la déclaration déclenche une erreur. Cette zone entre l'entrée dans le scope et l'exécution de la déclaration porte un nom : la temporal dead zone (TDZ) :

index.js
Output
Click Run to see the output here.

La TDZ est une fonctionnalité, pas un bug. Elle transforme un « utilisé avant déclaration » qui passait silencieusement à undefined en une vraie erreur bien visible, ce qui permet d'attraper pas mal de fautes de frappe et d'erreurs d'ordre dans le code.

La variable de boucle const dans for...of

Petit cas fréquent mais intéressant : les boucles for...of créent une nouvelle liaison à chaque itération. Tu peux donc utiliser const pour la variable de boucle, même si celle-ci « change » d'une itération à l'autre.

index.js
Output
Click Run to see the output here.

Chaque itération crée sa propre liaison name — il n'y a pas une seule variable qui se fait réassigner à chaque tour. Par contre, un bon vieux for (let i = 0; i < n; i++) a toujours besoin de let, parce que i correspond à une seule liaison qu'on incrémente.

Une règle pratique

Pour choisir entre les déclarations, suivez cet ordre de préférence :

  • const par défaut. Si la valeur n'est pas censée être réassignée, autant le dire clairement.
  • let quand la liaison doit réellement changer.
  • var uniquement si vous travaillez sur un code existant qui l'impose.

Appliqué de manière systématique, ce réflexe rend l'intention de chaque variable évidente au premier coup d'œil — réassignable ou non, limitée à ce bloc ou à cette fonction.

index.js
Output
Click Run to see the output here.

MAX_RETRIES et users ne bougent jamais — donc const. successful évolue au fil du temps — let. user, lui, est une nouvelle liaison à chaque itération — const. En lisant le code de haut en bas, on voit tout de suite ce qui change et ce qui reste fixe, sans avoir besoin de l'exécuter.

La suite : les types primitifs

Maintenant que tu sais déclarer une variable en JavaScript, la question logique c'est : quels types de valeurs peut-elle contenir ? JavaScript a un petit ensemble de types primitifs — nombres, chaînes, booléens et quelques autres — chacun avec ses petites subtilités. C'est ce qu'on va voir sur la page suivante.

Questions fréquentes

Quelle est la différence entre let, const et var en JavaScript ?

const et let ont une portée de bloc et sont arrivés avec ES2015 ; var a une portée de fonction et date d'avant. Une liaison const ne peut pas être réassignée, une liaison let si. var subit un hoisting et est initialisée à undefined, alors que let et const sont aussi hoistées mais inutilisables tant que leur déclaration n'a pas été exécutée — c'est la fameuse temporal dead zone.

Est-ce que const rend une valeur immuable en JavaScript ?

Non. const empêche uniquement la réassignation de la liaison. Si la valeur est un objet ou un tableau, on peut toujours modifier son contenu — const user = {}; user.name = 'Ada' passe sans broncher. Pour une vraie immuabilité, il faut passer par Object.freeze ou une bibliothèque dédiée.

Faut-il encore utiliser var en JavaScript moderne ?

Quasiment jamais. let et const ont des règles de portée plus claires et font remonter davantage de bugs dès le parsing. Les seuls endroits où l'on croise encore var, ce sont les vieilles bases de code et les rares scripts qui doivent tourner dans des environnements sans ES2015.

Apprendre à coder avec Coddy

COMMENCER