Reputation: 2240
Can someone tell me, please, for what reason this is allowed (?):
function A()
{
A.prototype.getA = function()
{
return "A!";
}
}
function B()
{
B.prototype.getB = function()
{
return "B!";
}
}
// Purposely placed here.
B.prototype = new A();
function SuperA()
{
SuperA.prototype.getSuperA = function()
{
return "SUPER A!";
}
}
A.prototype = new SuperA();
var objectB = new B();
alert(objectB.getA()); // A!
alert(objectB.getB()); // B!
alert(objectB.getSuperA()); // Error...
For what reason is permissible change a heritage structure, even in use? This change in inheritance structure should not be reflected?
Here is a possible / alleged inheritance among 3 types. Of course, the right thing to do would be to change the position of the statement "B.prototype = new A();", but I left that way on purpose.
Upvotes: 0
Views: 53
Reputation: 700342
That's because you can't declare the inheritance structure. All inheritance is done dynamically at runtime, so there is no point in time where it's no longer possible to change it.
When you use an instance of one class as a prottype for another, it's inheriting that instance, not just copying the structure. Example:
function A() {}
A.prototype = {
hello: function() {}
};
var a = new A();
function B() {}
B.prototype = a;
var b = new B();
// all instances of B has the hello method
b.hello();
// add a method to the A instance
a.goodbye = function() {};
// now all instances of B have that method
b.goodbye();
Upvotes: 1
Reputation: 4433
This line:
B.prototype = new A();
Says assign the prototype to an instance of A. If you leave out the constructor call, it's equivalent to this:
B.prototype = Object.create(A.prototype);
It means that B.prototype
is pointing to an object cloned from A.prototype
:
Object.getPrototypeOf(B.prototype) === A.prototype // true
But then in this line:
A.prototype = new SuperA();
You are replacing the reference in A.prototype
but B.prototype
still points to the old one:
var oldProto = A.prototype;
A.prototype = new SuperA();
Object.getPrototypeOf(B.prototype) === A.prototype // false
Object.getPrototypeOf(B.prototype) === oldProto // true
This line works:
alert(objectB.getA());
Because getA
was added in the new A()
call, so it adds a new slot to the existing prototype, instead of replacing the whole instance.
And this:
alert(objectB.getSuperA());
Doesn't work because SuperA is not in the prototype chain of B.
This problem is very tricky. But actually JavaScript has a very simple model, but confusing by some of the language keywords (new/instanceof), and the strange use of functions (to resemble Java constructors):
With only those two things you don't need the rest. And constructors -with some small internal differences- can be seen as a shortcut to:
var newInstance = Object.create(SomeFunction.prototype);
SomeFunction.constructor.apply(newInstance, arguments);
To me the use of functions to create objects was a bad idea, if JavaScript only had Object.create
from version 1 and no constructor functions, all the model is much easier to understand.
Upvotes: 1