Why do some variables declared using let inside a function become available in another function, while others result in a reference error?

bleat interteiment picture bleat interteiment · Jan 27, 2020 · Viewed 12k times · Source

I can't understand why variables act so strange when declared inside a function.

  1. In the first function I declare with let the variables b and c with the value 10:

    b = c = 10;
    

    In the second function I show:

    b + ", " + c
    

    And this shows:

    10, 10
    
  2. Also in first function I declare a with value 10:

    let a = b = c = 10;
    

    But in the second function it shows an error:

    Can't find variable: a

  3. Now in the first function I declare d with value 20:

    var d = 20;
    

    But in the second function it shows the same error as before, but with the variable d:

    Can't find variable: d

Example:

Answer

Tim Consolazio picture Tim Consolazio · Jan 27, 2020

It's because you're actually saying:

c = 10;
b = c;
let a = b;

And not what you think you are saying, which is:

let a = 10;
let b = 10;
let c = 10;

You'll notice that no matter how many variables you add to your chain, it will only be the first (a) that causes the error.

This is because "let" scopes your variable to the block (or, "locally", more or less meaning "in the brackets") in which you declare it.

If you declare a variable without "let", it scopes the variable globally.

So, in the function where you set your variables, everything gets the value 10 (you can see this in the debugger if you put a breakpoint). If you put a console log for a,b,c in that first function, all is well.

But as soon as you leave that function, the first one (a)--and again, keep in mind, technically in the order of assignment, it is the last one-- "disappears" (again, you can see this in the debugger if you set a breakpoint in the second function), but the other two (or however many you add) are still available.

This is because, "let" ONLY APPLIES TO (so only locally scopes) THE FIRST VARIABLE--again, which is technically the last to be declared and assigned a value--in the chain. The rest technically do not have "let" in front of them. So those are technically declared globally (that is, on the global object), which is why they appear in your second function.

Try it: remove the "let" keyword. All your vars will now be available.

"var" has a similar local-scope effect, but differs in how the variable is "hoisted", which is something you should definitely understand, but which is not directly involved with your question.

(BTW, this question would stump enough pro JS devs to make it a good one).

Strongly suggest you spend time with the differences in how variables can be declared in JS: without a keyword, with "let", and with "var".