Variable Scope and Closure

Self-Executing Anonymous Functions

We're going to enhance the bitmap.js file from our last exercise by wrapping it inside a self-executing (self-starting) anonymous function that looks like this:

(function () {

//put your Javascript code inside the curly brackets
.
.
})();

First, let's discuss the syntax and then we'll talk about why we'd want to wrap our code in a self-executing anonymous function. An anonymous function is a function without a name that bundles together several lines of code.

Remember the rotateImage() function we created in the last exercise? That's a more typical function that's named and you call it from different places in your code. With an anonymous function, you're often more concerned with running several lines of code at a particular moment rather than creating a reusable block of code that'll be called again and again.

We start our anonymous function with a left parenthesis, the right closing parenthesis comes on the last line after the curly bracket. Notice that we have two more parentheses after that closing parentheses—those parentheses make this anonymouse function self-executing, meaning all the code inside the function runs when the function is loaded. We need that to get things started.

The rest of the anonymous function syntax is similar to a typical function, only the function name is missing. We start with function, followed by opening and closing parentheses, followed by a left-facing curly bracket. After that bracket, we write all the code we want to be associated with the function, ending our function with a right-facing curly bracket at our last line of code.

Variables Scope

So why would we want to do this? When we write a variable the way we've been doing up to this point—type the var keyword and set the variable equal to a value—that variable is assigned to the window object, the main object of our web page. You can test this out with a couple of lines of JavaScript code. Create an HTML page, add a script tag, and type the following lines of JavaScript:

var globalVariable = "I can be accessed by everything!";
console.log("window globalVariable: " + window.globalVariable);

When you look at your browser's Console window, you'll see that window.globalVariable has the value of 'I can be accessed by everything!'. All of our variables (and functions) up to this point, are implicitly tied to the main, global window object.

Why would that be a problem? Attaching variables to the window object works fine when we're creating simple, one-off scripts. But as our code gets more complicated and we include several javascript files in our web page, if any of those scripts have the same variable names, we'll be overriding one variable's value with another variable's value.

If, for example, one script assigns a value to a variable and assumes it's the only script with access to that variable, then a second script comes along and assigns a new value to a variable with the same name, the first script no longer has control of that variable. The first script assumes it has control of that variable but the fact is the second script is using that variable for its own purposes.

Here's a more concrete example. Imagine we have two canvases on one page. First we place two canvas tags with unique ids in our HTML—let's say those ids are myCanvas1 and myCanvas2. We also have two script tags that bring in the scripts—one script creates the canvas and context for our first canvas tag and the other script creates the canvas and context for our second tag.

Here are a couple of code snippets; one script targets the first canvas and the other script targets the second canvas:

//Script 1
var canvas = document.getElementById('myCanvas1'),
context = canvas.getContext('2d');
.
.

//Script 2
var canvas = document.getElementById('myCanvas2'),
context = canvas.getContext('2d');
.
.

We've attached our uniquely identified canvas tags to the same variable name! When script 1 runs, canvas is set to the first canvas. When script 2 runs, canvas is re-assigned to the second canvas on our web page. This happens because our canvas variable is implicitly tied to the browser window object and the code in script 2 removes the original connection to our first canvas and replaces it with a reference to the second canvas. This means that any code in Script 1 that assumes it's working with the first canvas is actually working with the second canvas—that'll create some unexpected results.

You could avoid this problem by changing the variable names in each script. We could, for example, name our canvas and context variables canvas1 and context1 in our first script and canvas2 and context2 in our second script. This might work for a while if your project isn't too complex and you're very careful to make sure you have unique variables in every script you create for your page.

But what happens when you bring in scripts from other people or haven't checked carefully the code in every script you include in your page? You're very likely to have conflicts—we just noted the possible variable problems, but you could even have two functions with the same name in different scripts, each with very different code logic. The script that was last loaded would replace the previous same-name function in the other script and cause havoc in the first script's code.

To prevent this kind of confusion, we simply wrap each script in an anonymous function. Variables and functions have scope—that is, they can be accessed in some places and are inaccessible in other places. When you implicitly attach variables and functions to the main window object, you're giving your variables and functions global scope—they can be accessed by any script or object on your page. When you wrap your variables and functions inside an anonymous function, their scope is local—they can only be accessed inside that anonymous function. Wrapping our scripts in self-executing, anonymous functions avoids possible conflicts when we have similar variable or function names in multiple scripts.

Going back to our example of two canvases on a single page—if we wrap the code in scripts 1 and 2 in anonymous functions, it won't matter if they both use canvas and context as their variable names. They're no longer implicitly attached to the global window object, instead they're attached to their unique anonymous functions. Now we have no conflicts and we don't need to worry about creating unique variable and function names for each script. We'll be looking at other ways to scope our variables and functions when we get to object oriented programming, but for now, with these beginning scripts, we'll wrap everything in an anonymous function.

Closure

One more thought before we leave the world of scope. When we have functions within functions as we now have in our new scripts wrapped in anonymous functions, any local variable that's declared within our parent function is available to all children functions. That's called closure in JavaScript—we have variables tied to (or enclosed) inside our function and also available to any nested function within our parent function. If you're interested, here's more information about scope and closure.

Download the code for our bitmaps exercise now wrapped in an anonymous function.