Nov 28 2008
JavaScript Closures
Closures are one of the most powerful features of JavaScript. JavaScript isn’t the only language supporting this, but it’s certainly the one I’m going to discuss here. Just for example, the same thing can be done in ActionScript 3 — if you know how that works, you know how it works in JavaScript.
Getting down to the matter at hand, closures are essentially a way of managing variable scope. First lets look at some scope basics, though.
function User(name, age, address) {
//name, age and address are all private to the scope of this function
this.name = name; // public property
this.getAge = function () { return age; }; //public, privileged method
function getAddress() { return address; } //private method
}
User.prototype.getName = function () { return this.name; } //public, non-priveleged method
User.prototype.getAddress = function() { return address; } //fails. address is undefined in this scope.
Just to make it clear, you can have public properties and private variables, public — privileged and non-privileged — methods, and private methods. Privileged methods can access the variables and methods in the constructor (as well as the public ones), whereas non-priveleged methods can only access public members and methods.
Last week, I wrote this:
var myButton = document.getElementById("myButton");
myButton.addEventListener("click",
function (event) {
alert("you clicked!");
},
false);
Now lets combine the two ideas:
function User(element, name, age, address) {
//name, age and address are all private to the scope of this function
this.name = name; // public property
this.getAge = function () { return age; }; //public, privileged method
function getAddress() { return address; } //private method
element.addEventListener("click", function (event) { alert(this.name + "\n" + age + "\n" + getAddress()); }, false);
}
var myButton = document.getElementById("myButton");
var jon = new User(myButton, "Jon", 98, "123 fourth street, yourtown");
Now, if I click on myButton I’ll get an alert with all of the information…. except name. When the event handler executes, the value of this has changed. The easiest way to get around this is by taking advantage of closures and not use this by using var self = this;
function User(element, name, age, address) {
//name, age and address are all private to the scope of this function
this.name = name; // public property
this.getAge = function () { return age; }; //public, privileged method
function getAddress() { return address; } //private method
var self = this;
element.addEventListener("click", function (event) { alert(self.name + "\n" + age + "\n" + getAddress()); }, false);
}
var myButton = document.getElementById("myButton");
var jon = new User(myButton, "Jon", 98, "123 fourth street, yourtown");
Now it works. it’s a very small change and it means that by taking advantage of closures we can maintain a reference to this even when the context changes. This technique is extremely common in event handlers, but it’s also very useful when using setTimeout or setInterval (which use window as context)
Another use of this is to wrap functions that can see internal data. I’ll explain that more in the next post.

October 13th, 2009 at 12:06 am
[...] last wrote about closures and how this affects the visibility of variables and functions. This time I’m going to [...]