了解原型继承

Max*_*kyi 11 javascript inheritance

我画了下面的图片,演示了如何继承对象(函数构造函数标记为蓝色,从这些构造函数创建的对象标记为绿色):

在此输入图像描述

以下是创建此类层次结构的代码:

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();
Run Code Online (Sandbox Code Playgroud)

现在我想检查是否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()
Run Code Online (Sandbox Code Playgroud)

所以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()
Run Code Online (Sandbox Code Playgroud)

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

Tam*_*dus 8

你的逻辑是对的,但最初的假设有点不对劲.可以使用原型模拟基于常规类的继承.

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

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));
Run Code Online (Sandbox Code Playgroud)

如您所见,在配置时new Circle() instanceof Rect返回true.问题是通过设置Ellipse.prototypeRect.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));
Run Code Online (Sandbox Code Playgroud)

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

编辑

我重新绘制了你的图片,并绘制了另一个图片,它说明了对象的真实基于你的文本示例,这与我的第二个代码相同.

原文:我突出了表达式中的引用Rect.prototype === new Circle().__proto__.__proto__:

在此输入图像描述

第二个:

在此输入图像描述

PS

今天在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));
Run Code Online (Sandbox Code Playgroud)

  • 另一种方法是[使用Object.create](http://stackoverflow.com/a/17393153/3928341) (2认同)