javascript继承和唯一实例

时间:2014-08-09 17:35:24

标签: javascript

function Shape() {
    this.name = "none"; 
}

function Rect () {        
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
};

如果Shape的所有属性都可用于Rect,那么写

是正确的
Rect.prototype = Shape;

在这种情况下,Rect(i.e. Object.create(Rect))的每个实例都会从Shape对象中获取一个单独的名称。

2 个答案:

答案 0 :(得分:6)

Rect.prototype = Shape;绝对不正确。 Rect的每个实例都具有与函数 Shape相同的属性。这包括每个函数都有的方法,如.call.apply

但是,即使Rect.prototype = new Shape;如其他答案中所建议的那样也不是一个好的解决方案。虽然这会将name添加到Rect的每个实例,但每个实例都会共享相同的name属性。但name特定于实例的属性,它不属于原型。原型链应该只包含应该由每个实例共享的属性(值)。

那么,该怎么办?

Shape.prototype添加到Rect个实例的原型链中:

Rect.prototype = Object.create(Shape.prototype, {constructor: {value: Rect}});

您在Shape.prototype上没有任何自定义属性,但是,设置此属性可以完成以下工作:

var r = new Rect();
r instanceof Shape; // true

您还必须在Shape构造函数中调用超级构造函数Rect),并将this设置为新实例:

function Rect () {
    Shape.call(this);

    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
}

Shape.call(this);name分配给我们的新Rect 实例的时刻。

如果您来自Java或其他面向类的OO语言,这与在子构造函数中调用super();基本相同。


以上所有内容正是新ES6 class语法在内部的作用。

class Rect extends Shape {
  constructor() {
      super();
      // ...
  }
}

答案 1 :(得分:0)

你必须写下以下内容。

Rect.prototype = new Shape();

这将为Shape创建一个新对象,然后将其指定为Rect的原型。您不能将函数指定为原型。