Redeclare JavaScript Variable

2020-02-10 06:17发布

In the following code:

var greeting = "hi";

function changeGreeting() {
    if (greeting == "hi") {
        var greeting = "hello";
    }

    alert(greeting);
}

changeGreeting();​

...greeting is undefined. However if I remove the var and change changeGreeting() to this:

function changeGreeting() {
    if (greeting == "hi") {
        greeting = "hello";
    }

    alert(greeting);
}

...I get "hello" as expected.

I would never redeclare a variable like this in my code, but why does this happen?

3条回答
淡お忘
2楼-- · 2020-02-10 07:00

It's very simple: JS hoist the Variable declarations to the top of the current scope, but any operations (including assignments) aren't hoisted (within the same scope, see second case explanation), of course. So your snippet is translated to

(function()
{
    var currentSize;//undefined
    if (currentSize == 'hi')//always false
    {
        currentSize = 'hello';//assignment that will never be
    }
    alert(currentSize);//alerts undefined, of course
}());

By leaving out the var, proceeds to scope scanning (checking for the variable being declared in the global scope). Sadly, in doing so, the context of the first use of the var is lost (inside a branch), and the assignment is hoisted, too. An implied global is translated to:
Thank god this isn't true. I assumed it was, because I tested a couple of things in the console that seemed to corroborate this. In this case @amadan is right: you're using the global variable (called greeting in your snippet by mistake when I posted this). I'm going to leave the code below (corrected it) to show what implied globals actually are, hoping it helps somebody sometime in understanding scopes/scope-scanning in JS.

var currentSize = 'hello';
//well, actually implied globals can be deleted, so it's more like
Object.defineProperty(this,'currentSize',{value:undefined,
                                          writable:true,
                                          enumerable:true,
                                          configurable:true});
(function()
{
    if (currentSize == 'hi')//always false
    {//this still doesn't get executed
        currentSize = 'hello';//assignment that will never be
    }
    alert(currentSize);//alerts undefined
}());
查看更多
The star\"
3楼-- · 2020-02-10 07:12

JavaScript variables have function scope. Thus, the very presence of var greeting inside the function will declare a local greeting variable, which will be undefined at the time of its mention in if condition: the global variable will not be visible inside the function, being overshadowed by the local one. Therefore, the if does not happen, the assignment to hello doesn't happen, the variable is still undefined.

In the second example, you're using the global variable throughout, it is not overshadowed by a local variable (because, no var greeting inside the function), and things work as you expect.

查看更多
狗以群分
4楼-- · 2020-02-10 07:17

In your first code snippet, you're checking global variable, which doesn't exist -> doesn't pass if condition.

Check out this on javascript scopes and how to work with variables Javascript garden - function scopes

查看更多
登录 后发表回答