JavaScript - 为什么...继承

JavaScript - For what reason… Inheritance

谁能告诉我,为什么允许这样做(?):

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...

为什么允许更改遗产结构,即使是在使用中?这种继承结构的变化应该不会反映吧?

这是 3 种类型之间可能的/所谓的继承。当然,正确的做法是改变语句 "B.prototype = new A();" 的位置,但我是故意离开的。

那是因为你不能声明继承结构。所有继承都是在运行时动态完成的,因此没有时间点无法再更改它。

当您使用一个 class 的实例作为另一个的原型时,它是在继承该实例,而不仅仅是复制结构。示例:

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

这一行:

 B.prototype = new A();

说将原型分配给 A 的一个实例。 如果省略构造函数调用,则相当于:

B.prototype = Object.create(A.prototype);

这意味着 B.prototype 指向从 A.prototype 克隆的对象:

Object.getPrototypeOf(B.prototype) === A.prototype // true

但是在这一行中:

A.prototype = new SuperA();

您正在替换 A.prototype 中的引用,但 B.prototype 仍然指向旧引用:

var oldProto = A.prototype;
A.prototype = new SuperA();
Object.getPrototypeOf(B.prototype) === A.prototype // false
Object.getPrototypeOf(B.prototype) === oldProto    // true

这一行有效:

alert(objectB.getA());

因为 getA 是在 new A() 调用中添加的,所以它向现有原型添加了一个新插槽,而不是替换整个实例。

还有这个:

alert(objectB.getSuperA()); 

不起作用,因为 SuperA 不在 B 的原型链中。

这个问题很棘手。但实际上 JavaScript 有一个非常简单的模型,但被一些语言关键字(new/instanceof)和函数的奇怪使用(类似于 Java 构造函数)混淆了:

  • Property/method 查找总是在原型链中向上。这就是你所有的遗产。
  • "Clonning"(就Object.create而言)意味着创建一个新的空对象,并从给定的对象设置原型。
  • 原型只是对对象的引用,因此您可以随时 add/change 插槽。

只有这两件事你不需要其余的。和构造函数 - 有一些小的内部差异 - 可以看作是一个捷径:

var newInstance = Object.create(SomeFunction.prototype);
SomeFunction.constructor.apply(newInstance, arguments);

对我来说,使用函数创建对象是个坏主意,如果 JavaScript 只有版本 1 中的 Object.create 而没有构造函数,那么所有模型都更容易理解。