JavaScript Variable Scope

In this tutorial I will demonstrate some of the fundamental rules of variable and object scope in JavaScript. We all know how important it is to understand how scope works in each programming language, and not every language applies the same rules. With a clear understanding of how this works in JavaScript, you will be well equipped to write code that is easier to read and will avoid stepping on others’ (and your own) toes. If you want to skip the reading you can go right to a complete working example.

As a side note, one of my favorite things about JavaScript is “closures”. We won’t go over closures in this tutorial, but I will probably write another tutorial about them in the future. Some discussion about JSON will probably be appropriate for that tutorial as well.

JavaScript Global Variables

In JavaScript global variables and objects are accessible by all code under the “window” object, at all levels. Global variables can be created a few ways.

// omitting "var" from the definition will create the variable under the "window" object, wherever the variable is defined.
a = "I am a string.";
 
// using var will create the variable under the window object only if the code is executed at the document level.
var b = 101;
 
// the following explicitly defines the variable as a property of the window object.
window.c = 22.5;

Use Globals Responsibly

While variables with global scope have their purpose, you will probably not want to define everything at the window object level. The reason is that you, or someone else, may inadvertently read or alter a value that shouldn’t be. As an example let’s suppose you are writing some JavaScript on a page where another JavaScript author’s code has been included somewhere in the document. Their code has something to do with fruit, and so does yours.

// a different author's code
fruit = "apple";

Later in the document you have your own code.

// your code.
fruit = "pineapple";

Oops! You’ve changed the value of their variable.

Take Advantage Of Local Scope

You’ll need to be careful defining variables without “var”. To be safe I like to use “var” or the parent object’s name when defining variables. Let’s look at another example.

// a globally defined variable
var name = "John";
 
function HerName(){
    // this is supposed to be a local variable, but we forgot to use "var"
    name = "Sarah";
    return name;
}
 
alert('His name is ' + name);
// alerts 'John'
 
alert('Her name is ' + HerName());
// alerts 'Sarah'
 
alert('His name is ' + name);
// alerts 'Sarah'

It’s easy to forget that if a variable is defined in a function, omitting var or the parent object name will define a global variable, or access one that already exists.

A Complete Variable Scope Test

If you would like to see some of the items discussed feel free to copy this example segment and try it out yourself.

<html>
<head>
    <script type="text/javascript">
 
        // These variables are all created under the 'window' object.  In other words,
        // they have global scope.
        var a = "I am a string.";
        b = 10;
        this.c = { firstName: 'Fred', lastName: 'Jones' };
 
        function Test1(){
 
            Output("=====Begin Test 1=====");
 
            // since 'var' is not used to create this variable it is placed under
            // the 'window' object and is globally accessible.
            d = "I am a global variable.";
 
            // since this variable is created with the 'var' keyword it has
            // local scope to this function.  it cannot be accessed outside this function
            // and we don't risk changing any global variable that might also be
            // named 'e'.
            var e = "I am a local variable.";
 
            // *** Output the values of our global variables. ***
            Output(a);
            // I am a string.
 
            Output(b);
            // 10
 
            Output(c);
            // [object Object]
 
            Output(d);
            // I am a global variable.
 
 
            // *** Output the value of our local variable. ***
            Output(e);
            // I am a local variable.
 
            // Assign new values.
            a = 'A different string';
            b = 33;
            c = 101;
            d = 'I am d and I have changed.';
            e = 'I am still a local variable.';
 
            Output("=====End Test 1=====");
            Output("");
 
            // Variable 'e' will be destroyed once we leave
            // this function.
        }
 
        function Test2(){
 
            Output("=====Begin Test 2=====");
 
            // *** Output the values of our global variables. ***
            Output(a);
            // A different string
 
            Output(b);
            // 33
 
            Output(c);
            // 101
 
            Output(d);
            // I am d and I have changed.
 
            // *** Is variable 'e' from our previous test function still alive? ***
            Output(typeof e != 'undefined');
            // false
 
            Output("=====End Test 2=====");
            Output("");
        }
 
        function Test3(){
 
            Output("=====Begin Test 3=====");
 
            // This code demonstrates that global variables can be accessed
            // without the parent object or with it.  It some cases it is
            // safest to access a global explicity through the window object, just
            // in case a local variable has been declared with the same name.
            Output(a);
            // A different string
 
            Output(window.a);
            // A different string
 
            Output("=====End Test 3=====");
            Output("");
        }
 
        function Test4(){
 
            Output("=====Begin Test 4=====");
 
            // Declare a local variable with the same name.  If 'window' is omitted
            // in a reference then the local variable will be used.
            var a = 'I am local.';
            Output(a);
            // I am local.
 
            // Compare values
            Output(window.a == a);
            // false
 
            Output("=====End Test 4=====");
            Output("");
        }
 
        function Test5(){
 
            Output("=====Begin Test 5=====");
 
            var p = new Person();
 
            p.AssignName('Fred', 'Jones');
 
            p.OutputProperties();
            // Fred
            // Jones
 
            p.firstName = 'Charles';
            Output(p.firstName);
            Output(p.lastName);
            // Charles
            // Jones
 
            Output(p.height);
            // 50
 
            p.height = 10;
            Output(p.height);
            // 10
 
            Output(window.middleName);
            // Doofus
 
            p.OutputMore();
            // undefined undefined undefined
 
            // (THIS CALL FAILS)
            // p.GetMoreInformation();
 
            // (THIS CALL FAILS)
            // GetMoreInformation();
 
            Output("=====End Test 5=====");
            Output("");
        }
 
        function Person(){
 
            // These variables are unique to each Person object.  They are publicly accessible.
            var firstName = '';
            var lastName = '';
            this.height = 50;
 
            // Since this variable is not created with 'var' or 'this' it will be part of the 'window' object.
            // It could also be written as:
            // window.middleName = 'Doofus';
            middleName = 'Doofus';
 
            // The next three functions are also associated with this object, so they can access
            // the other properties of this object.
            this.AssignName = function(firstName, lastName){
                this.firstName = firstName;
                this.lastName = lastName;
            };
            this.OutputProperties = function(){
                Output(this.firstName);
                Output(this.lastName);
            };
            this.OutputMore = function(){
                Output(GetMoreInformation());
            };
 
            // this function does not have access to the object's data.  however, it is
            // locally scoped, so it can be called inside this object but not outside.
            function GetMoreInformation(){
                return this.firstName + " " + this.lastName + " " + this.height;
            }
 
        }
 
        function Output(text){
            document.getElementById('output').innerHTML += text + "<br />";
        }
 
    </script>
</head>
<body>
 
    <button onclick="Test1(); return false;">Test #1</button>
    <button onclick="Test2(); return false;">Test #2</button>
    <button onclick="Test3(); return false;">Test #3</button>
    <button onclick="Test4(); return false;">Test #4</button>
    <button onclick="Test5(); return false;">Test #5</button>
 
    <div id="output"></div>
 
</body>
</html>