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;
};
var cat = coolcat({ ... });
Can just as well be done with prototypes
var CoolCat = {
constructor: function () {
Cat.constructor.apply(this, arguments);
return this;
},
getName: function () {
return 'like ' + Cat.getName() + ' baby';
}
};
var cat = Object.create(CoolCat).constructor({ ... });
Of course the main difference here is that your not creating two new functions every time you invoke coolcat
. coolcat
creates a new function for get_name
and a new function for super_get_name
and basically wastes memory left and right.
One may argue coolcat
has privacy but it does not because anyone can call cat({}).superior('get_name');
and get your "private" method.
Of course if one wants privacy and prototypes that's perfectly possible, using the klass
macro as shown in the article
var Cat = klass(function (privates) {
return {
constructor: function (name) {
privates(this).name = name;
},
getName: function () {
return privates(this).name;
}
};
});
var CoolCat = klass(Cat, function (privates, $super) {
return {
constructor: function () {
$super.constructor.apply(this, arguments);
},
getName: function () {
return 'like ' + $super.getName.call(this) + ' baby';
}
};
});
var cat = new CoolCat("someName");
console.log(cat.getName());
Live Example
Here we achieve both privacy and super class inheritance in an "elegant" manner.
In this elegant means not having the closure overhead of multiple functions per object (we still add a single closure per object for the privates
function) and also allowing normal prototypical OO to just work.
Look up Object.create for an alternative to function constructors which I actually find very useful since they give you encapsulated instance vars via closure.
I'm not sure how long it's been available but I've been using <object>.constructor.prototype for some time now.
But really, JS was written in 10 days. It's been evolving from that rush job ever since. I'm not even sure they had prototype on function constructors when it was first released. Netscape's top brass wanted it to look like Java. Brendan Eich wanted it to work like Scheme (and decided he was making it look like C rather than Java, by which I assume he's stating he wasn't a huge fan even back then).
Also, Good Parts is a decent read but it's not the ultimate authority and Crockford has some really weird hang-ups about the language. Function constructors in particular which he's claimed are bad because you might forget to use new keyword and screw up. Well, you might forget to wear your pants in the morning too but you tend to notice pretty quick.
Took me a bit to find this but if you really want to know how it came about, it's best to go to the horse's mouth:
https://brendaneich.com/2008/04/popularity/
Best Answer
This works and is the right way depending on whether or not the browser supports
Object.create
:The
Object.create
method sets up prototypal inheritance without executing the constructor functionPerson
when "inheriting."