Why I cannot access this variable inside this simple function?

Viewed 1005

Im new to Javascript and I dont understand whats happening how the scope works in the following codes:

//Code n°1:

let num = 1;

function test(){
    console.log(num);
}

test()       //As I expected I get in console "1"
//Code n°2:

let num = 1;

function test(){
    let num = 2;
    console.log(num);
}

test()       //As I expected I get in console "2"

But here is the problem:

//Code n°3:

let num = 1;

function test(){
    console.log(num)
    let num = 2;
    console.log(num);
}

test()       //I expected to get in console "1" and then "2" but instead I get an error.

When I run in my browser the code n° 3 Im getting this error: Uncaught ReferenceError: can't access lexical declaration 'num' before initialization

If I look at code 1 and 2 I suppose that after running code 3 I will get in my console the number 1 and then number 2. But that isnt happening. Why?

Thank you so much!

4 Answers

The JavaScript exception "can't access lexical declaration `variable' before initialization" occurs when a lexical variable was accessed before it was initialized. This happens within any block statement, when let or const declarations are accessed before they are defined.

When the 'test function' is called, the function body gets executed. When it reaches to 'console.log(num)', it starts to search for the 'num variable declaration' (or 'num assignment' or 'num reassignment) in the test function scope. So it finds the variable declaration in the next line. The priority for searching for a variable is:

  1. Current Scope
  2. Closure
  3. Scope Chain

So, when the variable declaration is found i the current scope, searching is not continued to scope chain. (It will not search for num variable in global scope.)

I guess this is the reason of the error, but as I am new to javaScript, I am not completely sure.

If you initialize the variable without redeclaring, it will work normally, now if you redeclar the variable, then this error will happen with let or var, because in the same scope, it is being called by the previous console.log(). It is not recommended that you re-declare let variables, if you need to, don't use the same in previous statement, note that if you comment on the first console.log(), the code will work again, this occurs exactly for the lifetime of the variable within this scope, in this case, let

let num = 1;

function test(){

    console.log(num)
    let num = 2;
    console.log(num);
}

test()

Bacause in javascript functions and variables declared with var are hoisted, moved up to the top of the function/lexical block.

But let keyword respect the lexical flow. It pins variable where it is declared.

console.log try to access a variable that is declared bellow in the flow. So move up manually your let declaration to be above de console.log or change it to var let num = 2; to let javascript engine move it above all automatically.

var num = 1;

function test(){
    let num = 2;
    console.log(num);
}

test() 

or

var num = 1;

function test(){
    console.log(num)
    var num = 2;
    console.log(num);
}

test() 

or, to get access to global var num, which is shadowed by declarations from test's body, var or let, no matter

var num = 1;

function test(){
    console.log(num)
    //let num = 2;
    console.log(num);
}

test() 
Related