有人可以告诉我,原因是什么(?):
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();”的位置,但我故意这样做。
答案 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构造函数)而令人困惑:
只有这两件事你不需要休息。而构造函数 - 具有一些小的内部差异 - 可以被视为一个捷径:
var newInstance = Object.create(SomeFunction.prototype);
SomeFunction.constructor.apply(newInstance, arguments);
对我来说,使用函数来创建对象是一个坏主意,如果JavaScript只有版本1中的Object.create
而没有构造函数,那么所有模型都更容易理解。