Stack overflow in javascript inheritance - javascript

I have the below prog
Object.prototype.inherit = function(baseConstructor) {
this.prototype = (baseConstructor.prototype);
this.prototype.constructor = this;
};
Object.prototype.method = function(name, func) {
this.prototype[name] = func;
};
function StrangeArray(){}
StrangeArray.inherit(Array);
StrangeArray.method("push", function(value) {
Array.prototype.push.call(this, value);
});
var strange = new StrangeArray();
strange.push(4);
alert(strange);
and when irun it i get stack overflow? why?

You're setting StrangeArray.prototype to Array.prototype. Later, you're adding a push method to StrangeArray.prototype (which is now the same thing as Array.prototype). So you're effectively setting Array.prototype.push. Your push method calls Array.prototype.push - i.e. itself. So it ends up just calling itself repeatedly and you get a stack overflow.

Jon is right. Here's a way to fix it. Instead of setting StrangeArray.prototype to Array.prototype, this will let you set StrangeArray.prototype to a new instance of Array, so it inherits Array.prototype's properties (without calling Array's constructor).
Object.prototype.inherit = function(baseConstructor) {
var tmp = Function();
tmp.prototype = baseConstructor.prototype;
this.prototype = new tmp();
this.prototype.constructor = this;
};
Edit:
this.prototype = new baseConstructor();
works in this example, but is not good in more complex programs. If the base constructor does some initialization, such as creating DOM elements, incrementing a count, or connecting to a server, then all that initialization would take place when the script loads, instead of when the child object is instantiated.
Another way to deal with this is to differentiate in the constructor whether it is being called for inheritance (to assign to a prototype) or just to instantiate, and then not do the initialization stuff if it is being called for inheritance. But I prefer to just not call the constructor when inheriting, and so use an empty function for the constructor when inheriting.
I'm not very good at explaining this stuff. I recommend Crockford's site and also these two articles on Javascript inheritance.

You actually only have to set the actual object's prototype, to a new instance of the baseConstructor:
Object.prototype.inherit = function(baseConstructor) {
this.prototype = new baseConstructor();
};
I also suggest you to give a look to this Prototypal Inheritance technique that I found very clean.

Related

Why is it so important to redefine Function.prototype before instantiation of any objects?

From this example
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var g = new Graph();
If I first redefine prototype, and then create an object using constructor functio (like in the example), everything works (i.e. I can call g.addVertex("a");). But if i swap Graph.prototype = {...} and var g = new Graph(); - I can't call g.addVertex() function (method) anymore. Why?
Normally it's fine to change the protoype of existing objects' constructor. However, you're assigning a whole new object to Graph.prototype, so the reference that the instance had in its __proto__ property is no longer
the same as Graph.prototype.
If instead you add the method to the existing prototype, like this:
Graph.prototype.addVertex = function(v){
this.vertices.push(v)
}
Then it'll work in any order.
Because you are redefining the entire prototype after the instance is created, meaning that all new instances will get the new prototype, but already created instances won't. An instance won't know that the prototype of the constructor function where it came from has completely changed.

javascript inheritance: Instance vs prototype

When using inheritance, what is the difference and which approach would be better between ChildObject.prototype = new ParentObject(); or ChildObject.prototype = ParentObject.prototype;.
I have seen ChildObject.prototype = new ParentObject(); in a Douglas Crockford example.
Neither of those.
Instead:
ChildObject.prototype = Object.create(ParentObject.prototype);
ChildObject.prototype.constructor = ChildObject;
combined with this line at the beginning of ChildObject:
ParentObject.call(this/*, appropriate args if any*/);
or if passing along all args:
ParentObject.apply(this, arguments); // `arguments` literally -- it's provided by the JavaScript engine
The problem with ChildObject.prototype = new ParentObject(); is that it won't work if ParentObject expects arguments, as many (most?) constructors do. So the pattern doesn't work in a common (possibly majority) case.
The problem with ChildObject.prototype = ParentObject.prototype; is that then you have both of them pointing at the same object. So setting a property on ChildObject.prototype makes it show up on instances of ParentObject (since you've just set it on ParentObject.prototype as well).
The Object.create version defers calling ParentObject until you have an object to initialize, but gives you an object on which you can put the things specific to ChildObject instances. (The constructor backlink is to make the replacement object look like the default one ChildObject originally had; that didn't used to matter much, but it's actually used now by ES6 in some cases, and some libs used it before even if ES5 and earlier didn't [they just put it there].)
Finally: The single-argument version of Object.create can be shimmed for obsolete browsers from before 2009 when it was added in ES5, or you can use a factory function instead if you don't like partially-shimming things:
function objectCreate(proto) {
function ctor() { }
ctor.prototype = proto;
return new ctor;
}
We usually use prototypes to supply methods - to avoid duplicating the same function for each instance of class. In other words, for something like...
ChildObject.prototype.foo = function() {
console.log('foo');
};
Now you probably see the problem with the second approach: modifying ChildObject.prototype will modify ParentObject.prototype as well (it's the same object after ChildObject.prototype = ParentObject.prototype line). That means all ParentObject in this example will have foo method available to them. Actually, it's not even correct to say that ParentObject is parent of ChildObject - both have the same prototype chain.
Yet there's another nasty side effect. Consider this:
function ParentObj() {}
function ChildObj() {}
ChildObj.prototype = ParentObj.prototype;
var i = new ParentObj();
console.log(i); // ParentObj {}
var j = new ChildObj();
console.log(j); // ParentObj {}
See, both prototypes, as they are the same object, have the same constructor property. So to distinguish between those, we'll have to introduce some flags in the constructor functions, essentially overriding the already existing mechanism.
If you do
ChildObject.prototype = ParentObject.prototype;
then your parent and child have the same prototype. With the latter,
ChildObject.prototype = new ParentObject();
the child's prototype is the parent itself.

Setting C.prototype.constructor = C leads to StackOverflow

I have been learning about js inheritance and as a study project, I'm creating my own implementation of inheritance a base class extend method to create new classes. I use C.prototype.constructor = C as Stoyan Sefanov says to, however that leads to a stack overflow when I try to call the base class constructor.
The problem is that the second level of inheritance keeps on calling it's own constructor! If I remove that line, my inheritance seems to work fine.
jsfiddle sample.
Here is my implementation of the base class code.
(function(TestFramework, undefined) {
TestFramework.Class = function() {};
TestFramework.Class.extend = function(ctor) {
var base = this;
var derived = ctor;
//Duplicate static property access to derived
for (var property in base) {
if (base.hasOwnProperty(property)) derived[property] = base[property];
}
//Create lightweight intermediate constructor to avoid calling the base constructor
function lightweightCtor() { this.constructor = derived; };
//Setup prototype chain
lightweightCtor.prototype = base.prototype;
derived.prototype = new lightweightCtor();
derived.prototype._MyBase = lightweightCtor.prototype;
derived.prototype._MyBaseCtor = function() {
base.prototype.constructor.apply(this, arguments);
};
//Return derived class
return derived;
};
TestFramework.Class.prototype.ClassName = "TestFramework.Class";
})(window.TestFramework);
I spent a bit of time looking at the fiddle. I'm not entirely certain what you intend the code to do, but on line 23, you have:
base.prototype.constructor.apply(this, arguments);
which calls line 35..
this._MyBaseCtor();
.. which calls line 23, which calls line 35, etc.
Two suggestions (forgive me if you are well aware). Use the debugger statement when debugging - indispensable. And consider a library like Underscore.js if you want to use proven inheritance in a production environment.
Now that I understand the problem, the solution was pretty easy. I just had to store a reference to the original ctor before overwriting it and call that from within _MyBaseCtor. Here's the updated fiddle.
First, take out the constructor override inside of the lightweightCtor definition.
//Create lightweight intermediate constructor to avoid calling the base constructor
function lightweightCtor() {};
Then, add a new section to configure the constructor. Notice the check if base.__BaseCtor is configured and using the default base.prototype.constructor if it's not.
//Setup constructor references
derived.__BaseCtor = base.__BaseCtor || base.prototype.constructor;
derived.prototype.constructor = derived;
derived.prototype._MyBaseCtor = function() {
derived.__BaseCtor.apply(this, arguments);
};

Confusion over Classical and Prototypal Inheritance Javascript

// Prototye Inheritance
var AnswerPrototype = {
constructor: function(value){
this._val = value;
},
get: function(){
return this._val;
}
}
var lifeAnswer = Object.create(AnswerPrototype);
lifeAnswer.constructor(100);
alert(lifeAnswer.get());
var desertAnswer = Object.create(AnswerPrototype);
desertAnswer.constructor(200);
alert(desertAnswer.get());
var firmAnswerProtoype = Object.create(AnswerPrototype);
firmAnswerProtoype.get = function(){
return AnswerPrototype.get.call(this);
}
var luckyAnswer = Object.create(firmAnswerProtoype);
luckyAnswer.constructor(1);
alert(luckyAnswer.get());
var magicAnswer = Object.create(firmAnswerProtoype);
magicAnswer.constructor(2);
alert(magicAnswer.get());
// Classical Inheritance
function Answer(value){
this._val = value;
}
Answer.prototype.get = function(){
return this._val;
}
var lifeAnswer = new Answer(100);
alert(lifeAnswer.get());
var desertAnswer = new Answer(200);
alert(desertAnswer.get());
function firmAnswer(value){
return Answer.call(this,value);
}
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype.get = function(){
return Answer.prototype.get.call(this);
}
var luckyAnswer = new firmAnswer(20);
alert(luckyAnswer.get())
Can anyone tell me on how the second one is classical and the first one is prototypal. I was watching the http://www.objectplayground.com/ and i am totally confused as in both the cases we use Object.create() and as well as prototype object.
First, to get it straight, Javascript only has prototypal inheritance. What you can do is simulate "classical" inheritance. The difference between the two boils down to the syntax with which objects are instantiated - "classical" inheritance uses the more familiar constructor functions and "new" operator, which hide the inherent prototypal nature of Javascript's object creation and inheritance properties.
Let's break down both cases a bit.
var AnswerPrototype = {
constructor: function(value){
this._val = value;
},
get: function(){
return this._val;
}
}
The prototype here is explicitly created, along with a "constructor" (or more properly named, initializing function).
var lifeAnswer = Object.create(AnswerPrototype);
lifeAnswer.constructor(100);
alert(lifeAnswer.get());
Now, creating objects is slightly clunky here. First you need to call Object.create(), and then you need to call the initializer function. This doesn't have to be the case though - here's a different sample prototype which does both in one swoop:
var AnswerPrototype = {
create: function(value){
var obj = Object.create(AnswerPrototype);
obj._val = value;
return obj;
},
get: function(){
return this._val;
}
}
var lifeAnswer = AnswerPrototype.create(100);
Simulating "classical" inheritance relies on letting developers use the more familiar constructor functions and "new" operator to create their objects, but since it it just masking the prototypal inheritance of Javascript, it remains essentially the same thing.
function Answer(value){
this._val = value;
}
Answer.prototype.get = function(){
return this._val;
}
This isn't much different from the prototypal inheritance one, except the Answer is decoupled from the now implicitly created prototype object(Which can be accessed via the Answer.prototype property)
var lifeAnswer = new Answer(100);
Practically, sugar for var lifeAnswer = Object.create(Answer.prototype); // Call Answer on the newly created object to initialize some values, e.g. with Answer.call(lifeAnswer, 100);
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype is just the implicitly created prototype, very similar to firmAnswerPrototype in the first case.
To answer your specific question, the reason why they use Object.create() here is because inheritance via new quickly becomes very clunky. You would need to do something like:
firmAnswer.prototype = new Answer();
But now you either need Answer to be an empty constructor(function Answer() {}), or explicitly differentiate between calling it with no arguments(to use for inheritance), and calling it with arguments(to use for instantiating "Answer" objects).
You have those backwards. The second one is prototypal because it uses the object's prototype property to inherit. This block
firmAnswer.prototype = Object.create(Answer);
firmAnswer.prototype.constructor = firmAnswer;
firmAnswer.prototype.get = function(){
return Answer.prototype.get.call(this);
}
is assigning an instance of Answer to firmAnswer's prototype. However, it's piss poor code, as it's not actually taking advantage of the inheritance, it's redeclaring the get function.
I would avoid this code altogether. Read Crockford's The Good Parts for a good distinction between the two types.
EDIT: To give a bit of an explanation (without referencing that code), here's the basic difference.
'Classical' inheritance in Javascript (the way I see it used) is when you override objects properties. You have an object with a foo and a bar method. You then use a library (like jQuery or Prototype) to call an extend method. The method takes two arguments, a base object and a child object. It takes all of the properties of the base object, inserts the properties of the child object (possibly overwriting) and then returns a new object that has a mix of both properties. There's a bit more to it, but that's the gist. It's just manipulating object properties without the prototype.
Prototypal inheritance uses Javascript's built in prototype. A prototype is a chain of objects (essentially). Let's say you have an object B that inherits from A. To create a C class that inherits from B, we create a function named C and then assign B to the prototype. Then, when a property is requested from C, Javascript will do the following:
Check if the property exists on the instance of C. If not:
Check if the property is on the prototype of B. If not:
Check if the property is on the prototype of A. If not:
Throw error.
Sorry if it's a little vague. I'm trying to simplify it a bit. There's a lot to the prototype in Javascript. I would suggest reading some of Crockford's materials.
How is the second one is classical and the first one is prototypal
Both are using prototypical inheritance, there are no classes in JavaScript.
The second one is called "classical" (sometimes "pseudoclassical") because it uses the class pattern and mimics the conventional class syntax (as known from Java) when objects are created with the new operator.
The only difference is the .prototype link from the constructor function to the prototype object and the shorter instantiation syntax with only one command instead of two, what happens behind is the same in both approaches.
As we can see in your example, also the inheritance between two "classes" is a bit different. In both approaches the child prototype object inherits from the parent prototype object, and in both approaches you can call parent ("super") methods by invoking the functions explicitly on the child instance. Yet, in the "classical" pattern you need to declare a new constructor function for the child (to reference it), while in your explicit prototypical approach the children are inheriting the parent's .constructor method.

why do we use `Boy.prototype = new Human;` to simulate inheritance?

i don't get why everyone is using Boy.prototype = new Human; to simulate inheritance. Look, what we want is the function's of A right? we can do that without instantiating a new A (in fact instantiating a new A does give us undesirable results, in the sense that we are actually running the instantiating function which isn't what we want)
So isn't this a better solution?
for (var prop_name in Human.prototype) {
Object.defineProperty(
Boy.prototype,
prop_name,
Object.getOwnPropertyDescriptor(Human.prototype,prop_name)
);
}
Say we are that particular and want not only the enumerable properties in Human.prototype we could still achieve it by using Object.getOwnPropertyNames and calling it on the prototype chain, which in turn is available to us through Object.getPrototypeOf.
So what exactly is the benefit of doing Boy.prototype = new Human; to simulate inheritance when we have better options available to us?
A better option is to create an intermediate to hold the prototype.
function extend(clazz, superclass) {
var intermediate = function() {};
intermediate.prototype = superclass.prototype;
clazz.prototype = new intermediate();
// Following line is optional, but useful
clazz.prototype.constructor = clazz;
}
This avoids unnecessary copying, but still means that you don't need to instantiate an object that will do work in its constructor. It also sets up the prototype chain so that you can use instanceof. It also doesn't result in superclass prototype contamination which some inheritance antipatterns can.
For completeness, your subclass should call the superclass constructor in its constructor, which you can do with Superclass.call(this);.
EDIT: Since ES5, you can replace calls to extend with
Subclass.prototype = Object.create(Superclass.prototype);
which does the same thing.
It sets up the prototype chain correctly, meaning that instanceof and isPrototypeOf() will work
It's less verbose
There are simple but ugly workarounds to prevent a constructor function from performing its usual initialization when you're just using it to create a prototype object. For example, you could either check the arguments:
function Boy(name) {
if (arguments.length == 1) {
this.name = name;
// Do other initialization
}
}
... or move the initialization into a separate method that has to be called explicitly:
function Boy(name) {}
Boy.prototype.init = function(name) {
this.name = name;
// Do other initialization
}
This has the obvious downside of requiring you to remember to call init() whenever you create a new Boy.
In ECMAScript 5 environments (current versions of most browsers, for example), a better option may be ECMAScript 5's Object.create(), which allows you to create an object which inherits directly from another object and sets up the prototype chain for you. This can be emulated (but only approximately: see Object.defineProperty in ES5?) in non-ES5 environments:
if (!Object.create) {
Object.create = function(o) {
function F() {}
F.prototype = o;
return new F();
};
}

Categories