0

How will the code look after hoisting is done by js? jsFiddle shows it prints 1, but how is that true?

var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

This is what I have come up with:

var a;              //hoisted var declaration
function b() {      //hoisted function declaration
    function a() {} //hoisted function declaration
    a = 10;
    return; 
}
a=1;
b();
alert(a);
kheya
  • 7,546
  • 20
  • 77
  • 109

4 Answers4

2

This is expected behaviour.

var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

This all has to do with the scope and when a function is defined. Declaring a function with the codeword function first

function a(){};

will add the function to the scope at parse time. I.E It is defined before the first line in b(). What is happeing is that you define a to be a loal variable inside b. This will make the global variable a unreachable from within b. a will be defined and manipulated locally within the scope of b and leave the global a untouched.

Equivalient code will be

var a = 1;
function b() {
    var a = function() {}
    a = 10;
    return;
}
b();
alert(a);
Ole Borgersen
  • 1,094
  • 9
  • 9
  • If you add the following alerts to the start of "b" function: "alert(a);" and "alert(window.a);" you will see that this answer seems to be correct... – Yaniv Efraim Sep 29 '14 at 08:39
1

After some experimentation, i've reached to the conclusion that having the same Global variable and local function name is confusing the JS Engine..

So what you are doing by a = 10 is changing that function declaration or something.. it's not affecting the global variable a. But, changing the name of global variable and keeping it different from the inner local function will give the expected results:

var c;              //hoisted var declaration
function b() {      //hoisted function declaration
    function a() {alert('in');} //hoisted function declaration
    c = 10;
    return; 
}
c=1;
alert(c); //1
b();
alert(c); //10

See the DEMO here

Abdul Jabbar
  • 2,573
  • 5
  • 23
  • 43
1
var a = 1;
function b() {
    a = 10;
    return;
    function a() {}
}
b();
alert(a);

There is nothing confusing here. Moving all declaration to the top, your code is the same as:

var a;                      //global a
var b = function(){
    var a = function(){};   //local a
    a = 10;                 //still referring to local a
    return;
};
a = 1;                      //referring to global a
b();
alert(a);                   //referring to global a

Both a aren't the same. I believe it is quite obvious.

Derek 朕會功夫
  • 92,235
  • 44
  • 185
  • 247
  • var b = function(){ } is totally different from function b(). Function expression won't be hoisted while function declaration will be. – kheya Sep 29 '14 at 18:03
  • @kheya - They are the same after moving them all to the top. – Derek 朕會功夫 Sep 29 '14 at 18:05
  • Therefore `function b()` and `var b = function ()` are completely the same. They do exactly the same thing in the browser's internal code except the latter one doesn't have the `b.name` set. You can read more about their differences [here](http://stackoverflow.com/a/3435763/283863). – Derek 朕會功夫 Sep 29 '14 at 18:19
  • As far fas hoisting is concerned, they will be treated differently. – kheya Sep 29 '14 at 18:34
  • @kheya - The equivalent code I posted is representing the code *after* hoisting. Of course they will be treated differently in normal cases, but not in my demonstration code. In reality the browser will internally move all of them to the top, initialize them right away, and set the `.name` property. You can see the exact same thing in my code, so they are *exactly* the same (ignoring the `.name` property.) Nothing will be treated differently. – Derek 朕會功夫 Sep 29 '14 at 18:37
1

The first code example given appears to be identical to one on Ben Cherry's adequately good site. This goes into more detail on the way scoping works in JavaScript (primarily - it's function-level, not block-level), and ends with the following statement, attributed directly to the ECMAScript Standard:

If the variable statement occurs inside a FunctionDeclaration, the variables are defined with function-local scope in that function, as described in section 10.1.3. Otherwise, they are defined with global scope (that is, they are created as members of the global object, as described in section 10.1.3) using property attributes.

...

A Block does not define a new execution scope. Only Program and FunctionDeclaration produce a new scope.

This hopefully explains why the code you include works the way it does - there is no "way the code looks after hoisting", there's just a simple (and, common) misunderstanding about how scope works in JavaScript.

Community
  • 1
  • 1
Adrian Wragg
  • 7,311
  • 3
  • 26
  • 50