'Hoisted' JavaScript Variables

I do not fully understand why the following displays "hoisted" towards the end.

var x = 'set';
var y = function () 
{
    // WHAT YOU DON'T SEE -> var x; 
    // is effectively "hoisted" to this line!

    if (!x) 
    { 
        // You might expect the variable to be populated at this point...it is not
        // though, so this block executes
        var x = 'hoisted'; 
    }

    alert(x); 
}

//... and this call causes an alert to display "hoisted"
y();

Any pointers would be appreciated.

Answers:

Answer

Quoting MDN Docs on var hoisting,

Because variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it's declared. This behavior is called "hoisting", as it appears that the variable declaration is moved to the top of the function or global code.

So, in your case, JavaScript knows that a local variable (not the one declared outside) x is defined somewhere in the function, but it does not know the actual value of it until the execution reaches an assignment statement which assigns to x. (Declarations are processed during the compile time and assigments are done in the execution time) Till the assignment is done, the default value undefined will be used. Since undefined is falsy, the condition

if (!x) {

is satisfied and the assignment statement is executed. That is why you are getting hoisted in the alert box.


Let's say you have not declared x inside the function,

var x;

var y = function () {
    if (!x) {
        x = 'hoisted';
    }
    alert(x);
}

y();
alert(x);

Here, since x is not declared anywhere within the function, at runtime, JavaScript will look for x in the higher scopes. In this case, it finds it right outside the function. So, that x will be used. Since you assigned hoisted to x, the inner alert will also say hoisted and after leaving the function, alert(x) will also alert hoisted.

Answer

In javascript console.log inside a function gives undefined as output for unpassed parameters but outside the function it gives not defined error as inside a function browsers explicitly declares the variable. For e.g

console.log(x) 

gives VM1533:1 Uncaught ReferenceError: x is not defined whereas

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

gives undefined. It is because the function test() is rewritten by browser as:

function test(x) {
    var x;
    console.log(x)
    }

Another Example : -

var x =5 ;
function test(x) {
console.log(x)
}
test(); 

is still undefined as the function becomes

function test(x) {
    var x;
    console.log(x)
    }

The alert in the below example will give undefined :-

    var x =5;
    function test() {
    alert(x);
    var x =10;
    }

test(); 

The above function will become :-

 function test() {
    var x;
    alert(x);
    x =10;
    }

The scope of javascript variable inside a function is function level scope and not block level. For e.g.

function varScope() {

for(var i = 0; i < 10; i++){
    for(var j = 0; j < 5; j++){}
        console.log("j is "+j)
    }
    console.log("i is "+i);


}
varScope();

will give output as :

j is 5 
i is 10

Again the function has become as :-

  function varScope() {
    var i;
    var j;
    for(i = 0; i < 10; i++){
        for(j = 0; j < 5; j++){}
            console.log("j is "+j)
        }
        console.log("i is "+i);
    }
Answer

Variable declarations hoist to the top of the scope. So your code is equivalent to this:

var x = 'set';
var y = function () {
    var x;
    if (!x) {
        x = 'hoisted';
    }
    alert(x);
}

y();

When y is executed, var x shadows outer scope x so inside of the y function x is undefined after the first line of declaration.

Answer

this answer explain in very detail the different scopes of the variables. In your particular case you can use the reference to:

this.x; 

To access to the global x variable outside the function. Because inside of the function you are trying to access to an undefined variable, using the this keyword you make a reference to variables outside of the function.

And the part of

if(!x)

It's true because you are testing: is false and x in that point is undefined because does not exist in the function scope, and undefined is consider one of the false values in JS, for more info please take a look here.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.