0

I don't understand why var overwrites the value of the global variable inside a function before its called.

const VAR1=3
document.onclick=()=>{
    console.log(VAR1);
    // var VAR1=2;
    console.log(VAR1);
}

When I click, this logs

3
3

as expected but if I uncomment var VAR1=2;, I get

undefined
2

instead of

3
2

Even though I wouldn't have expected it to modify the global scope.

The reason I encountered this was when I was writing a library I said LIB_VERSION=x and I can then test to see the version in the program that uses it and avoid it breaking with a random error message.

But since some old versions of the library don't have this defined I said

function testVersion(){
    if (typeof LIB_VERSION==='undefined'){
        var LIB_VERSION="Unknown Version";
    }
    if (LIB_VERSION!==3){
        console.log("Your version of the library "+LIB_VERSION+" is not compatible with this program");
    }
}

I know there are several workarounds I was curious as to why this happened.

Something else I noticed was if I put a console.log(LIB_VERSION) just before the if statement I would find that LIB_VERSION was undefined before even entering the if (so if it had something in it it gets erased).

Thanks in advance!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459

2 Answers2

0

It's not overwriting the global value - indeed, you can't, because const VAR1 creates a constant - this can never be directly reassigned by using =. Your code is experiencing variable hoisting - here's an explanation:

Your code contains two variables of the same name - one outside of the function (global scoped) and one inside the function (local scoped).

You are attempting to read the variable inside of the function before you assign it. This makes your code equivalent to this:

const VAR1 = 3;
document.onclick = () => {
    var VAR1;
    console.log(VAR1);
    VAR1 = 2;
    console.log(VAR1);
}

If you run your code without the local-scoped variable, then it works by looking at the global scope (because variables work from the current scope outwards):

const VAR1 = 3;
document.onclick = () => {
    //There's no VAR1 here, so it goes out a level and looks for VAR1 there and so on until it finds it.
    console.log(VAR1);
    console.log(VAR1);
}
Jack Bashford
  • 43,180
  • 11
  • 50
  • 79
0

This has to do with a hoisting effect of your VAR variable inside the event handler. So this

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Document</title>
</head>
<body>
    <script>
     const VAR = 3;
     document.onclick = function(event) {
         console.log(VAR); // undefined, VAR in so-called Temporary Dead Zone
         var VAR = 2;
         console.log(VAR); // 2
     };
    </script>
</body>
</html>

is equivalent to this

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8"/>
    <title>Document</title>
</head>
<body>
    <script>
     const VAR = 3;
     document.onclick = function(event) {
         var VAR; // VAR declared but NOT defined, so VAR again in TDZ
         console.log(VAR); // undefined
         VAR = 2; // VAR defined
         console.log(VAR); // 2
     };
    </script>
</body>
</html>

You might want to read more about hoisting, Old-School var declarations and TDZ. -- Regards, M.

Micha
  • 181
  • 5
  • I apologize to Jack Bashford, his answer was first, and I couldn't say it any better. However, while I was writing my answer, I wasn't aware of Jack already posting his. – Micha Mar 31 '19 at 00:52