Why does shadowed variable evaluate to undefined when defined in outside scope?

Consider the following piece of code:

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
        }
        f1();
    </script>
</body>
</html> 

The output for this code is that the alert box displays the message "outside scope". But, if I slightly modify the code as:

<html><head></head>
<body>
    <script type="text/javascript">
        var outside_scope = "outside scope";
        function f1() {
            alert(outside_scope) ;
            var outside_scope = "inside scope";
        }
        f1();
    </script>
</body>
</html> 

the alert box displays the message "undefined". I could have understood the logic if it displays "undefined" in both the cases. But, that is not happening. It displays "undefined" only in the second case. Why is this?

Thanks in advance for your help!


Variables are subject to hoisting. This means that regardless of where a variable is placed within a function, it is moved to the top of the scope in which it is defined.

For example:

var outside_scope = "outside scope";
function f1() {
    alert(outside_scope) ;
    var outside_scope = "inside scope";
}
f1();

Gets interpreted into:

var outside_scope = "outside scope";
function f1() {
    var outside_scope; // is undefined
    alert(outside_scope) ;
    outside_scope = "inside scope";
}
f1();

Because of that, and the function only scope that JavaScript has, is recommended to declare all the variables at the top of the function, to resemble what will happen.


In the first case, your code is accessing the global variable "outside_scope", which has been initialized to "outside scope".

Javascript has function level scope, so in the second case it is accessing the function scoped variable "outside_scope", but it has not yet been initialized at the time of the alert box. So it displays undefined.


JavaScript has function scope, not block scope.

In the second case, the declaration of outside_scope is hoisted up to the top of the function (but the assignment isn't).

This is a great example of why JavaScript code is easier to read if you put all your variable declarations up at the top of the function. Your second example is equivalent to:

function f1() {
    var outside_scope;
    alert(outside_scope);
    outside_scope = "inside scope";
}

and you can probably now understand why you're getting "undefined."