1. Computing

The Scope of Variables

By

JavaScript is different from almost all other programming languages in the way that variable scope works. Scope is that part of the program processing during which the particular variable exists.

In most languages the scope of a variable starts from where the variable is defined and runs to the end of the block in which it is defined. This is called "block scope". If JavaScript supported block scope (which it doesn't then the "i" variable defined in the following code would cease to exist at the end of the loop).


for (var i = x.length - 1; i >= 0; i--) {
...
}
// "i" no longer defined here for block scope

Because JavaScript doesn't support block scope the value of "i" continues to exist after the loop has completed. This means that any use of another variable of the same name outside the loop is in fact referring to the same variable even though the intention may have been to have two totally separate variables. So with multiple loops one after the other each using similar code to control the loop actually reuse the same variable rather than each creating their own and then deleting it again at the end of the loop.

Now this isn't a huge problem since the same code works either way but you do need to be aware that it is happening since the different scope of variables from what you are used to in other languages can end up causing unexpected problems when you forget that your variables continue to exist and try to use the same name for a different purpose.

Variables in JavaScript are all defined with global scope by default. In fact the biggest problem with JavaScript is that it doesn't insist on your defining variables before using them and will create a variable with global scope .the first time a variable is referenced if that reference isn't defining the variable (and perhaps therefore giving it a different scope).

Consider the following code which contains a typo.


var carrot = 'vegetable';
if (carot === 'vegetable') {...

Because of the typo we now have two separate variables which have different values and hence the if statement does not return the expected result. Most other languages require that you define variables before you use them and so would detect this typo as an error. This is in fact such a big problem that ECMAScript 5 introduces a new "strict" mode to JavaScript where you can insist that variables be defined before use and where this error would then be able to be detected. You just need all your visitors to be running browsers that support a version of JavaScript based on ECMAScript 5 to be able to apply this validation.

The only scope that JavaScript provides for variables other than global scope is function scope. A variable defined inside a function exists from when the function starts to run until the function finishes. Provided that we actually define the variable somewhere inside the function (using the "var" keyword), all references to that name within the function will be considered to be references to that variable with function scope and not to a variable of the same name with global scope. Consider the following:


var x = 0;
function y() {
x = 1;
alert(x);
var x = 2;
alert(x);
}
y();
alert(x);

The value displayed by the last of these alerts may surprise you if you are used to the way that scope usually works in programs other than JavaScript. If it doesn't surprise you then you are familiar with the way the scope of variables in JavaScript works.

Perhaps the biggest problem relating to scope in JavaScript is that variables are global unless they are defined inside a function. This leads to te very common problem people have of having obtained two scripts that they want to use on the same page where either will run by itself but where the two together will not run because of a conflict of variables between the scripts.

The solution to this is to wrap all your processing inside of functions so that the variables have function scope. Unfortunately that still leaves the functions themselves in the global scope where their names can still conflict with one another. The way around that is to use an anonymous function (one without a name) as the wrapper and code it so that the function runs immediately after it has been defined.


(function() {
// code to be removed from global scope goes here
})();

With this code there are three sets of parentheses. The ones following the word function are what makes this an anonymous function as otherwise there would be a function name between the word "function" and the parentheses. Any arguments the function uses would be defined inside there. The parentheses right on the end are the ones that tell the function to run immediately. Any parameters being passed into the function would appear in there. As it is an anonymous function running itself there is no point passing anything into the function. The last set of parentheses (around the entire function) is there because a statement starting with the keyword function is assumed to be a function declaration using te function foo() {...{ format whereas our anonymous function is actually using the var foo = function() {...} format but without assigning the function to anything.

Being able to write your JavaScript code so as to minimise what appears in the global scope will reduce the chances of your code interfering with other JavaScript code that might be added to the same page. Unfortunately, the way that JavaScript is defined makes it far more difficult to apply the appropriate scope to variables that it is in other languages (note that am not saying that it can't be done, just that the constructs required to do so are significantly different from what you would need in other languages that look similar).

  1. About.com
  2. Computing
  3. JavaScript
  4. Problem Solving
  5. The Scope of Variables

©2014 About.com. All rights reserved.