10

First , let's see the code.

var a=0;
b=1;
document.write(a);
function run(){
    document.write(b);
    var b=1;
}
run();

I think the result is 01 .but in fact , The result is 0undefined.

Then I modify this code.

var a=0;
b=1;
document.write(a);
function run(){
    document.write(this.b); //or document.write(window.b)
    var b=1;
}
run();

Yeah, this time it runs as expected. 01 . I can't understand, WHY?

More interesting, I modify the code again .

var a=0;
b=1;
document.write(a);
function run(){
    document.write(b);
    //var b=1;       //I comment this line
}
run();

The result is 01.

So , Can anyone explain this?

Thanks for share your viewpoints. I simplify this code

b=1;
function run(){
    console.log(b); //1
}

two:

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

three:

b=1;
function run(){
    console.log(b); //undefined
    var b=2;
}
SeasonHuang
  • 157
  • 1
  • 1
  • 9
  • Note, the way I read this question originally was you were wondering why `this.b` works (as well as `window.b`), but but just plain `b` does not work before the `var b...` in the function. `this` and `window` are the same in that context. This could be confusing if you've seen objects created using functions and local scope, but that's because functions can be used as constructors. Also, the effect of a `var` statement "rising" to the top of the scope *before* execution is called [hoisting](http://bonsaiden.github.com/JavaScript-Garden/#function.scopes). This is why `var b...` is local. – Jared Farrish Aug 15 '12 at 02:37
  • See my comments: http://jsfiddle.net/userdude/NMxdU/6/ You need a console open, like Firebug or Chrome console. – Jared Farrish Aug 15 '12 at 02:51

4 Answers4

18

When you refer to a variable within a function JS first checks if that variable is declared in the current scope, i.e., within that function. If not found it looks in the containing scope. If still not found it looks in the next scope up, and so forth until finally it reaches the global scope. (Bear in mind that you can nest functions inside each other, so that's how you get several levels of containing scope though of course your exmaple doesn't do that.)

The statement:

b=1;

without var declares a global variable that is accessible within any function, except that then in your first function you also declare a local b. This is called variable shadowing.

"But", you say, "I declare the local b after document.write(b)". Here you are running into declaration "hoisting". A variable declared anywhere in a function is treated by the JS interpreter as if it had been declared at the top of the function (i.e., it is "hoisted" to the top), but, any value assignment happens in place. So your first function is actually executed as if it was like this:

function run(){
    var b;              // defaults to undefined
    document.write(b);  // write value of local b
    b=1;                // set value of local b
}

In your second function when you use this.b, you'll find that this refers to window, and global variables are essentially properties of window. So you are accessing the global b and ignoring the local one.

In your third function you don't declare a local b at all so it references the global one.

nnnnnn
  • 147,572
  • 30
  • 200
  • 241
3

When you write b = 1, you're creating a property in the global object.
In an ordinary function, b will refer to this global.

Since your function contains var b;, b within the function refers to the local variable. (var statements create local variables throughout the function, no matter where the var is).
However, the executable portion of the var statement (b = 1) is only executed at that point.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
  • 1
    But crucially, even though `var b = 1;` occurs after the `document.write()`, `var b` is defined in context of the function, still undefined until it is later initialized to 1. – Michael Berkowski Aug 15 '12 at 02:12
  • It seems this doesn't answer the op's question. – xdazz Aug 15 '12 at 02:13
3

The var directive is processed on the pre-execution stage, the b becomes local variable before document.write(b);, so at that time, b is undefined.

Note: assign a value to a variable is at the execution time, so you could image your code is like below.

function run(){
    document.write(b);
    var b=1;
}

is the same as:

function run(){
    var b;
    document.write(b);
    b=1;
}

Addtion:

This is why Put every var definition at the top of the function is good practice.

xdazz
  • 158,678
  • 38
  • 247
  • 274
  • @JaredFarrish `this` in that function is `window`, and `window['b']` is the global `b`. – xdazz Aug 15 '12 at 02:24
  • In that case, the answer is [hoisting](http://bonsaiden.github.com/JavaScript-Garden/#function.scopes). – Jared Farrish Aug 15 '12 at 02:29
  • 1
    _"The code with_ `this` _is very clear and no need to answer."_ - It's clear to the people who answered, but I don't know that it's clear to the OP, and it may not be clear to others who stumble upon this question later. Given the question boils down to "Which `b` is which?" some people might think `this.b` refers to the local `b`, especially since both the local and global ones are set to `1`. – nnnnnn Aug 15 '12 at 02:46
0

This code work fine for me

  if(var_name === "undefined"){
     alert(var_name+' : undefined');
   }
Sandeep Sherpur
  • 2,418
  • 25
  • 27