Glad You're Ready. Let's Get Started!

Let us know how we can contact you.

Thank you!

We'll respond shortly.

Pseudo-classical inheritance in JavaScript — a rebuttal

A couple weeks ago Davis wrote about using pseudo-classical inheritance to make your JavaScript more object-oriented. I agree with a number of his points about the goal of well-structured code. However, based on my just-over-a-month experience in JavaScript, I personally don’t like to shoehorn the language into object-orientation via pseudo-classical inheritance.

For the sake of examples consider the following class hierarchy: Athlete, Footballer, and Defender.

Implementing this with pseudo-classical inheritance would look something like this, assuming the implementation of Object.extend() from here (I’ve had bad luck with the __super attribute in the past, but let’s assume it works for the moment).

This creates relationships between constructor functions and prototypes that look something like this (if you’ll excuse the ASCII art):

Athlete()    ---->   Athlete.prototype

Footballer() ---->   Footballer.prototype
Defender()   ---->   Defender.prototype

Arrows represent prototype attributes. Creating a new instance defender of the Defender class creates these relationships between the prototoypes and the instance:


defender     ---->   Defender.prototype

This should look familiar; it’s exactly the pattern that Ruby uses for basic inheritance, with the prototype objects representing instances of Ruby’s Class object, and prototype attributes representing Ruby’s Object#class (horizontal) or Class#superclass (vertical) attributes. The lookup rules work the same as Ruby as well: start with methods on the instance (in Ruby these would be methods on the instance’s singleton class); if not found, look for a method on the instance’s class; if not found, look on the Class instance’s superclass; repeat until found or you run out of classes/prototypes.

This looks comfortable and familiar, but unfortunately JavaScript and Ruby have a fundamental difference: Ruby is a class-based language and JavaScript is not. Object instances have instance-specific state — instance variables — which the instance methods use. However, while the instance variable are attributes of the instance, the instance methods live on the class/prototype object. This isn’t a problem in Ruby, because the interpreter knows what’s going on and gives the methods defined on the class access to the instance variables defined on the instance. JavaScript has no such capacity, so all instance variables in these pseudo-classes must be public attributes of the instance. This attempt to create object-oriented behavior by approximating classes actually ends up precluding encapsulation, one of the fundamental aspects of object-orientation.

A different approach to creating our classes could look like this (with a nod to Douglas Crockford). There are a few things I prefer about this approach:

  • Privates are private. Implementation methods such as #shoot and #feignInjury are hidden from the outside world. The same can be done for instance variables.
  • Object definitions have a clearly defined structure: instance variables at the top of the function definition, ending with the declaration and definition of self; public instance methods next, ending with the return of self; private instance methods at the end, where they belong.
  • Object definitions are nicely contained. In the first example the methods are defined at the top level, outside the constructor definition. In this second example everything that defines the class is nicely contained within a single function scope.
  • No dependence on, or pollution of the global namespace with, a method such as #extend.

I’ve heard brought up a couple concerns with this style:

  • Methods are, necessarily, defined on the object rather than the prototype, which can lead to duplication and inefficiency. This is a fair point, but I have yet to see it cause a problem. I’d be interested to see actual numbers that show how much of a performance hit this causes, given a certain number of object creations. In the meantime, I haven’t noticed a performance problem with code written this way, so I’m inclined to prefer encapsulation over theoretical performance issues.
  • Objects defined this way do not properly set their constructor attribute upon creation. Some test methods (notably Jasmine’s any method) depend on this.
  • Closures can be hard to grok.

We’ve recently finished up a reasonably sized project largely using this functional style of object definition, and it worked quite well. I’m sure there’s some reason that it shouldn’t have that I’ve overlooked; I’m curious to hear what that is.

  1. Davis W. Frank says:

    These “functional constructors” are so well organized that it helps explain JavaScript’s closures & function declaration much better than the same topic in “JavaScript: The Good Parts”.

    Color me convinced.

  2. JB says:

    This article has a few things to say on the subject, not all of which apply to your particular implementation.

  3. I actually wrote about this exact method about a year ago. Glad to see other people using this pattern.

    I did some benchmarks as well, comparing this style of inheritence to others out there – it is VERY performant:

  4. Peter Jaros says:

    Ooh, I like this pattern. The only downside that I see is that you don’t have a prototype you can add methods to later, which is useful in some contexts. On the other hand, you use factory functions instead of constructors, which means [your solution to the constructor spying problem]( works here.

Post a Comment

Your Information (Name required. Email address will not be displayed with comment.)

* Copy This Password *

* Type Or Paste Password Here *