21
function foo(str, a) {
  eval( str );
  console.log( a, b );
}

foo( "var b = 3;", 1 ); 

This works just fine, but when we use let instead of var, it does not work. Why?

Yosvel Quintero
  • 18,669
  • 5
  • 37
  • 46
Kenny Omega
  • 398
  • 2
  • 12
  • 10
    why are you using eval? – Tschallacka Apr 30 '18 at 10:10
  • 4
    @Tschallacka Why not? Seems an interesting question about scopes to me. Even more so when the usual go-to alternative, `new Function`, [behaves differently](https://i.stack.imgur.com/2w2K6.png). – James Thorpe Apr 30 '18 at 10:11
  • 1
    Doing this is a bad practice, but I don't know why is this not working with let –  Apr 30 '18 at 10:12
  • Checked in the browser console, eval only works with var and not with const and let even if you do this global scope –  Apr 30 '18 at 10:14
  • 1
    @JamesThorpe I'm always curious when someone uses eval to what their tought behind it is. – Tschallacka Apr 30 '18 at 10:15
  • Possible useful reading [**eval documentation**](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) – Nope Apr 30 '18 at 10:25

1 Answers1

24

Because eval introduces a new block of code. The declaration using var will declare a variable outside of this block of code, since var declares a variable in the function scope.

let, on the other hand, declares a variable in a block scope. So, your b variable will only be visible in your eval block. It's not visible in your function's scope.

More on the differences between var and let

EDIT : To be more precise eval + let do, in fact, create a Lexical Environment. See @RobG response in Define const variable using eval()

Guillaume Georges
  • 3,878
  • 3
  • 14
  • 32
  • You haven't shown how *eval* crates a block. I think the correct answer is [*linked by Nope*](https://stackoverflow.com/questions/43188732/define-const-variable-using-eval): using *let* in *eval* causes it to run in strict mode, where eval'd code doesn't create variables in the enclosing execution context. – RobG Apr 30 '18 at 10:21
  • 3
    Worth mentioning that the context in eval is slightly more complex than a few lines of explanation. The official ECMAScript documentation explains how the PerformEval operation actually works according to the external context: https://www.ecma-international.org/ecma-262/6.0/#sec-eval-x (18.2.1 and 18.2.1.1). Not extremely relevant, but it's worth taking a look to that, in my opinion. – briosheje Apr 30 '18 at 10:23
  • 1
    @briosheje—yes, but probably should link to [*ECMAScript 2017*](http://ecma-international.org/ecma-262/8.0/#sec-eval-x), soon to be replaced by ECMAScript 2018. ;-) – RobG Apr 30 '18 at 10:26
  • 1
    @RobG: yup, indeed, far more updated (also, it would be interesting to see how it changed in the last years, I don't see some "major" changes, but it's different). – briosheje Apr 30 '18 at 10:29
  • @briosheje—I don't know if there are changes, like probably 99.999% of scripters I don't ever use *eval* so it's just an oddity. ;-) – RobG Apr 30 '18 at 10:33
  • @RobG: I don't as well, but it was an interesting question anyway, otherwise I would have **never** looked at the official eval documentation :D – briosheje Apr 30 '18 at 10:35
  • @RobG I read Nope's link. And I'm not convinced. Please see my last edit. – Guillaume Georges Apr 30 '18 at 10:39
  • @RogerC—maybe, but there is no evidence of a block either. It is a duplicate question, but perhaps there is not yet a good answer. There is an issue with the acceptance and voting system here on SO that the people who vote on questions often have no idea whether it's a good answer or not. And MDN is no paragon, it can have incorrect information. – RobG Apr 30 '18 at 11:27
  • @RogerC eval indeed creates a block scope, and let won't last after the block is done executing. Thanks for the help mate. I appreciate it.. – Kenny Omega Apr 30 '18 at 11:45
  • @RogerC—I've added an answer at the duplicate. It's not block scope nor is it automatic strict mode, it relates to lexical environments which are created by blocks and direct calls to eval. – RobG Apr 30 '18 at 11:55
  • @KennyOmega—no it doesn't, there is no block. – RobG Apr 30 '18 at 11:56
  • 1
    @RobG - ok, if it does not create a block scope, then what happens? Please add a link to any resource that explains it. Thanks in advance... – Kenny Omega Apr 30 '18 at 12:04
  • the let keyword is block scoped –  Sep 13 '20 at 15:43