I\'ve been reading the chapter on functional inheritance in Crockford\'s \'The Good Parts\'. In the mammal example he gives I\'m a bit confused as to why he uses the s
The idea here is that this:
var super_get_name = that.superior('get_name');
makes super_get_name
into a function that — every time it is called — invokes that
's original get_name
method. This allows the new get_name
to call the old (super-class) get_name
.
Now, if the original get_name
method will never have any effect other than to return a single value that never changes, then yeah, this is kind of pointless; you can just save that single-value-that-never-changes and then use it in the new get_name
. But if the original get_name
can actually do things (such as, say, run an AJAX request, or change the styling of an HTML element), or if its return-value can change (say, if there were some corresponding set_name
method), then there would be an important difference between what your code does (save the original return-value and use it) and what Crockford's code does (save the original method and invoke it).
The confusion that arises from this chapter of Crockford's book arises as what Crockford describes is "his" preferred pattern for implementing inheritance in JavaScript, which relies on his extending the Function
object with the Function.prototype.method
(chapter 1.3) which he uses to add methods to the Function object.
The problem addressed in the coolcat
example is the need to access the method of the parent type. In 'classical' OO languages like Java this is natural as classes exist in their own right. In JavaScript inheritance is prototypical, you make an object of type mammal
and then modify the object to create the type cat
or coolcat
.
Depending on your design you may add properties and functions or override an 'inherited' function. The problem arises when you override an 'inherited' function, in JavaScript you basically replace the old function with the new function, thereby loosing the older function.
Crockford now needs to do two things:
get_name
method; andIn this code:
var coolcat = function(spec) {
var that = cat(spec),
super_get_name = that.superior('get_name');
that.get_name = function(n) {
return 'like ' + super_get_name() + ' baby';
};
return that;
};
He does 1. by calling the superior method to get a function that gets the cat's get_name
function;
and he does 2. by saving it to the super_get_name
variable within the coolcat function(/object) allowing access to the cat's get_name
function before it is overridden (more correctly overwritten) by the coolcat's get_name
function.
In my opinion the confusion arises because:
superior
method is named oddly: the 'superior' method is simply a function look up by name method and could be better named, for example as getFunctionByName
(you can try this by replacing the string get_name
, by purr
, the coolcat's get_name will now call purr, just remember to call it as super_get_name(10)
otherwise you'll get an empty string back).I think there is a simpler way to achieve this, one that I think because it is completely localized is easier to understand etc., as in the code below:
var coolcat = function(spec) {
var that = cat(spec);
that.parent_get_name = that.get_name;
that.get_name = function() {
return 'like ' + this.parent_get_name() + ' baby';
};
return that;
};
There are some other oddities for example the argument n
in definition of the coolcat get_name
function, which I can only assume came from copying the purr function, which would suggest a ghost writer!
Finally, I would suggest that before one reads the book one should listen to his talk on 'JavaScript the good parts'. The talk is absolutely brilliant, much better than the book.