Quel état est tenu entre les lignes JavaScript?

Je me demandais quels états sont conservés entre deux lignes de code JavaScript soumises à babel-node . Ma confusion se pose parce que si vous écrivez deux lignes de code, vous pouvez remplacer une définition de variable sans erreur. Par exemple, avec babel-node --presets es2015 , vous pouvez:

 > const a = 1; undefined > let a = 2; undefined 

Maintenant, si vous l'écrivez en une seule ligne, vous obtenez une erreur:

 > const a = 1; let a = 2; TypeError: repl: Duplicate declaration "a" ... 

Il semble que, dans le premier cas, l'état que a est défini comme 1 (affectation de variable const ) est perdu (mais pas jusqu'à la deuxième affectation), alors que dans le second cas, il est maintenu.

Qu'est-ce qui cause les différences ici? Et quels états sont maintenus?

Parce que const et let sont de nouvelles syntaxes, elles doivent être transpilées au seul mécanisme de liaison disponible avant ES6: var . Dans ce cas, var permet toutes sortes de réaffectation au hasard sans générer d'avertissement.

Donc, lorsque vous tapez une expression dans babel-node , babel transpile, l'évalue, puis affiche le résultat. Babel peut vérifier l'utilisation abusive d'une liaison const au moment du transpile, c'est pourquoi vous voyez l'erreur pour const a = 1; let a = 2 const a = 1; let a = 2 . Mais const a = 1 et let a = 2 , lorsqu'il est transpilé / évalué comme expressions séparées, ne montrera pas l'erreur car Babel n'est pas capable de détecter un problème dans l'une ou l'autre expression.


Une démonstration plus visuelle du problème: pour chaque expression expr vous tapez le REPL de babel-node , c'est essentiellement ce qui se passe

 evaluate(transpile(expr)) // => someResult 

Donc, vous ne verrez pas une erreur ici

 evaluate(transpile('const a = 1')) evaluate('var a = 1') // bind a to 1 // return undefined evaluate(transpile('let a = 2')) evaluate('var a = 2') // bind a to 2 // return undefined 

Mais vous verrez une erreur ici

 evaluate(transpile('const a = 1; let a = 2')) // ERROR during transpile: const a has already been declared 

Je n'utilise pas babel-repl , mais il doit être quelque chose à voir avec la conversion, car tout fonctionne comme prévu avec le REPL régulier:

 $ node -v v7.4.0 $ node > const a = 1; undefined > let a = 1; SyntaxError: Identifier 'a' has already been declared > const b = 1; let b = 1; const b = 1; let b = 1; ^ SyntaxError: Identifier 'b' has already been declared > .editor // Entering editor mode (^D to finish, ^C to cancel) const c = 1; let c = 1; let c = 1; ^ SyntaxError: Identifier 'c' has already been declared