7. Variable Scope


In This Chapter

Understand global scope

Familiarize yourself with the various techniques available for using local scope

Learn about some quirks that might cause your code to behave unpredictably


Let’s revisit something relating to variables that we saw in Chapter 2, “Values and Variables.” Each variable you declare has a certain level of visibility that determines when you can actually use it. In human-understandable terms, what this means is simple: just because you declare a variable doesn’t mean that it can be accessed from anywhere in your code. There are some basic things you need to understand, and this whole area of understanding falls under a topic known as variable scope.

In this chapter, I explain variable scope by looking at common cases that you’ve (mostly) already seen. This is a pretty deep topic, but we are just going to scratch the surface here. You’ll see variable scope creep up in many subsequent chapters where we will expand on what you will learn here.

Onwards!

Global Scope

We are going to start our exploration of scope at the very top with what is known as global scope. In real life, when we say that something can be heard globally, it means that you can be anywhere in the world and still be able to hear that...something (see Figure 7.1).

Image

FIGURE 7.1 Something that is global can be accessed and heard from anywhere.

In JavaScript, much the same applies. If we say, for example, that a variable is available globally, it means that any code on your page has access to read and modify this variable. The way you make something apply globally is by declaring it in your code completely outside of a function.

To illustrate this, let’s take a look at the following example:

<script>
var counter = 0;
</script>

Here, I am simply declaring a variable called counter and initializing it to 0. By virtue of this variable being declared directly inside the script tag without being placed inside a function, the counter variable is considered to be global. What this distinction means is that your counter variable can be accessed by any code that lives in your document.

The code that follows highlights this:

var counter = 0;

function returnCount() {
    return counter;
}

In this example, the counter variable is declared outside of the returnCount function. Despite that, the returnCount function has full access to the counter variable.

At this point, you are probably wondering why I am pointing out what seems very obvious. After all, you’ve been using global variables all this time without really noticing it. All I am doing here is formally introducing you to a guest that has been hanging around your party for a while, a guest that has the potential for causing a lot of mayhem if you aren’t careful.


Image Note

I’ve been pretty vague in defining what global exactly means. This is deliberate, as formally describing it will involve a whole lot more backstory to make sense of everything. If you are familiar enough with JavaScript (or are feeling adventurous), read on. If not, feel free to skip this note and move on to the next section. We’ll revisit this later.


Anyway, something is considered global in JavaScript when it is a direct child of your browser’s window object. That is a more precise way of saying “declared outside of a function.” You can verify this pretty easily by checking if counter and window.counter point to exactly the same thing:

alert(window.counter == counter);

The answer is going to be true. The reason is that you are referring to the exact same thing.

Realizing that global variables live under your window object should help you understand why you can access a global variable from anywhere in your document. All your code (for everything you’ll see in this book) lives under the umbrella of your window object.

Local Scope

Now, things get a little interesting when we look at things that aren’t globally declared. This is where understanding scope really helps you out. As you saw earlier, a variable declared globally is accessible inside a function:

var counter = 0;

function returnCount() {
    return counter;
}

The opposite doesn’t hold true. A variable declared inside a function will not work when accessed outside of the function:

function setState() {
    var state = "on";
}
setState();

alert(state) // nooooooooooo

In this example, the state variable is declared inside the setState function, and accessing the state variable outside of that function doesn’t work. The reason is that the scope for your state variable is local to the setState function itself. A more generic way of describing this is by saying that your state variable is just local.


Image Note

Let’s clarify something that I briefly mentioned when looking at variables. Continuing our earlier example, if we declare the state variable without using the var keyword, the scoping behavior is drastically different:

function setState() {
    state = "on";
}
setState();
alert(state); // on


In this case, even though your state variable makes its appearance inside the setState function first, not including the var keyword makes this variable live globally.

Keep in mind that a variable that is used without being declared using the var keyword will always live globally.

Miscellaneous Scoping Shenanigans

Since we are talking about JavaScript here, things would be too easy if we just left everything with variable scope as it stands now. In the following sections, I am going to highlight some quirks that you need to be familiar with.

Declarations Using var Do Not Support Block Scoping

Before I attempt to explain this, take a look at the following code:

function checkWeight(weight) {
    if (weight > 5000) {
        var text = "No free shipping for you!";
        alert(text);

    }
    alert(text); // how did it know??!

}

