0

I'm trying to understand block scoping on ES6 and found the following issue (maybe I'm just misunderstanding the concept):

In the first test I tried the following and got the commented error:

{
    const x = 2;
    console.log( x );   //2
    {
        let x = "b";
        console.log(x); //b
        {
            var x = true; //Identifier 'x' has already been declared
        }
    }

}
console.log(x)

But when I try to get the type of the "already declared" x I get :

{
    const x = 2;
    console.log( x );   //2
    {
        let x = "b";
        console.log(x);  //b
        {
            console.log(typeof x); //this throws Uncaught ReferenceError: x is not defined
        }
    }

}
console.log(x);

I'll keep trying to see what is going on, any ideas are accepted.

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
CRz
  • 51
  • 3
  • I tried the typeof without declaring in that block to see wich one of the above it was taking, or any hint to find out what happened – CRz Nov 27 '17 at 19:56

2 Answers2

2

Actually, your error comes from the final console.log(x);. Removing that line makes your code work fine.

This error makes perfect sense. x is only defined in inner blocks; it doesn't exist in the outer scope.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • In that case it would throw a Reference Error, try removing it and it would still have the same result. I know the error is for usinr "var" but don't now the exact answer. – CRz Nov 27 '17 at 20:40
0

First of all, you need to know the difference between let and var

let allows you to declare variables that are limited in scope to the block, statement, or expression on which it is used. This is unlike the var keyword, which defines a variable globally, or locally to an entire function regardless of block scope. An explanation of why the name "let" was chosen can be found here. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/let

Second, you got this error "Identifier 'x' has already been declared" because you already have "let x" so you can't use "var x". However, if you change the var to let, it will work.

Example to understand scoping:

function test() {     // first scope
   let x = 1;
   let y = 2;
   console.log(x, y); //1 2

   function test2() {  // second scope
     let x = 2;
     let z = 3;
     console.log(x,y,z); //2 2 3

   }
   test2();
   console.log(z); //z is not defined... notice z is defined in the second scope, not the first one
}
test();

Keep in mind, you can access variables from higher/global scopes in inner scopes, but you can't access variables from inner scopes in higher/global scopes.

Read this: What is the scope of variables in JavaScript?

EDIT:

If you do this, it should work fine

const x = 2;
console.log( x );   //2
{
    let x = "b";
    console.log(x); //b
    {
         x = true;
    }
}
console.log(x)

OR

const x = 2;
console.log( x );   //2
{
    let x = "b";
    console.log(x); //b
    {
        let x = true;
    }
}
console.log(x)
Moe kanan
  • 189
  • 12
  • Thanks for your answer @moe-kanan. I have read and understand the concepts and differences, but in this case I would like to know the exact cause and reason for the error. I tought the js hoisting would make the inner x (var) global, but not sure why is showing this specific behavior. – CRz Nov 27 '17 at 20:43
  • Yes I have tested some other scenarios (loops, if) and looked that the **var** under the **let** will show the same error, but with functions it worked fine. I guess is part of the spec but couldn't find a direct answer on the docs, I think this solve it. – CRz Nov 27 '17 at 21:01
  • @CRz Yes, I guess "let" respects the curly brackets, but var don't :) – Moe kanan Nov 27 '17 at 21:03