31 votes

Pourquoi la redéclaration d'un argument à l'intérieur d'un try/catch entraîne-t-elle une ReferenceError ?

J'ai écrit par erreur une re-déclaration d'un argument en tant que const dans une fonction et au lieu de lancer SyntaxError: Identifier 'bar' has already been declared Je me suis retrouvé avec ReferenceError: bar is not defined. .

Quelle est la cause de ce comportement ? Ce n'était pas l'erreur attendue, et cela m'a laissé perplexe pendant quelques minutes.

Exemple de code :

function foo(bar) {
  try {
      console.log(bar);
      const bar = 123;
  } catch(err) { console.log(err) }
}
foo(456);

Si je n'englobe pas la déclaration dans un try/catch, j'obtiens (ce que je crois être) l'erreur attendue.

19voto

Marcus Parsons Points 482

Les constantes ont une taille de bloc, tout comme les variables définies à l'aide de l'instruction let.

De cet article de MDN.

Puisque vous avez emballé bar à l'intérieur d'un bloc d'accolades, sa définition est relative à ce bloc. Et comme vous avez un autre bar à l'intérieur de ce bloc, bien qu'elle se trouve après l'appel à ce bloc, le compilateur tentera d'utiliser cette nouvelle définition de la déclaration bar au lieu du paramètre transmis. Renommez-les en tant que paramètres distincts pour limiter la confusion, car on peut supposer qu'ils contiennent des données différentes à cause de votre déclaration.

8voto

Cerbrus Points 20704

Parce que const ont une portée de bloc, les déclarations const bar la déclaration est hissée au début du bloc. (Juste après try { )

Cela signifie que bar n'est pas vraiment défini quand vous essayez de l'enregistrer, parce que le levage Remplace / cache le paramètre bar .

8voto

T.J. Crowder Points 285826

C'est un mythe que const et let ne sont pas du tout hissés. Ils sont moitié - hoisis. :-) C'est-à-dire : Dans un bloc, si const bar ou let bar (ou class bar { } d'ailleurs) apparaît n'importe où dans ce bloc, alors bar ne peut pas être utilisé avant cette déclaration dans le bloc - même s'il existe dans une portée contenue. Cette zone située entre le début du bloc et la déclaration s'appelle le Zone morte temporelle :

function foo(bar) {
  // `bar` is fine here
  try {
      // Temporal Dead Zone, `bar` cannot be used here
      console.log(bar);
      // End of TDZ
      const bar = 123;
      // `bar` would be fine here
  } catch(err) { console.log(err) }
}
foo(456);

3voto

mike123 Points 8

Tiré d'ici https://tylermcginnis.com/videos/var-let-const/

var a une portée de fonction et si vous essayez d'utiliser une variable déclarée avec var avant la déclaration proprement dite, vous obtiendrez simplement une valeur indéfinie. const et let ont une portée bloquée et si vous essayez d'utiliser une variable const ou let avant la déclaration, vous obtiendrez une erreur de référence.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X