Javascript does not support classical OOP. Instead it supports prototypal inheritance. It seems that everybody still wants to use the classical OOP pattern though and I don't really blame them. I use it all the time in my own projects and I see it used in many of the libraries and frameworks out there. Some people think that classical OOP has no place in Javascript, but I and many others respectfully disagree.
Despite the numerous tutorials on the web, many people still ask what is the proper way to do classical OOP. I'm not sure if the issue is the quality of the tutorials or the myriad of ways to simulate classes. In any case, I feel that there is room for one more quick tutorial. I do not claim this way to be the "proper" way, but I do feel that it is a "good" way. Many people and libraries/frameworks use this pattern or something very close to it
Classes and the Constructor
Defining a class and it's constructor function is easy. It looks like this:
// create a class called Animal
var Animal = function(name, age) {
// assign the passed-in arguments to instance members
this.name = name;
this.age = age;
};
Using this class is also easy:
// create an instance and assign it to the pet variable
var pet = new Animal("Spot", 2);
Instance Methods
To add an instance method, you want to use the prototype property. It looks like this:
// create an instance method called "sayHello"
Animal.prototype.sayHello = function() {
// access instance members using the "this" keyword
return this.name + " doesn't speak.";
};
To use an instance method, you can simply call it on the instance:
// make the animal say hello
pet.sayHello(); // returns "Spot doesn't speak."
Static Methods
Static methods are applied to directly to the class like so:
// create a static method called "getName"
Animal.getName = function(animal) {
// return the name of the passed-in animal
return animal.name;
};
When using a static method, you use the class:
// call the static method
Animal.getName(pet); // returns "Spot"
Subclassing
This is usually the sticky point and where many implementations differ slightly (or not-so-slightly). Like I said, I think the way I present is a good way though. It requires one little helper function.
var extend = function(subClass, parentClass) {
var tempFn = function() {};
tempFn.prototype = parentClass.prototype;
subClass.prototype = new tempFn();
subClass.prototype.constructor = subClass;
subClass.superclass = parentClass.prototype;
};
The what, why and how are beyond the scope of this article, but I certainly encourage you to do deeper digging if you are so inclined. Using the function is rather easy though.
// create a new class called "Dog"
var Dog = function(name, age) {
// call the constructor of the superclass
Dog.superclass.constructor.call(this, name, age);
};
// explicitly make Dog subclass Animal
extend(Dog, Animal);
Instance Methods
To add new instance methods, just add them to the prototype of the subclass:
// create an instance method called "bark"
Dog.prototype.bark = function() {
return "Woof!";
};
To override instance methods, and to call superclass methods, do this:
// override the instance method called "sayHello"
Dog.prototype.sayHello = function() {
if (this.age < 1) {
// call the super "sayHello" method
return Dog.superclass.sayHello.call(this);
}
else {
return this.bark();
}
}
Using instance methods on the subclass works exactly like before:
var petDog = new Dog("Spot", 2);
// make the animal say hello
petDog.sayHello(); // returns "Woof!"
That's really about it. It's simple and doesn't include many things like interfaces or
private members, but it works. And that's how you do easy breezy Javascript OOP.