Movatterモバイル変換


[0]ホーム

URL:


  1. Web
  2. JavaScript
  3. Référence
  4. Instructions
  5. let

Cette page a été traduite à partir de l'anglais par la communauté.Vous pouvez contribuer en rejoignant la communauté francophone sur MDN Web Docs.

View in EnglishAlways switch to English

let

Baseline Widely available

Cette fonctionnalité est bien établie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis ⁨septembre 2016⁩.

L'instructionlet permet de déclarer une variable dont la portée est celle du bloc courant, éventuellement en initialisant sa valeur.

Exemple interactif

let x = 1;if (x === 1) {  let x = 2;  console.log(x);  // Expected output: 2}console.log(x);// Expected output: 1

Syntaxe

js
let var1 [= valeur1] [, var2 [= valeur2]] [, …, varN [= valeurN]];

Paramètres

var1,var2, …,varN

Le nom de la ou des variables. Ces noms doivent être des identifiants JavaScript valides.

valeur1,valeur2, …,valeurNFacultatif

Pour chaque variable déclaré, on peut indiquer, de façon optionnelle, sa valeur initiale. Ces valeurs peuvent être n'importe quelle expression légale.

Description

let permet de déclarer des variables dont la portée est limitée à celle dubloc dans lequel elles sont déclarées. Le mot-clévar, quant à lui, permet de définir une variable globale ou locale à une fonction (sans distinction des blocs utilisés dans la fonction).

Une autre différence entrelet etvar est la façon dont la variable est initialisée : pourlet, la variable est initialisée à l'endroit où le parseur évalue son contenu (cf. ci-après).

À l'instar deconst,let ne crée pas de propriété sur l'objetwindow quand les variables sont déclarées au niveau global.

L'origine du nomlet est décritedans cette réponse (en anglais).

Les portées de bloc aveclet

Le mot-clélet permet de définir des variables au sein d'un bloc et des blocs qu'il contient.var permet quant à lui de définir une variable dont la portée est celle de la fonction englobante.

js
if (x > y) {  let gamma = 12.7 + y;  i = gamma * x;}function varTest() {  var x = 1;  if (true) {    var x = 2; // c'est la même variable !    console.log(x); // 2  }  console.log(x); // 2}function letTest() {  let x = 1;  if (true) {    let x = 2; // c'est une variable différente    console.log(x); // 2  }  console.log(x); // 1}

Une meilleure lisibilité pour les fonctions internes

let peut parfois permettre de rendre le code plus lisible lorsqu'on utilise des fonctions internes.

js
var list = document.getElementById("list");for (let i = 1; i <= 5; i++) {  var item = document.createElement("li");  item.appendChild(document.createTextNode("Élément " + i));  item.onclick = function (ev) {    console.log("Clic sur l'élément " + i + ".");  };  list.appendChild(item);}// Pour obtenir le même effet avec var// il aurait fallu créer un contexte différent// avec une fermeture (closure) pour la valeurfor (var i = 1; i <= 5; i++) {  var item = document.createElement("li");  item.appendChild(document.createTextNode("Item " + i));  (function (i) {    item.onclick = function (ev) {      console.log("Item " + i + " a reçu un clic.");    };  })(i);  list.appendChild(item);}

Dans l'exemple précédent, cela fonctionne comme on l'attend car les cinq instances de la fonction anonyme sont liées à cinq instances différentes dei. Si on remplacelet parvar, on n'obtiendra pas l'effet escompté car on aura une même variable pour cette portéei=6 (au lieu de 5 différentes).

Règles de portées

Les variables déclarées aveclet appartiennent à la portée du bloc dans lequel elles sont définies et indirectement aux portées des blocs de ce bloc. D'une certaine façonlet fonctionne commevar, la seule différence dans cette analogie est quelet fonctionne avec les portées de bloc etvar avec les portées des fonctions :

js
function varTest() {  var x = 31;  if (true) {    var x = 71; // c'est la même variable !    console.log(x); // 71  }  console.log(x); // 71}function letTest() {  let x = 31;  if (true) {    let x = 71; // c'est une variable différente    console.log(x); // 71  }  console.log(x); // 31}

Au niveau le plus haut (la portée globale),let crée une variable globale alors quevar ajoute une propriété à l'objet global :

js
var x = "global";let y = "global2";console.log(this.x); // "global"console.log(this.y); // undefinedconsole.log(y); // "global2"

Émuler le fonctionnement des interfaces privées

En utilisant l'instructionlet avecdes constructeurs, on peut créer desinterfaces privées sans avoir à utiliserde fermetures :

js
var Truc;{  let porteePrivee = new WeakMap();  let compteur = 0;  Truc = function () {    this.unePropriete = "toto";    porteePrivee.set(this, {      cachee: ++compteur,    });  };  Truc.prototype.montrerPublique = function () {    return this.unePropriete;  };  Truc.prototype.montrerPrivee = function () {    return porteePrivee.get(this).cachee;  };}console.log(typeof porteePrivee);// "undefined"var truc = new Truc();console.log(truc);// Truc {unePropriete: "toto"}truc.montrerPublique();// "toto"truc.montrerPrivee();// 1

Cette technique permet d'obtenir un état privé « statique ». Ainsi, dans l'exemple qui précède, toutes les instances deTruc partageront la mêmeportéePrivée.Il était possible d'obtenir un tel isolement avecvar mais il fallait passer par des fonctions isolées (généralement des fonctions immédiatement appelées (IIFE)).

Zone morte temporaire (Temporal Dead Zone / TDZ) et les erreurs liées àlet

Lorsqu'on redéclare une même variable au sein d'une même portée de bloc, cela entraîne une exceptionSyntaxError.

js
if (x) {  let toto;  let toto; // SyntaxError}

Avec ECMAScript 2015 (ES6),letremontera (hoisting) la déclaration variable au début de la portée (au début du bloc) mais pas l'initialisation. Si on fait référence à une variable dans un bloc avant la déclaration de celle-ci aveclet, cela entraînera une exceptionReferenceError. En effet, la variable est placée dans une « zone morte temporaire » entre le début du bloc et le moment où la déclaration est traitée. Autrement dit, la déclaration est bien remontée mais la variable ne peut pas être utilisée tant que l'affectation (qui n'est pas remontée) n'a pas été effectuée.

js
function faire_quelque_chose() {  console.log(truc); // undefined  console.log(toto); // ReferenceError  let toto = 2;  var truc = 1;}

Il est possible d'obtenir des erreurs au sein de l'instructionInstructions/switch. En effet, il y a un seul bloc implicite pour cette instruction.

js
switch (x) {  case 0:    let toto;    break;  case 1:    let toto; // SyntaxError for redeclaration.    break;}

Par contre, si on ajoute une instruction de bloc dans la clausecase, cela créera une nouvelle portée et empêchera l'erreur :

js
let x = 1;switch (x) {  case 0: {    let toto;    break;  }  case 1: {    let toto;    break;  }}

Autres situations

Lorsqu'on utiliselet dans un bloc, sa portée est limitée à celle du bloc. On notera ici la différence avecvar dont la portée est celle de la fonction où il est utilisé.

js
var a = 1;var b = 2;if (a === 1) {  var a = 11; // la portée est la portée globale  let b = 22; // la portée est celle du bloc if  console.log(a); // 11  console.log(b); // 22}console.log(a); // 11console.log(b); // 2

Cependant, la combinaison utilisée ci-après déclenchera une exceptionSyntaxError car la déclaration avecvar est remontée en haut du bloc et il y a donc une redéclaration implicite de la variable (également utilisée aveclet).

js
let x = 1;if (true) {  var x = 2; // SyntaxError liée à la redéclaration}

La zone morte temporaire ettypeof

Si on utilisetypeof sur des variables non déclarées ou qui valentundefined, on obtiendra la valeurundefined. Mais si on utilisetypeof sur une variable au sein de la zone morte temporaire de cette variable, cela déclenchera uneReferenceError :

js
console.log(typeof variableNonDeclaree); // affiche 'undefined'console.log(typeof i); // ReferenceErrorlet i = 10;

Autre exemple lié à la zone morte temporaire et aux portées lexicales

Dans l'exemple qui suit, dans l'expressiontoto + 55, l'identifianttoto fait référence à la variable du bloc courant et non à celle qui est déclarée au dessus et qui a la valeur 33. Dans l'instructionlet toto = (toto + 55); l'instruction est bien remontée mais l'endroit où on utilisetoto (dans le fragment(toto + 55)) est toujours dans la zone morte temporaire cartoto n'a pas encore été affecté.

js
function test() {  var toto = 33;  if (true) {    let toto = toto + 55; // ReferenceError: can't access lexical declaration `toto` before initialization  }}test();

Si on utiliselet avec un nom de variable qui est le même que celui de l'argument passé à la fonction, on aura une erreur due à la confusion des portées :

js
function go(n) {  for (let n of n.a) {    // ReferenceError: can't access lexical declaration `n' before initialization    console.log(n);  }}go({ a: [1, 2, 3] });

Les variables déclarées aveclet et les bouclesfor

Le mot-clélet permet de lier des variables localement dans la portée des boucles for. Contrairement au mot-clé var qui lui rend les variables visibles depuis l'ensemble de la fonction qui contient la boucle.

js
var a = 0;for (let i = a; i < 10; i++) {  console.log(i);}

Règles de portées

js
for (let expr1; expr2; expr3) instruction;

Dans cet exemple,expr2,expr3, etinstruction sont contenues dans un bloc implicite qui contient la variable de bloc local déclarée aveclet expr1.

Exemples

let /var

Lorsqu'il est utilisé dans un bloc,let permet de limiter la portée de la variable à ce bloc.var quant à lui limite la portée de la variable à la fonction.

js
var a = 5;var b = 10;if (a === 5) {  let a = 4; // La portée est celle du bloc if  var b = 1; // La portée est celle interne à la fonction  console.log(a); // 4  console.log(b); // 1}console.log(a); // 5console.log(b); // 1

let utilisé dans les boucles

Le mot-clé let permet de lier des variables à la portée de la boucle plutôt qu'à celle de la fonction (avecvar) :

js
for (let i = 0; i < 10; i++) {  console.log(i); // 0, 1, 2, 3, 4 ... 9}console.log(i); // i n'est pas défini

Spécifications

Specification
ECMAScript® 2026 Language Specification
# sec-let-and-const-declarations

Compatibilité des navigateurs

Voir aussi

Help improve MDN

Learn how to contribute

Cette page a été modifiée le par lescontributeurs du MDN.


[8]ページ先頭

©2009-2025 Movatter.jp