checkWeight(6000);

I’ve highlighted the relevant lines that you should focus on. Inside the if statement, we declare a variable called text. When this code is run, the alert function directly below it displays No free shipping for you! That makes sense. What might make less sense is that the second alert that is outside of the if statement also displays No free shipping for you!.

Here is what is going on. Your text variable is declared inside what is known as a block. A block is anything that appears within the open and close brackets - { and }. In many programming languages, variables declared inside a block are part of that block’s own scope. That means those variables are local and can’t be accessed outside of the block.

JavaScript is not like those many “other” programming languages. JavaScript doesn’t support block scoping. For the code you just saw, despite the text variable being declared inside a block, from JavaScript’s point of view, it might as well have been declared at the top of your checkWeight function itself as follows:

function checkWeight(weight) {
    var text;


    if (weight > 5000) {
        text = "No free shipping for you!";
        alert(text);
    }
    alert(text);
}

checkWeight(6000);

The behavior of this checkWeight function is identical compared to what you saw a few moments earlier.

To repeat, there are only two scopes you need to keep track of. The first is the global scope where what you are declaring is completely outside the grip of a function. The second is the local scope where what you are declaring is enclosed by whatever function you are inside.


Image Note

The latest version of JavaScript (part of the ECMAScript 6/ES2015 improvements) introduces support for the let keyword that allows you to declare variables that are block scoped:

var x = 100;

function blockScoping() {
    if (true) {
        let x = 350;
        alert(x) // 350
    }
    alert(x); // 100;
}
blockScoping();


How JavaScript Processes Variables

If you thought the earlier block scoping logic was weird, wait till you see this one. Take a look at the following code:

var foo = "Hello!";


function doSomethingClever() {
    alert(foo);

    var foo = "Good Bye!";

    alert(foo);
}

doSomethingClever();

Examine the code in detail. What do you think is shown in the two highlighted alert function calls? Given what is going on, you may answer Hello! and Good Bye! However, if you test this code out, what you will actually see is undefined and Good Bye! Let’s look at what is going on here.

At the very top, we have our foo variable that is instantiated to Hello!. Inside the doSomethingClever function, the first thing we have is an alert that should show the value stored by the foo variable. A few lines below that, we re-declare the foo variable with a new value of Good Bye!:

var foo = "Hello!";

function doSomethingClever() {
    alert(foo);

    var foo = "Good Bye!";

    alert(foo);
}

doSomethingClever();

Because our first alert comes before the foo variable re-declaration, the logical assumption is that foo’s original value of Hello! will be what gets shown. As you saw earlier, that isn’t the case. The value of foo when it hits the first alert is actually undefined. The reason for this has to do with how JavaScript deals with variables.

When JavaScript encounters a function, one of the first things it does is scan the full body of the code for any declared variables. When it encounters them, it initializes them by default with a value of undefined. Because the doSomethingClever function is declaring a variable called foo, before the first alert even hits, an entry for foo is created with a value of undefined. Eventually, when our code hits var foo = "Good Bye!", the value of foo is properly initialized. That doesn’t help our first alert function, but it does help the second one that follows the re-declaration of foo. All of this has a name. It is known as hoisting or variable hoisting!

Keep this little quirk in mind if you ever run into a situation where you are re-declaring variables into a local scope like this simple example highlighted. Tracking down why your variables aren’t behaving as expected isn’t fun, and hopefully this tidbit of knowledge will come in handy.

Closures

No conversation about variable scope can be wrapped up without discussing closures. That is, until right now. I am not going to explain closures here, for it is important and involved enough to require its own chapter. That chapter...is coming up next!

Given that this section is titled “Closures,” I’ll just do my usual closing song and dance here itself:

Well, that concludes this topic of variable scopes. This topic seems very simple on the surface, but as you can see, there are some unique characteristics that take some time and practice to fully understand.

I am not good at conclusions...or singing and dancing. I get that, and they are all on my bucket list. I swear!


Image Tip

Just a quick reminder for those of you reading these words in the print or e-book edition of this book: If you go to www.quepublishing.com and register this book, you can receive free access to an online Web Edition that not only contains the complete text of this book but also features a short, fun interactive quiz to test your understanding of the chapter you just read.

If you’re reading these words in the Web Edition already and want to try your hand at the quiz, then you’re in luck – all you need to do is scroll down!


..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.45.5