了解原型继承

马克斯·科雷茨基(Max Koretskyi)

我画了下图,展示了对象是如何继承的(函数构造函数被标记为蓝色,从那些构造函数创建的对象被标记为绿色):

在此处输入图片说明

这是创建这种层次结构的代码:

function Figure() {}

function Rect() {}
Rect.prototype = new Figure();

function Square() {}
Square.prototype = new Rect();

function Ellipse() {}
Ellipse.prototype = new Figure();

function Circle() {}
Circle.prototype = new Ellipse();

现在,我想检查是否new Square()继承自Rect,因此这是我期望JavaScript引擎检查的方式:

var s = new Square();
s instanceof Rect // ?

s.__proto__ === Rect.prototype // false
new Rect()      new Figure()

s.__proto__.__proto__ === Rect.prototype // true
new Figure()              new Figure()

所以s instanceof Rect应该退货true这是预料之中的,实际上是我运行代码后返回的结果。但是然后我想检查是否new Circle()继承自Rect,所以我遵循相同的逻辑:

var c = new Circle();
c instanceof Rect // ?

c.__proto__ === Rect.prototype // false
new Ellipse()      new Figure()

c.__proto__.__proto__ === Rect.prototype // true
new Figure()              new Figure()

因此,使用此检查逻辑c instanceof Rect应返回true,但如果我实际运行代码,则c instanceof Rect返回false。我是否误解了instanceof操作员的机制

塔玛斯·赫格杜斯(Tamas Hegedus)

您的逻辑是正确的,但最初的假设有些错误。可以使用原型来模拟基于常规类的继承。

为了重现您绘制的结构,我创建了以下代码:

function Figure() {}
function Rect() {}
function Square() {}

function Ellipse() {}
function Circle() {}

Ellipse.prototype = Rect.prototype = new Figure();

Square.prototype = new Rect();
Circle.prototype = new Ellipse();

console.log("is Figure: " + (new Circle() instanceof Figure));
console.log("is Ellipse: " + (new Circle() instanceof Ellipse));
console.log("is Rect: " + (new Circle() instanceof Rect));

如您所见,new Circle() instanceof Rect按置备返回true。问题在于,通过将Ellipse.prototype设置Rect.prototype为相同的对象,它们基本上变成了相同的类型(具有多个构造函数)。

那么如何解决呢?Figure为原型创建不同的实例,如下所示:

function Figure() {}
function Rect() {}
function Square() {}

function Ellipse() {}
function Circle() {}

Ellipse.prototype = new Figure();
Rect.prototype = new Figure();

Square.prototype = new Rect();
Circle.prototype = new Ellipse();

console.log("is Figure: " + (new Circle() instanceof Figure));
console.log("is Ellipse: " + (new Circle() instanceof Ellipse));
console.log("is Rect: " + (new Circle() instanceof Rect));

现在的结果是每个人都期望的。

编辑

我重新绘制了您的图片,并绘制了另一张图片,该图片根据您的文本示例说明了这些对象实际上是如何创建的,这与第二个代码相同。

原始的一个:我突出显示了表达式中的引用Rect.prototype === new Circle().__proto__.__proto__

在此处输入图片说明

第二个:

在此处输入图片说明

聚苯乙烯

在2016年的今天,不是Circle.prototype = new Ellipse()实现继承的方法,而是使用标准的类继承:

class Figure {}
class Rect extends Figure {}
class Square extends Rect {}
class Ellipse extends Figure {}
class Circle extends Ellipse {}

console.log("new Circle is Figure: " + (new Circle() instanceof Figure));
console.log("new Circle is Rect: " + (new Circle() instanceof Rect));

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章