Explaining JavaScript scope and closures

Tweet Follow @robertnyman
This article is also available in Turkish, Russian and Traditional Chinese.

I thought I’d try to explain something which many people struggle with: JavaScript scope and closures.

Background

There are a number of articles and blog posts out there trying to explain scope and closures, but overall I’d say that a majority of them aren’t crystal-clear. Besides, a number of them take for granted that everyone has developed in about 15 other languages before, while my experience is that a lot of people writing JavaScript come from a HTML and CSS background, instead of C and Java.

Therefore, my humble goal with this article is for everyone to finally grasp what scope and closures are, how they works, and especially how you can benefit from them. You do need to understand the basic concepts of variables and functions before reading this.

Scope

Scope refers to where variables and functions are accessible, and in what context it is being executed. Basically, a variable or function can be defined in a global or local scope. Variables have so-called function scope, and functions have the same scope as variables.

Global scope

When something is global means that it is accessible from anywhere in your code. Take this for example:

var monkey = "Gorilla";

function greetVisitor () {
	return alert("Hello dear blog reader!");
}

If that code was being run in a web browser, the function scope would be window, thus making it available to everything running in that web browser window.

Local scope

As opposed to the global scope, the local scope is when something is just defined and accessible in a certain part of the code, like a function. For instance;

function talkDirty () {
	var saying = "Oh, you little VB lover, you";
	return alert(saying);
}
alert(saying); // Throws an error

If you take a look at the code above, the variable saying is only available within the talkDirty function. Outside of it it isn’t defined at all. Note of caution: if you were to declare saying without the var keyword preceding it, it would automatically become a global variable.

What this also means is that if you have nested functions, the inner function will have access to the containing functions variables and functions:

function saveName (firstName) {
	function capitalizeName () {
		return firstName.toUpperCase();
	}
	var capitalized = capitalizeName();
	return capitalized; 
}
alert(saveName("Robert")); // Returns "ROBERT"

As you just saw, the inner function capitalizeName didn’t need any parameter sent in, but had complete access to the parameter firstName in the outer saveName function. For clarity, let’s take another example:

function siblings () {
	var siblings = ["John", "Liza", "Peter"];
	function siblingCount () {
		var siblingsLength = siblings.length;
		return siblingsLength;
	}
	function joinSiblingNames () {
		return "I have " + siblingCount() + " siblings:\n\n" + siblings.join("\n");
	}
	return joinSiblingNames(); 
}
alert(siblings()); // Outputs "I have 3 siblings: John Liza Peter"

As you just saw, both inner functions have access to the siblings array in the containing function, and each inner function have access to the other inner functions on the same level (in this case, joinSiblingNames can access siblingCount). However, the variable siblingsLength in the siblingCount is only available within that function, i.e. that scope.

Closures

Now when you hopefully have gotten a better grasp of what scope is, let’s add closures to the mix. Closures are expressions, usually functions, which can work with variables set within a certain context. Or, to try and make it easier, inner functions referring to local variables of its outer function create closures. For instance:

function add (x) {
	return function (y) {
		return x + y;
	};
}
var add5 = add(5);
var no8 = add5(3);
alert(no8); // Returns 8

Whoa, whoa! What just happened? Let’s break it down:

  1. When the add function is called, it returns a function.
  2. That function closes the context and remembers what the parameter x was at exactly that time (i.e. 5 in the code above)
  3. When the result of calling the add function is assigned to the variable add5, it will always know what x was when it was initially created.
  4. The add5 variable above refers to a function which will always add the value 5 to what is being sent in.
  5. That means when add5 is called with a value of 3, it will add 5 together with 3, and return 8.

So, in the world of JavaScript, the add5 function actually looks like this in reality:

function add5 (y) {
	return 5 + y;
}

The infamous loop problem

How many times have you created some sort of loop where you wanted to assign the value of i in some way, e.g. to an element, and found out it just returned the last value i had?

Incorrect reference

Let’s take a look at this faulty code, which creates 5 a elements, adds the value of i as a text to each element and an onclick which is expected to alert the value of i for that link, i.e. the same value as in the a element’s text. It then appends them to your document body:

function addLinks () {
	for (var i=0, link; i<5; i++) {
		link = document.createElement("a");
		link.innerHTML = "Link " + i;
		link.onclick = function () {
			alert(i);
		};
		document.body.appendChild(link);
	}
}
window.onload = addLinks;

Each a element gets the correct text, i.e. “Link 0”, “Link 1” and so on. But whichever link you click, it alerts the number “5”. Oh my God, why? The reason for this is that the variable i get its value increased with 1 for each iteration of the loop, and since the onclick event isn’t being executed, just applied to the a element, it adds up.

Therefore, the loop continues until i is 5, which is the last value of i before the function addLinks exits. Then, whenever the onclick event is actually being triggered, it takes the last value of i.

Working reference

What you want to do instead is create a closure, so that when you apply the value of i to the onclick event of the a element, it gets the exact value of i at just that moment in time. Like this:

function addLinks () {
	for (var i=0, link; i<5; i++) {
		link = document.createElement("a");
		link.innerHTML = "Link " + i;
		link.onclick = function (num) {
			return function () {
				alert(num);
			};
		}(i);
		document.body.appendChild(link);
	}
}
window.onload = addLinks;

With this code, if you click the first a element it will alert “0”, the second “1” etc; just what you probably expected with the first code I showed you to do. The solution here is that the inner function of what’s applied to the onclick event create a closure where it references the parameter num, i.e. what the i variable is at just that time.

That function then closes with that value safely tucked away, and can then return its corresponding number when the onclick event is being called.

Self-invoking functions

Self-invoking functions are functions who execute immediately, and create their own closure. Take a look at this:

