Adventures in JavaScript: Global Variables and State (Or, how I learned to stop worrying and love closures)

02 Mar 2014 . category: . Comments

About a year ago, I started a job which requires me to do a lot of work in JavaScript and CSS. My previous background was in C++ and Java, very different languages. As the mood tickles my fancy, I’ll share what I’ve learned (and maybe even make it easy to appreciate if you don’t know JavaScript).

As I made the move to JavaScript, I was not a happy camper. I hated the language. Its lack of datatypes and classes led me to write code that was messy, buggy, and hard to keep running. However, as I wrote more and more of it, I realized that I was having so many problems because I was writing JavaScript as if it was a language like C++, when it isn’t. In this post, we’ll go over the concept of maintaining state, and how doing it in JavaScript is very different from doing in it in C++.

A Specific State of Mind

One of the most common problems we need to solve in programming is state. State is the answer to the question “what is the system doing right now?” Depending on what state a system is in, we want to have different behavior occur.

Ok, that was a little abstract. Let’s consider something a little more specific–a television remote. If you look at the remote for a television, odds are you see a single power button. It’s pretty intuitive what that button does. If you press it when the TV is on, the TV turns off. Press it when the TV is off, and it turns on. Pretty simple, right?

In the TV example, there are two states for the TV: on and off. When you press the power button on the remote, what you are really telling the tv to do is go to the next state. What you see happening when you push that button is totally dependent on what the current state and the next state are.

The power button isn’t the only button on the remote that’s state dependent. Nearly every button on that remote is–volume up/down, channel up/down, input, etc. What each of those buttons do is totally dependent on what the TV is doing right now.

Managing State in an Object-oriented Language

Languages like C++ and Java are totally down to maintain state. As a matter of fact, it’s core to their functionality. In these languages, we use objects to organize everything–functions, variables, the whole lot. Object-oriented programming (OOP) languages are a topic of discussion all in and of themselves, but the important thing to remember here is that OOP languages make it really easy to maintain state.

If you’re willing to look at some C++ code, check out the following, otherwise, click here to skip on past it.

Creating a Television Class

Update: While the following code works, there’s a big potential bug in it. To understand what’s going on, check out this post. This code works for this example, but I’d be remiss if I didn’t mention the bug here.

For those with some C++ familiarity, this is how our Television might look in C++:

television.h

class Television
{
    public:
        Television();
        ~Television();

        void pressPowerButton();

    private:
        bool tvIsOn; //state variable

        void turnOn();
        void turnOff();
};

There’s a lot going on here, so let’s take this apart. What we’re looking at is a class declaration in C++. Here’s what the code is saying:

  1. There is a class called Television.
  2. If you create an object of class Television, you can do exactly one thing with it–press the power button (hence, pressPowerButton()). We know this because pressPowerButton() is in the public section of the declaration.
  3. The object we create has other stuff, too, like a state variable tvIsOn, and two functions: turnOn() and turnOff(). These are things that you can’t mess with when you create the object. That’s why they’re in the private section of the declaration.
  4. The state variable tvIsOn is a boolean variable, which is a really fancy way of saying “this variable can only be true or false”. If tvIsOn is equal to “true”, that means our TV is in the “on” state. Otherwise, it’s in the “off” state.

This is a key feature of an OOP language. An object has two kinds of stuff: things you can mess with (like pressPowerButton()), and things you can’t touch (like turnOff()). If you think about it, this is a lot like a real TV. If you press the power button on your TV, it just works. Unless you know what you’re doing, you really shouldn’t be opening up the TV and messing with its insides–there’s a lot of stuff in there that needs to be left alone in order for the TV to work.

Continuing on, let’s look at the definition.

television.cpp

Television::Television() 
{   
    //on creation, the television is off.
    tvIsOn = false;
}

Television::~Television()
{

}

void Television::pressPowerButton() 
{
    tvIsOn = !tvIsOn;

    if (tvIsOn == true) 
    {
        turnOn();
    } 
    else
    {
        turnOff();
    }
}

void Television::turnOn() 
{
    //do stuff to turn on
}

void Television::turnOff() 
{
    //do stuff to turn off
}

This is what’s called a class definition. It’s the counterpart to the class declaration we just showed. It basically just explains what all the functions we named in the declaration actually do. There’s a few salient things here:

  1. When the Television is first created, it’s off. (To understand why, you’ll need to understand what a constructor is).
  2. When the user presses the power button, we do the following
    • Change the state to its opposite state. (If the state is “true”, it becomes “false”, and vice versa).
    • If the state is now “true”, turn the TV on.
    • If the state is now “false”, turn the TV off.

The astute reader will note that I didn’t put any code in the turnOn() and turnOff() functions. That’s because this Television is a made-up example, and I couldn’t be bothered to make up the code for them. That’s okay though, because for this example, it doesn’t matter what they actually do. It just matters that they exist and that we know when to use them.

Using Our (Classy) Television

To use our first television in C++, we just do this:

//create the TV
Television * tv = new Television();
//press the tv pwr button
tv->pressPowerButton();

...

//later on, press the tv pwr button again
tv->pressPowerButton();

Whoa, nelly, what just happened there? Well, we first create the tv, using this line:

Television * tv = new Television();

Then, we decide to press the power button to turn it on.

tv->pressPowerButton();

The tv is in the “off” state before we press the button. When we press the button, it goes to the “on” state and turns on.

After we’re done using it, we decide to turn it off. So we press the power button again in the same way.

tv->pressPowerButton();

The only difference is that now, the tv was in the “on” state before we pressed the button. Now, it goes to the “off” state and turns off.

Groovy. But what if we have other TV’s? Like say, one in the bedroom. No problem!

//create the TV
Television * tv = new Television();
//create the other TV
Television * tv2 = new Television();

//press the first tv's pwr button
tv->pressPowerButton();

//press the other tv's pwr button
tv2->pressPowerButton();

What we’ve done here is create two separate objects. Each object has its own state variable and its own pressPowerButton() function. Because the state is private, the user can’t mess with them, either. This means I can’t accidentally move my tv to the “off” state if it’s on without using the pressPowerButton() function. This phenomenon where each object has its own state and hides it from the user is called encapsulation, and it’s a powerful concept.

Managing State in JavaScript

Ok, so let’s imagine my television on a webpage. I’d have HTML that shows how to draw the webpage. It might look like this:

<div>The tv is <span id="tv_state">off</span>!</div>
<button id="tv_pwr_button">Power Button</button>

The span called tv_state will tell me what the state of my TV is. The button named tv_pwr_button will be the power button of my TV. Now, to make the “television” do stuff, we need to use JavaScript. I’m going to make my life easy and use jQuery, a JavaScript library that makes doing these things a lot easier. In jQuery, the code to make the TV work might look like this:

var tvIsOn = false;

$("#tv_pwr_button").click(function () {
    tvIsOn = !tvIsOn;
    if (tvIsOn == true) 
    {
        $("#tv_state").html("on");
    }
    else
    {
        $("#tv_state").html("off");
    }
});

It’s a lot like the C++ example. When I click the button, I change the state of the TV, and act accordingly. You can see an example of this here:

Cool. But there’s a slight issue. To demonstrate it, I’ll add another TV.

Huh. That’s odd. If you click one button, then the other, sometimes nothing happens! The buttons just stop working properly. What happened??

The answer lies in our JavaScript. If we look at the code, we have a single state variable, tvIsOn. When we press either button, that state changes. Oops.

Wait, why is that? Why can anything change the state? Because the state is what’s called a global variable.

The Global Variable (and Why it Sometimes Sucks)

In order to explain what a global variable is, I need to talk about a concept called scope. The best explanation I can come up with is that the scope of a variable tells you how much code can mess with the value of that variable.

In our C++ code, everything in the Television class had a nicely defined scope. For example, pressPowerButton() was scoped to the user, and everything else was scoped to the class. This means that only code inside the Television class can mess with the tvIsOn state variable.

Global variables are nuts because they are scoped to everything. Any piece of code that is running in your program can change that variable. This means you can easily change a global variable by accident.

In JavaScript, any variables that appear outside a function are automatically global. This is a problem for C++ developers, who are used to having to go out of their way to make a variable global. If you meet a developer who’s making the transition from OOP to JavaScript, chances are they’ve got a lot of global variables in their code (I know I did in mine).

In JavaScript, we don’t really have nice access to classes like we do in C++ (without using Object.prototype, but that’s a lesson for another day). So how do we fix our code so we have multiple TVs working? After all, I need to play my Xbox.

Using Closures to Provide Encapsulation

One easy thing to take advantage of is local variables within a function. Consider the following example:

function countTo(number) {
    for (var i = 0; i <= number; i++) {
        console.log(i);
    }
}

function countToInDiv(number, div) {
    for (var i = 0; i <= number; i++) {
        div.append(i);
    }
}

Now, what the code is doing isn’t important. What is important to notice, is that both countTo and countToInDiv use variables named i and number. Hold the phone! Isn’t this a problem? Wasn’t this what caused our example with two tv’s to fail?

No. Because in this case, number and i are scoped only to the function they’re in. So, the number and i in countTo are totally separate from the number and i in countToInDiv. If this sounds familiar to you, it should–it’s the same sort of encapsulation we got with the C++ classes earlier, just with JavaScript.

This is an important lesson to learn: JavaScript does provide a lot of the features we’re used to in OOP languages, it just does it in a different way.

So, what if we tried wrapping the code for the TV in a function, and then call that function in our main code? Something like, say, this:

function initializeFirstTv() {
    var tvIsOn = false;

    $("#tv_pwr_button").click(function () {
        tvIsOn = !tvIsOn;
        if (tvIsOn == true) 
        {
            $("#tv_state").html("on");
        }
        else
        {
            $("#tv_state").html("off");
        }
    });
} 

function initializeSecondTv() {
    var tvIsOn = false;

    $("#tv_pwr_button2").click(function () {
        tvIsOn = !tvIsOn;
        if (tvIsOn == true) 
        {
            $("#tv_state2").html("on");
        }
        else
        {
            $("#tv_state2").html("off");
        }
    });
}

initializeFirstTv();
initializeSecondTv();

Well, see for yourself!

Yahoo! The code works exactly as it should, because each TV has its own state.

I should probably note that this is hardly the best way to code, but since the demand for my web-based “televisions” is probably really low, I think it’s okay in this case. ;)

The important thing to note here is using closures helps us keep our code clean and limit the scope of variables we care about.

Closing

JavaScript is a language all of its own, and it needs to be treated that way. While it may not look like it on the outset, it is a fully-featured and modern language. It’s also the wave of the future, as web applications take over more and more of our daily computing experience.

The fact of the matter is that you cannot write code as if you were developing in JavaScript. You wouldn’t go running in high-heels, nor would you show up at a fancy gala in running shoes. JavaScript and OOP languages have their places, but it’s up to the developer to take full advantage of the language they’re in


Me

Vishal Kotcherlakota is a reformed sysadmin, who writes code and will talk incessantly about DevOps to anyone who will listen. All views expressed here are his and not those of his employers.