JavaScript classes

From Trephine

Jump to: navigation, search
« JavaScript call and apply quick reference Understanding JavaScript's new keyword »

[subscribe] Recent blog entries

Live Demos

JavaScript classes

JavaScript is a powerful and elegant language, with many great features. One feature which it doesn't have, however, is classes - at least, not in the statically typed, classically inherited sense. Instead, JavaScript has a robust object prototyping system, the basics of which are explained in this article.

To get started, consider this simple JavaScript function:

function Person( name ) {
  this.name = name;
}

In addition to their usual role, functions also act as the basis of prototypes in JavaScript. We can create new Person instances with code such as this:

var bob = new Person( "Bob" );
var alice = new Person( "Alice" );

At this point, bob is an object created from the Person prototype. If we were to interrogate bob.name we find that it contains the string "Bob". The bob object has certain methods available, such as toString(), which it transitively inherits from Object (more on this in a bit).

Unlike classes in a statically typed, classically inherited language (such as Java or C#), JavaScript prototypes can be modified on the fly, and each instance will pick up the changes automatically.

Consider if we wanted all Person's to have a greet() method. We might achieve that with code like the following:

Person.prototype.greet = function( otherPerson ) {
  alert( "Hello " + otherPerson.name + ", I'm " + this.name );
};

Now we can have bob and alice greet each other like so:

bob.greet( alice ); // alerts "Hello Alice, I'm Bob"
alice.greet( bob ); // alerts "Hello Bob, I'm Alice"

When we call bob.greet(), the JavaScript engine looks for a greet function in the following places:

  1. A property (member) of bob itself (like bob.name),
  2. A property of Person.prototype,
  3. A property of Object.prototype.

The engine finds greet as a property of Person.prototype and looks no further. On the other hand, calling bob.toString() forces the engine to look all the way up into Object.prototype to find a match.

We could override this behavior by defining a toString property on the Person prototype:

Person.prototype.toString = function() {
  return this.name.toString();
};

The three locations listed earlier are the only places where the JavaScript runtime will look for a property. That is to say, JavaScript does not natively support "extending" one prototype to another in the same fashion as one would create subclasses of a parent class in a class-based language.

Of course, the JavaScript language is powerful enough to allow a framework or library to overlay an inheritance model in one form or another. This could be done, for example, by replicating the members of one prototype onto another. In a more sophisticated setup, one could capture property lookup events and return the first match along a specifically maintained inheritance chain. Both of these methodologies are outside the scope of this introductory article however.

That about wraps up this JavaScript "classes" primer. I hope to build on the concepts introduced here in coming articles; exploring, for example, the inner workings of the "new" keyword.

As always, I look forward to your comments and suggestions. Enjoy!

--Jim R. Wilson (jimbojw) 03:29, 7 April 2009 (UTC)
Personal tools