简体   繁体   中英

JavaScript - For what reason… Inheritance

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.

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();

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):

  • Property/method lookup always goes up in the prototype chain. That's all the inheritance that you have.
  • "Clonning" (in terms of Object.create) means to create a new empty object, and set the prototype from the given object.
  • Prototypes are just reference to objects, so you can add/change slots at any time.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM