3

Hi I have a snippet of code. I am confused about change of value x1 when I remove non-related part of same code. I searched about it and I came to know that it has to do with hoisting. But the value x1 is still unclear even with hoisting concept for me. Can someone please make me clear on this?

var x = 10;               
    
function main() {
  document.write("<br>x1 is " + x);
  x = 20;
  if (x > 0) {
    var x = 30;
    document.write("<br>x2 is " + x);
  }
  var x = 40;
  var f = function(x) { 
    document.write("<br>x3 is " + x); 
  }
  f(50);
}

main();

The output of this code is:

x1 is undefined
x2 is 30
x3 is 50

If I change this code to:

        
var x = 10;

function main() {
  document.write("<br>x1 is " + x);  
}

main();

The output is:

x1 is 10

Boann
  • 48,794
  • 16
  • 117
  • 146
amulamul
  • 372
  • 3
  • 14

2 Answers2

2

So what is happening here is a common pitfall.

The simplest way to put this is. When you set var x = 30 inside your main function, you are actually redefining the scope that var x = 10 had for use inside this function. This has to do with how Javascript executes and scope.

By defining x inside the function, your scope for x has changed. Below is an example of what I mean and a version of your code that works

Example:

var test = 'test';
function run(){
    console.log(test);
    var test=1;
}

Your Code Updated:

var x = 10; 
        function main() {
            console.log("<br>x1 is " + x);
            x = 20;
            if (x > 0) {
                x = 30;
                console.log("<br>x2 is " + x);
            }
            x = 40;
            var f = function(x) { console.log("<br>x3 is " + x); }
            f(50);
        }
        main();

Good question btw.

Since this is somewhat of a very interesting scope of how Javascript executes, consider the following code and its outputs to get the full idea

var test = 'test';

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

console.log(test);

run();

console.log(test);

Very interesting to see how this reacts.

Jesse
  • 2,790
  • 1
  • 20
  • 36
  • They actually redefine scope in var x = 30; they sign the original x to 20 just fine. – EasyBB Oct 16 '15 at 03:36
  • 1
    Not sure whether you mean the right thing by "killing the scope". At least "removing it's scope" is wrong, if at least horribly misleading. There simply are multiple scopes, and now there are *two variables* with the *same name* in the different scopes. – Bergi Oct 16 '15 at 03:39
  • @Bergi - You are right, edited for future visitors – Jesse Oct 16 '15 at 03:40
  • @Jesse In "Your updated code" section I can see you removed var from var x= 30. I assume you did this to make x scope global so that it won't be hoisted within scope of a function. This makes sense but the output of x1 is still undefined which means var or no var it has no effect whatsoever on the output. – amulamul Oct 16 '15 at 03:51
1

All variable and function declarations get "hoisted" or moved to the top of their scope. The undefined value for x is caused because the var x statement gets moved up to the top of main however the assignment = 30 does not.

So, your code will read more like this:

var x = 10;                             // x is 10
function main() {
    var x;                              // x declaration is "hoisted"
    document.write("<br>x1 is" + x);    // x1 is undefined
    x = 20;                             // x is 20
    if (x > 0) {
        x = 30;                         // x is 30
        document.write("<br>x2 is" + x);// x2 is 30
    }
    x = 40;                             // x is 40
    var f = function(x) {               // x is 50
        document.write("<br>x3 is" + x);// x3 is 50
    }
    f(50);
}
main();

You can read more about Hoisting here: JavaScript Scoping and Hoisting

jungy
  • 2,932
  • 2
  • 18
  • 17