Nov 28 2008

JavaScript Closures

Category: JavaScriptJonathan Fingland @ 1:26 am

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.

One Response to “JavaScript Closures”

  1. Ashita.org » Functions in Closures says:

    [...] last wrote about closures and how this affects the visibility of variables and functions. This time I’m going to [...]

Leave a Reply