首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >什么是一个好的简约Javascript继承方法?

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

Stack Overflow用户
提问于 2009-09-10 10:47:22
回答 5查看 1.9K关注 0票数 6

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

因此,我正在寻找一种在JavaScript中编写“类”继承的方法,该继承具有以下要求:

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

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

代码语言:javascript
复制
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();

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

欢迎提出任何建议。

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2009-09-10 11:18:23

我建议使用函数从原型而不是实例继承以下模式:

代码语言:javascript
复制
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); // ...
};

方法驻留在原型中是很重要的(因为性能方面的原因,它应该是这样的),所以您可以通过以下方式调用超类的方法

代码语言:javascript
复制
SuperClass.prototype.aMethod.call(this, arg1, arg2);

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

代码语言:javascript
复制
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); // ...
    }
});
票数 5
EN

Stack Overflow用户

发布于 2009-09-10 10:49:33

Douglas在Javascript中有关于古典主义原型继承的优秀文章,这应该是一个很好的起点。

票数 4
EN

Stack Overflow用户

发布于 2009-09-10 12:44:33

好的,在JavaScript中复制类/实例样式系统的诀窍是,您只能在实例上使用原型继承。因此,您需要能够创建一个仅用于继承的“非实例”实例,并将初始化方法与构造函数本身分开。

这是我使用的最小系统(在添加花边之前),将一个特殊的一次性值传递给构造函数,让它在不初始化对象的情况下构造一个对象:

代码语言:javascript
复制
Function.prototype.subclass= function() {
    var c= new Function(
        'if (!(this instanceof arguments.callee)) throw(\'Constructor called without "new"\'); '+
        'if (arguments[0]!==Function.prototype.subclass._FLAG && this._init) this._init.apply(this, arguments); '
    );
    if (this!==Object)
        c.prototype= new this(Function.prototype.subclass._FLAG);
    return c;
};
Function.prototype.subclass._FLAG= {};

使用new Function()是避免在子类()上形成不必要的闭包的一种方法。如果您愿意,可以用更漂亮的function() {...}表达式替换它。

用法相对清晰,通常类似于Python样式的对象,但语法稍显笨拙:

代码语言:javascript
复制
var Shape= Object.subclass();
Shape.prototype._init= function(x, y) {
    this.x= x;
    this.y= y;
};
Shape.prototype.draw= function() {
    throw new Error("Arbitrary shapes cannot be drawn");
};

var Square= Shape.subclass();
Square.prototype._init= function(x, y, side) {
    Shape.prototype._init.call(this, x, y);
    this.side= side;
};
Square.prototype.draw= function() {
    gotoXY(this.x, this.y);
    lineTo(this.x+this.side, this.y); // ...
};

猴子修补一个内置的(功能)有点问题,但它让人愉快地阅读,而且没有人可能想要for...in的一个功能。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1404559

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档