什么是一个很好的简约Javascript继承方法?

Gus*_*uss 6 javascript oop inheritance

我正在重写一个JavaScript项目,我希望能够使用面向对象的方法来组织当前代码的混乱.主要关注的是这个JavaScript应该作为第三方网站内的一个小部件运行,我不能让它与其他网站可能使用的其他JavaScript库冲突.

所以我正在寻找一种在JavaScript中编写"类类"继承的方法,它具有以下要求:

  1. 没有外部库或与外部库冲突的东西(阻止从外部库复制和粘贴).
  2. 简约 - 我不希望支持代码比几行代码更大,我不希望开发人员每次定义新的类或方法时都需要大量的样板.
  3. 应该允许动态扩展父对象,以便子对象看到更改(原型).
  4. 应该允许构造函数链接.
  5. 应该允许super类型调用.
  6. 还应该感受到JavaScript-ish.

最初我尝试使用简单的原型链接:

function Shape(x,y) {
  this.x = x;
  this.y = y;

  this.draw = function() {
    throw new Error("Arbitrary shapes cannot be drawn");
  }
}

function Square(x,y,side) {
  this.x = x;
  this.y = y;
  this.side = side;

  this.draw = function() {
    gotoXY(this.x,this.y); lineTo(this.x+this.side, this.y); ...
  }
}
Square.prototype = new Shape();
Run Code Online (Sandbox Code Playgroud)

这解决了需求1,2和6,但id不允许超级调用(新函数覆盖父函数),构造函数链接和动态扩展父级不会为子类提供新方法.

欢迎任何建议.

Chr*_*oph 5

我建议使用以下模式,它使用一个clone函数来继承原型而不是实例:

function Shape(x, y) {
    this.x = x;
    this.y = y;
}

Shape.prototype.draw = function() {
    throw new Error('Arbitrary shapes cannot be drawn');
};

function Square(x,y,side) {
    Shape.call(this, x, y); // call super constructor
    this.side = side;
}

// inherit from `Shape.prototype` and *not* an actual instance:
Square.prototype = clone(Shape.prototype);

// override `draw()` method
Square.prototype.draw = function() {
    gotoXY(this.x,this.y); lineTo(this.x+this.side, this.y); // ...
};
Run Code Online (Sandbox Code Playgroud)

方法驻留在原型中是非常重要的(出于性能原因,它应该是应该的)因此你可以调用超类的方法

SuperClass.prototype.aMethod.call(this, arg1, arg2);
Run Code Online (Sandbox Code Playgroud)

使用一些语法糖,你可以使JS看起来像一个经典的基于类的语言:

var Shape = Class.extend({
    constructor : function(x, y) {
        this.x = x;
        this.y = y;
    },
    draw : function() {
        throw new Error('Arbitrary shapes cannot be drawn');
    }
});

var Square = Shape.extend({
    constructor : function(x, y, side) {
        Shape.call(this, x, y);
        this.side = side
    },
    draw : function() {
        gotoXY(this.x,this.y); lineTo(this.x+this.side, this.y); // ...
    }
});
Run Code Online (Sandbox Code Playgroud)