- How do I set up inheritance without classes?
- What exactly does
- What on earth is going on with the
Once those are settled, the pieces begin to fall into place, and they can actually get started writing software. Eventually, though, another question arises: what about
Invoking Methods from a Known Prototype
That gets the job done, but it's a bit verbose, and it can be even worse in certain situations. For instance, at Salsify we use composite views from Marionette to simplify rendering individual item views for every model in a collection. But what happens when we're extending another composite view and want to override one of its item view's methods?
In addition to the verbosity of this approach, it has the downside of needing to know the name of the prototype when you're writing the method. This means that changes to your inheritance hierarchy can require updating every call site for a prototype method. It also prohibits reusing function implementations that need to invoke overridden functionality.
Invoking Methods from the Constructor's Prototype
To solve the problem of needing to know the prototype name (and put a cap on the verbosity), it might be tempting to use the object's
This works for the simple case; calling
doSomething on an instance of
Child behaves as expected. Unfortunately, calling it on an instance of
Grandchild doesn't go so smoothly. Since
constructor always refers to the actual function used to instantiate the object, the attempted super call instead becomes recursive, resulting in a stack overflow.
On the Shoulders of Giants
Short, sweet, and simple. The down side to this approach is that it ends up wrapping every function in a helper that maintains the value of the
_super attribute, updating it before and after each invocation. This means the stack is littered with calls through this wrapper during debugging. It can also have performance implications, because every method invocation (regardless of whether it's a super call or not) has to set up a try/finally block, which can be expensive in some JS engines.
The Prototype.js library attacks the problem from the outside in. To invoke a super method in a Prototype class, you declare your method to take a special
$super parameter as its first argument. The framework will pick this up and pass in the overridden implementation when the method is called.
Prototype's solution is consise and easy to read. It does, however, require some magic on the part of the framework to detect whether methods want the
$super parameter or not. It also bears considering that the value of that parameter is not the actual super implementation; it's wrapped in a helper that handles passing that method its
$super parameter if necessary, binding
this for the method invocation, etc. Overall, the Prototype approach ends up being fairly complex to implement.
Of course, the other option if a language doesn't have the feature you want is to switch to another language. Both CoffeeScript and TypeScript have
super built in, and compile it down to a static reference using the object's prototype.
super looks similar to many of the JS solutions we've looked at:
TypeScript's, on the other hand, more closely resembles Java:
super property on the base prototype in our hierarchy that takes on the value of whatever method its caller overrides.
Using it is as simple as:
One key difference between this and the earlier solutions is that
There are two things you may notice about this implementation. First, the use of
Object.defineProperty means it won't work in IE 8 or older. Second, it uses the dubious
Until then we'd love to hear your take on any of the approaches here, or others you've tried out.