A JavaScript 'Class'


Part 5


A JavaScript 'Class'

Last time I looked at how JavaScript does scope a little differently from your average curly-brace-based language. It's worth checking out that previous post if you're not aware of these foibles!

So, JavaScript functions encapsulate their innards, but a function can also access the variables outside of itself. This can be very useful.

Have a look at this code for a simple progress indicator:

var progressIndicator = function (numItems) {
    
    var done = 0;  // The number of items that have been done so far.
    var next = 10; // Output a message every 10% towards completion.
    
    return {

        reportProgress: function() {
            
            done++;
            
            // Get the percentage completed so far.
            var progress = 100 * done / numItems;
            
            // If we 've reached the next 10%, write out a message.
            if (progress >= next) {
            
                console.log(done + " items processed (" + next + "%)");
            
                next += 10;
            }
        },

        isComplete: function() {
            
            return done >= todo;
        }
    };    
};

Let's say you have 127 items to process. Here's how you'd use it:

// Create a progressIndicator.  Tell it that we have 127 items to process.
var myProgressIndicator = progressIndicator(127);

// Call this each an item is processed.
myProgressIndicator.reportProgress();

If you have an OOP background, it can be useful to think of this in the following ways:

That's not really what's happening, but there are some similarities.

How does that work?

This line of code:

var myProgressIndicator = progressIndicator(127);

is calling the progressIndicator function, and putting its return value in myProgressIndicator.

Here's the skeleton of progressIndicator:

var progressIndicator = function (numItems) {
    
    var done = 0;
    var next = 10;
    
    return {

        reportProgress: function() {
            
            ...
        },

        isComplete: function() {
            
            ...
        }
    };    
};

It's declaring two variables done and next, and also returning something. The thing it's returning is an object (see 'JavaScript Objects') with two properties: reportProgress and isComplete. Both of these are functions.

The neat thing is that because the functions reportProgress and isComplete are inside the progressIndicator function, they can access the done, next and numItems variables.

But this is slightly odd when you think about it. Look at this line again:

var myProgressIndicator = progressIndicator(127);

After this line has been executed, even though the progressIndicator function has finished executing, the done, next and numItems variables still exist! Well at least as far as reportProgress and isComplete are concerned.

Which is a bit weird to get your head around at first, but very, very useful.

Nesting functions in JS allows for some very powerful techniques.