javascript继承和唯一实例

Tal*_*Kit 0 javascript

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

function Rect () {        
    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
};
Run Code Online (Sandbox Code Playgroud)

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

Rect.prototype = Shape;
Run Code Online (Sandbox Code Playgroud)

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

Fel*_*ing 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}});
Run Code Online (Sandbox Code Playgroud)

您还没有任何自定义属性Shape.prototype,但是,设置它会使以下工作:

var r = new Rect();
r instanceof Shape; // true
Run Code Online (Sandbox Code Playgroud)

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

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

    this.x = 0;
    this.y = 0;
    this.width = 0;
    this.height = 0;
}
Run Code Online (Sandbox Code Playgroud)

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

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


以上所有内容正是新ES6 class语法在内部所做的.

class Rect extends Shape {
  constructor() {
      super();
      // ...
  }
}
Run Code Online (Sandbox Code Playgroud)