JavaScript - 出于什么原因......继承

时间:2015-03-28 01:49:04

标签: javascript inheritance ecmascript-5

有人可以告诉我,原因是什么(?):

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();”的位置,但我故意这样做。

2 个答案:

答案 0 :(得分:1)

那是因为你不能宣告继承结构。所有继承都是在运行时动态完成的,因此没有时间可以更改它。

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

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

答案 1 :(得分:1)

这一行:

 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构造函数)而令人困惑:

  • 属性/方法查找总是在原型链中上升。这就是你拥有的所有遗产。
  • “Clonning”(就Object.create而言)意味着创建一个新的空对象,并从给定对象设置原型。
  • 原型只是对象的引用,因此您可以随时添加/更改插槽。

只有这两件事你不需要休息。而构造函数 - 具有一些小的内部差异 - 可以被视为一个捷径:

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

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