(function () {
	var dog = "German Shepherd";
	alert(dog);
})();
alert(dog); // Returns undefined

Ok, so the dog variable was only available within that context. Big deal, man, hidden dogs… But, my friends, this is where it becomes really interesting! It solved our problem with the loop above, and it is also the base for the Yahoo JavaScript Module Pattern.

Yahoo JavaScript Module Pattern

The gist of the pattern is that it uses a self-invoking function to create a closure, hence making it possible to have private and public properties and methods. A simple example:

var person = function () {
	// Private
	var name = "Robert";
	return {
		getName : function () {
			return name;
		},
		setName : function (newName) {
			name = newName;
		}
	};
}();
alert(person.name); // Undefined
alert(person.getName()); // "Robert"
person.setName("Robert Nyman");
alert(person.getName()); // "Robert Nyman"

The beauty of this is that you now can decide on your own what will be publicly visible for your object (and can be overwritten), and what is private and no one can access nor alter. The variable name above is hidden outside the context of the function, but accessible from the returned getName respectively setName functions, since they create closures where they have a reference to the name variable.

Conclusion

My sincere hope is that after reading this, novice or experienced programmer, you have gotten a clear view of how scope and closures actually work in JavaScript. Questions and feedback are very welcome, and if any input is deemed important enough, I will update this article with it.

Happy coding!

Follow @robertnyman RSS
Posted in Developing,JavaScript,Technology | Tweet

221 Comments

  • RSS feed for comments on this post
  • RSS feed for comments on all posts
  • spacer Norbert says:
    October 9, 2008 at 22:40

    Thanks for explaining JS closures! It's very helpful.

    I also decided to give another try for the LISP book I was reading.

    Reply
  • spacer Steven Clark says:
    October 10, 2008 at 3:42

    Mmm I'm going to have to bookmark this fundamental JS stuff – you're training me by proxy I'm sure.

    I've definately got a far better handle on closures now. Thanks. spacer

    Reply
  • spacer Harmen Janssen says:
    October 10, 2008 at 11:46

    Nice read, Robert spacer

    I must say I already was familiar with most concepts you describe, but it's good to have them explained again all in one place for quick reference. Especially the infamous loop problem sometimes still bites me in the ass πŸ˜€

    Reply
  • spacer HÃ¥kan says:
    October 10, 2008 at 11:48

    Great post and good summary of important concepts!

    Thanks!

    Reply
  • spacer Andrea Giammarchi says:
    October 10, 2008 at 13:22

    Hi Robert,

    I would suggest a better addLinks example, since there is no reason to create two functions, one for the closure, and another for the current link onclick event.

    function addLinks () {

    for (var onclick = function(num){return function(){alert(num)}}, i=0, link; i<5; i++) {

    link = document.createElement("a");

    link.innerHTML = "Link " + i;

    link.onclick = onclick(i);

    document.body.appendChild(link);

    }

    };

    onload = addLinks;

    This is more about performances (maniacs) but it is good to understand closure portability, isn't it? spacer

    Reply
  • spacer Robert Nyman says:
    October 10, 2008 at 13:47

    Thanks guys, I'm glad that you liked it!

    Andrea,

    Really nice! spacer

    I choose my approach partly for easier readability and understanding for everyone, but also honestly because I didn't think as far as you did.

    I think it's a perfect example of making closures portable! Thanks!

    Reply
  • spacer Andreas Rydberg says:
    October 10, 2008 at 15:48

    Thanks Robert for a great article! I really need to read up on closures.

    Reply
  • spacer Chris says:
    October 10, 2008 at 17:25

    Thank you for that article. Made some things clear. But I have one question:

    In your addLinks-example, why does link.onclick know that num gets the

    value of i and not something else?

    It's not the first time I see this and don't understand ?-)

    Reply
  • spacer Robert Nyman says:
    October 10, 2008 at 17:58

    Andreas,

    Thanks!

    Chris,

    Thank you!

    The key is that the function is self-invoked, i.e. gets executed right away, and sends in the value <code>i</code> to be the value of <code>num</code>.

    If you examine that part of the code more closely:

    <code>link.onclick = function (num) {

    return function () {

    alert(num);

    };

    }(i);</code>

    you can see that it is not just assigned, but actually gets called immediately by having two parentheses at the end, with <code>i</code> in them.

    And since inner functions will always have access to their outer/containing functions' variables (i.e. a closure is created), it will always know that <code>num</code> is the value of <code>i</code> when it was initially called.

    I hope it's clearer now! spacer

    Reply
  • spacer Chris says:
    October 10, 2008 at 18:11

    It does clarify indeed! What I oversaw was just the parantheses in the end:

    <code>}(i);</code>

    Thanks for explaining and for writing so much good stuff!

    Reply
  • spacer Robert Nyman says:
    October 10, 2008 at 19:30

    Chris,

    Thanks! spacer

    I'm glad that you understood it!

    Reply
  • spacer Jeff L says:
    October 10, 2008 at 21:43

    Thanks for a great article Robert. I also missed the (i) at the end of the onclick function and was wondering how num = i —makes sense now that you pointed it out, though.

    I also appreciate you using an example that most of us have problem run into (where i was not what we expected, but instead was the last known value). I think that makes a big difference in helping folks to understand.

    Reply
  • spacer Robert Nyman says:
    October 10, 2008 at 21:59

    Jeff,

    Thank you!

    Glad that it helped you as well!

    Reply
  • Weekly Links #22 | GrantPalin.com says:
    October 12, 2008 at 21:38

    […] Explaining JavaScript scope and closures JavaScript handles scope somewhat differently from other common programming and scripting languages, and it also has an interesting capability for creating and using closures. Robert Nyman explains the concepts clearly. […]

    Reply
  • gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.