Hang on a tick... there is a problem here that, weirdly nobody has noticed. I will admit that this is hardly ever used, but still:
In a normal JS prototypal inheritance scenario, you would be able to pull stunts like these:
var Animal = (function()
{
function Animal()
{
this.name = this.constructor.name;
};
Animal.prototype.walk = function()
{
return this.name + ' is walking';
};
return Animal;
}()):
var Cat = (function(parent)
{
function Cat(name)
{
this.name = name || this.constructor.name;
};
Cat.prototype = new Animal;
Cat.prototype.constructor = Cat;
Cat.prototype.sleep = function()
{
return this.name + ' is sleeping';
};
return Cat;
}(Animal));
var garfield = new Cat('Garfield');
//code
var newSameClass = new garfield.constructor();
Whereas the extends
method you have written causes infinite constructor recursion: you're declaring a new function, that uses the this
keyword... but because it's being used with the new
keyword, it creates a new instance of itself (temp
).
In the constructor of temp
, all it does is equate its prototype to its own instance... you create an object that is its own prototype and therefore effectively is not part of any chain (it keeps on pointing to itself) and for some bizarre reason, you expect this to keep track of the constructor? I think what you ought to write is this:
Function.prototype.extends = function(parentClass)
{
var temp = this.prototype.constructor;
this.prototype = new ParentClass;
this.prototype.constructor = temp;
};
Which works just fine, and doesn't require some temp constructor/object at any point.
Just try it with this simple example:
function Animal(){};
function Cow(){};
Cow.extends(Animal);
function Bird(){};
function Chicken(){};
Bird.extends(Animal);
Chicken.extends(Bird);
var dinner = new Chicken();
console.log(dinner instanceof Animal);//true -- sorry vegetarians
console.log(dinner instanceof Cow);//false -- no beef tonight
console.log(dinner instanceof Bird);//true -- mmm, poultry
console.log(dinner instanceof Chicken);//true -- roasted, probably
Which is, I take it, what you wanted.
PS: I would strongly advise you not to augment prototypes you don't own. By that I mean Object
, Array
, Function
, Date
and the like... Save for a few cases where the String
prototype poses X-browser issues (String.trim
wasn't implemented in IE8, for example).
You might encounter issues with other toolkits/libs, future updates, issues depending on the implementation (IE, FF and V8 deal with native prototypes differently in some cases)
All in all, it's best to leave them be... I see no reason why you shouldn't simply write a function, and not attach it to the prototype. Or, if needs must, do what ECMA is doing: all these createObject
-like thingies go into one big bin: Object
as in Object.getOwnPropertyNames()
and Object.getPrototypeOf()
. What's so difficult about:
function extend(child, parent)
{
var prto, Object.getPrototypeOf(child),
tmp = prto.constructor;
prto = new parent;
prto.constructor = tmp;
return child;//<-- this might be handy
}
//usage:
var garfield = new (extends(Cat, Animal))('garfield');