Team LiB   Previous Section   Next Section

4.3 Variable Scope

The scope of a variable is the region of your program in which it is defined. A global variable has global scope -- it is defined everywhere in your JavaScript code. On the other hand, variables declared within a function are defined only within the body of the function. They are local variables and have local scope. Function parameters also count as local variables and are defined only within the body of the function.

Within the body of a function, a local variable takes precedence over a global variable with the same name. If you declare a local variable or function parameter with the same name as a global variable, you effectively hide the global variable. For example, the following code prints the word "local":

var scope = "global";         // Declare a global variable

function checkscope(  ) {

    var scope = "local";      // Declare a local variable with the same name

    document.write(scope);    // Use the local variable, not the global one

}

checkscope(  );               // Prints "local" 

Although you can get away with not using the var statement when you write code in the global scope, you must always use var to declare local variables. Consider what happens if you don't:

scope = "global";               // Declare a global variable, even without var

function checkscope(  ) {

    scope = "local";            // Oops! We just changed the global variable

    document.write(scope);      // Uses the global variable

    myscope = "local";          // This implicitly declares a new global variable

    document.write(myscope);    // Uses the new global variable

}

checkscope(  );                 // Prints "locallocal"

document.write(scope);          // This prints "local"

document.write(myscope);        // This prints "local" 

In general, functions do not know what variables are defined in the global scope or what they are being used for. Thus, if a function uses a global variable instead of a local one, it runs the risk of changing a value upon which some other part of the program relies. Fortunately, avoiding this problem is simple: declare all variables with var.

In JavaScript 1.2 (and ECMAScript v3), function definitions can be nested. Each function has its own local scope, so it is possible to have several nested layers of local scope. For example:

var scope = "global scope";          // A global variable

function checkscope(  ) {

    var scope = "local scope";       // A local variable

    function nested(  ) {

        var scope = "nested scope";  // A nested scope of local variables

        document.write(scope);       // Prints "nested scope"

    }

    nested(  );

}

checkscope(  ); 

4.3.1 No Block Scope

Note that unlike C, C++, and Java, JavaScript does not have block-level scope. All variables declared in a function, no matter where they are declared, are defined throughout the function. In the following code, the variables i, j, and k all have the same scope: all three are defined throughout the body of the function. This would not be the case if the code were written in C, C++, or Java:

function test(o) {

    var i = 0;                         // i is defined throughout function

    if (typeof o == "object") {

        var j = 0;                     // j is defined everywhere, not just block

        for(var k = 0; k < 10; k++) {  // k is defined everywhere, not just loop

            document.write(k);

        }

        document.write(k);             // k is still defined: prints 10

    }

    document.write(j);                 // j is defined, but may not be initialized

} 

The rule that all variables declared in a function are defined throughout the function can cause surprising results. The following code illustrates this:

var scope = "global";

function f(  ) {

    alert(scope);         // Displays "undefined", not "global"

    var scope = "local";  // Variable initialized here, but defined everywhere

    alert(scope);         // Displays "local"

}

f(  ); 

You might think that the first call to alert( ) would display "global", since the var statement declaring the local variable has not yet been executed. Because of the scope rules, however, this is not what happens. The local variable is defined throughout the body of the function, which means the global variable by the same name is hidden throughout the function. Although the local variable is defined throughout, it is not actually initialized until the var statement is executed. Thus, the function f in the previous example is equivalent to the following:

function f(  ) {

    var scope;        // Local variable is declared at the start of the function

    alert(scope);     // It exists here, but still has "undefined" value

    scope = "local";  // Now we initialize it and give it a value

    alert(scope);     // And here it has a value

} 

This example illustrates why it is good programming practice to place all of your variable declarations together at the start of any function.

4.3.2 Undefined Versus Unassigned

The examples in the previous section demonstrate a subtle point in JavaScript programming: there are two different kinds of undefined variables. The first kind of undefined variable is one that has never been declared. An attempt to read the value of such an undeclared variable causes a runtime error. Undeclared variables are undefined because they simply do not exist. As described earlier, assigning a value to an undeclared variable does not cause an error; instead, it implicitly declares the variable in the global scope.

The second kind of undefined variable is one that has been declared but has never had a value assigned to it. If you read the value of one of these variables, you obtain its default value, undefined. This type of undefined variable might more usefully be called unassigned, to distinguish it from the more serious kind of undefined variable that has not even been declared and does not exist.

The following code fragment illustrates some of the differences between truly undefined and merely unassigned variables:

var x;     // Declare an unassigned variable. Its value is undefined.

alert(u);  // Using an undeclared variable causes an error.

u = 3;     // Assigning a value to an undeclared variable creates the variable. 
    Team LiB   Previous Section   Next Section