Object-Oriented JavaScript, Part 1

JavaScript takes a different approach to OOP than other languages. It replaces the class-based system of languages like C++ and Java with a prototype-based approach. See here for an excellent discussion of the differences between these two approaches. For now, the most important thing to note is that in JavaScript, there are no classes, so if you come from a C++, C#, or Java background, you will need to disregard much of what you already know in order to effectively work with objects in JavaScript.

To create an object in JavaScript, all you need to do is create a function that returns “this”, call it, and store the returned value in a variable:

function Mammal() {
	/* add attributes and functions to "this" */
	return this;
}

var dog = new Mammal();

Because everything, even functions, are objects in JavaScript, we can store variables and functions on the above function’s “this”:

function Mammal() {
	this.sound = "Grrrr."
	this.makeSound = function() {
		console.log(this.sound);
	}
}

Now, when we create a Mammal object and call its “makeSound()” method, the object’s “sound” member variable will be printed to the console.

This approach is nice, but it has one major problem: every time we create a Mammal object using this function, that object will have its own allocated memory to store the function instructions for the “makeSound()” method. In some cases when we create huge arrays of our custom objects, this is incredibly inefficient. It would be much better if we had a way of defining objects that allowed us to keep only one copy of the methods attached to those objects, no matter how many individual instances we have.

Enter the prototype. In JavaScript, each object has an associated prototype. You can look at the prototype as the part of the object that other kinds of objects can copy and modify in order to take advantage of inheritance. Not only does this have huge benefits with reference to memory savings, it also gives us the ability to define object hierarchies that can be modified during execution (not often a good idea, but it CAN come in handy every once in a while).

So, how does one access and edit the prototype of an object? There are two general ways of doing this. The first is to treat prototype as a hash on the Mammal object as follows:

function Mammal() {
	//construct stuff that you don't want other objects to inherit
}

Mammal.prototype = {
	sound: "Grrrr.",
	makeSound: function() {
		console.log(this.sound);
	}
}

This is great, but sometimes you don’t want to replace the prototype that is already there. In other words, sometimes you want one object (a cat, for example) to inherit the behavior and default data of the parent object (Mammal). In these cases, we would declare individual functions and member variables as attributes of the object’s prototype:

Mammal.prototype.eat = function() {
	console.log("Nom nom nom!");
}

As stated before, we can store both data and functions in the prototype of an object. Everything we store in the prototype can be inherited by other objects by declaring the prototypes of those objects to be equal to the parent object type. Using this approach, we can create a Dog object as follows:

function Dog() {
	return this;
}
Dog.prototype = new Mammal();
//And later...
var fido = new Dog();
fido.makeSound();

Now the Dog object type has the capacity to do anything that the Mammal object can do, plus whatever else we add to its prototype. Once we define methods for things that all dogs can do (Like the “goToHeaven()” method), we can get more specific with individual kinds of dogs, like the “rollOver()” method for trained dogs or the “superDrool()” method for those dogs that just can’t stop… Anyway, after defining all of this individual stuff on sub-objects, we can still access the methods of the Mammal object and they still behave the same way, unless one of the sub-objects has overridden one of Mammal’s functions.

The best way to nail this down is to get an interactive console (I suggest installing Node) and play around with objects to figure out what does and does not work. Once you get the basic idea down, you’ll find that the way that JavaScript handles objects is incredibly intuitive and makes perfect sense for scripting languages.

Adam Nickle

About Adam Nickle

I'm a total nerd, intellectual explorer, number theory enthusiast, and computer science nut. I'll write about anything from math and programming to religion and science fiction, all of which play central roles in my life.
This entry was posted in Web Development and tagged , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *