Creating JavaScript Classes, Part 3: Method Inheritance (with screencast)
by Jason S. Kerchner on Feb 24, 2009 (filed in Development)
View Screencast | Download code
For a complete explanation of the following code, watch the screencast. In the previous post, I looked at how JavaScript can access properties of ancestor classes in descendant classes. In this post, I am going to look at how to do the same with JavaScript functions. To keep things consistent, I’m going to build on the original class hierarchy that I used last week. For reference, here is that class hierarchy again:

Figure 1 - Class Diagram
If you recall from an earlier post, methods are added to constructor functions using the prototype object of that function. What I need to be able to do is have one class reference the prototype object of its parent class. This needs to work even if we have multiple levels of inheritance (as we do with our example classes).
Please note that I am not going to go into all the details of why these specific implementation techniques were chosen. View the screencast if you want to see all the details (you’ll also learn a lot more about method inheritance in the screencast).
In order to get the Employee class to inherit the methods of the Person class, I need to use a secret, special syntax that JavaScript understands. I call it secret because it doesn’t do what you think it does, and I call it special because it does something more useful than what you think it does.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * @class Employee * @inherits Person */ function Employee(first, last, company) { this.company = company; }; // The secret, special syntax of method inheritance Employee.prototype = new Person(); Employee.prototype.getCompanyWebsite = function() { return 'http://www.' + this.company + '.com'; }; |
The secret, special syntax is in line 10 (in case you missed the comment right above it). Here’s the secret: it doesn’t really create a new instance of a Person object and assign it to the Employee.prototype property. Here’s the special: it does create a new instance of a Person object that has a reference to the methods of the Person.prototype object, and it will assign that same reference to Employee.prototype. This means that an instance of Employee (when we create one) will have access to all the methods of the Person class, because Employee.prototype references Person.prototype.
Now you might think that JavaScript is also smart enough not to execute the full constructor. After all, I’m not creating an object that I want to use. I’m just creating it so I can get a reference to the prototype. Well, JavaScript isn’t that smart. In this simple example, this is not a big deal. However, in a real application, where classes could be much larger, and constructors might do real work like alter the web page, this could be a bad thing. So I want to execute the constructor just enough to create a reference to the prototype, without actually executing any of the code within the constructor.
This is actually pretty simple to do. I can create a unique object, I’ll call it inheriting, and pass that object to the constructor function when I am setting up inheritance. Because this is a unique object, I can check for it in the constructor and, if it was passed in, bail before it actually executes any additional code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | // Object used to signal that inheritance is being set // up, and that constructor code should not execute. var inheriting = { }; /** * @class Person */ function Person(first, last) { // If first argument is the inheriting object, bail // out early, since we don't want to execute any code. if (arguments[0] === inheriting) return; // Constructor code when not setting up inheritance. this.firstName = first; this.lastName = last; }; Person.prototype.getFullName = function() { return this.firstName + ' ' + this.lastName; }; |
Line 3 is the unique inheriting object, and line 11 in the constructor checks for it. If it was passed in, which it only ever will be when inheritance is being set up, then the constructor is exited immediately without executing any additional code. If it wasn’t passed in, then execution proceeds as normal. I use arguments[0] as a convention, since some constructors will not expect any arguments (and therefore there will be no named arguments to reference).
The last thing I need to do is update the Employee class to utilize the inheriting object to signal the constructor function that inheritance is being set up.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | /** * @class Employee * @inherits Person */ function Employee(first, last, company) { this.company = company; }; // The secret, special syntax of method inheritance Employee.prototype = new Person(inheriting); Employee.prototype.getCompanyWebsite = function() { return 'http://www.' + this.company + '.com'; }; |
On line 10 the inheriting object is now being passed to the Person constructor function during inheritance. Following this same logic, I can add the secret, special syntax to the Manager and Worker classes to have them inherit the methods of the Employee class. And because the Employee class already has a reference to the methods of the Person class, Manager and Worker will automatically inherit that reference as well. This gives inheritance through multiple class levels, and all is good.
In the next post, I’ll be looking at how to implement method overrides. That is, I want to be able to replace one method of a class with another method of the same name in the descendant class. But, I still want to be able to access the original method in the ancestor class when necessary. Although this is common in most object-oriented languages, its not a straight-forward thing to implement in JavaScript.
May 15th, 2009 on 12:57 pm
[...] Consider the canonical example: [...]