4

I write this simple program to update value of JS hoisting. But as per my understanding global x need to update, but It is not updating.

x = 5;
var w = function(){
    x = 7
    var x;
    console.log(x);
    x = 10;
    console.log(x);
};
w();
console.log(x);

Output:

  • 7
  • 10
  • 5

Could anyone explain in more details why it did not update global x ?

Javascript work on reference of values so when I write x = 7, it should be update the global x. But it din't! So I just want to why x =7 doesn't work ?

Thanks!

Pankaj Jatav
  • 2,158
  • 2
  • 14
  • 22
  • The `x` you redeclare inside the function shadow the global one. – ibrahim mahrir Apr 21 '17 at 23:55
  • Hey Guys, I just updated my question. I have good experience in js. So I have idea about scopping and how can i solve this issue. But I just want to know why x =7 doesn't update ? – Pankaj Jatav Apr 22 '17 at 00:02
  • I am defining local x after the x =7, So x =7 should be update the global and then compiler move to next line. But x= 7 didn't update global, This is my main concern? – Pankaj Jatav Apr 22 '17 at 00:04
  • JS differ from most other languages on scopes. JS doesn't implement block-scopes, the only scope in JS is function scopes. When you declare a variable inside a function scope, it shadows the outer ones no matter where you declare it (as the last instruction, or even inside an `if` or a `for`, ... or even inside 1000 `for`s deep as long as it is still in that function scope). – ibrahim mahrir Apr 22 '17 at 00:09
  • @ibrahimmahrir his main concern is probably *declaration hoisting*, not *local/global scoping* – nicholaswmin Apr 22 '17 at 00:11
  • Yes @NicholasKyriakides You got my point. Please check my comment as well – Pankaj Jatav Apr 22 '17 at 00:12
  • It is not an error, I am exploring the JS for me. – Pankaj Jatav Apr 22 '17 at 00:12
  • [MDN](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Statements/var) Says that _Variable declarations, wherever they occur, are processed before any code is executed..._ – ibrahim mahrir Apr 22 '17 at 00:21

3 Answers3

9

The moment you declared a variable inside your function, it masked the global variable due to the way scoping rules work from inner to outer. So, function level var x variable is found first and not the global one that you expected.

JS converted your function from :

function(){
    x = 7
    var x;
    console.log(x);
    x = 10;
    console.log(x);
}

to this:

function(){
    var x;
    x = 7
    //var x;
    console.log(x);
    x = 10;
    console.log(x);
}

To your question about updating x = 7 and then declaring var x, let me explain it a bit more. Javascript code is not just executed, there is a compilation phase too. In this phase var declarations are looked inside the function(apart from so many other things that happen but I am just sticking to the question at hand). If found, they are moved at the top of the function. This is called hoisting. At this time you can think that your code has been modified by JS(order of var declaration and assignment doesn't matter now). If you just think of code being interpreted then order matters but as I said, due to compilation phase the hoisting occurs and not thinking in these terms causes the confusion you have. Once you look at it from compilation, hoisting angle, things look clearer.

Hope it helps! For further study, please read/listen Kyle Simpson who is authority on javascript.

Pankaj Shukla
  • 2,657
  • 2
  • 11
  • 18
4

Because you redeclared x in your function's local scope. That's the one you assigned 10 to, instead of the global one.

Ditch the var x; and it will work.

x = 5;
var w = function(){
    x = 7
    // var x;
    console.log(x);
    x = 10;
    console.log(x);
};
w();
console.log(x);

That being said, what's probably baffling you is hoisting

Hoisting is JavaScript's default behavior of moving all declarations to the top of the current scope (to the top of the current script or the current function).

x = 5;
var w = function(){
    x = 7
    var x; // this is moved to the top of the local scope
    console.log(x);
    x = 10;
    console.log(x);
};
w();
console.log(x);
nicholaswmin
  • 21,686
  • 15
  • 91
  • 167
  • 1
    You can complement your answer explaining the way scopping works in Javascript and why redeclaring x inside the function overrode global x – Lixus Apr 22 '17 at 00:00
  • 1
    @Lixus you can as well by hitting the "edit" button - feel free – nicholaswmin Apr 22 '17 at 00:01
  • 1
    So you want to say that if I update any global variable inside any function and any point I define the same local variable name as same name as global variable. Then all the update on global function will reset ? – Pankaj Jatav Apr 22 '17 at 00:10
  • 1
    No, read the 2nd part of my question - The `var x;` inside your function is *hoisted* to the top of your function "before" it's actually assigned a value within your function. **You are always assigning a value to your function's local `var x` inside your function**. That's why you are not overriding your global at all – nicholaswmin Apr 22 '17 at 00:12
  • 2
    Thanks @NicholasKyriakides. I got it. "Hoisting works well with other data types and variables as well. The variables can be initialized and used before declared. But they cannot be used without initialization." This make perfect sound to me. – Pankaj Jatav Apr 22 '17 at 00:21
2

Always remember , local variable has highest precedence over any other and also please use proper naming conventions for the global and local variables thus preventing you from causing this kind of errors. They are very hard to be detected in huge project.