这是我的解决方案,该解决方案基于Lorenzo Polidori的 答案中描述的标准原型继承方法。
首先,我首先定义这些帮助程序方法,这些方法使事情在以后变得更易于理解和可读:
Function.prototype.setSuperclass = function(target) {
this._superclass = target;
this.prototype = Object.create(this._superclass.prototype);
this.prototype.constructor = this;
};
Function.prototype.getSuperclass = function(target) {
return this._superclass;
};
Function.prototype.callSuper = function(target, methodName, args) {
if (arguments.length < 3) {
return this.callSuperConstructor(arguments[0], arguments[1]);
}
if (args === undefined || args === null) args = [];
var superclass = this.getSuperclass();
if (superclass === undefined) throw new TypeError("A superclass for " + this + " could not be found.");
var method = superclass.prototype[methodName];
if (typeof method != "function") throw new TypeError("TypeError: Object " + superclass.prototype + " has no method '" + methodName + "'");
return method.apply(target, args);
};
Function.prototype.callSuperConstructor = function(target, args) {
if (args === undefined || args === null) args = [];
var superclass = this.getSuperclass();
if (superclass === undefined) throw new TypeError("A superclass for " + this + " could not be found.");
return superclass.apply(target, args);
};
现在,您不仅可以使用设置类的超类SubClass.setSuperclass(ParentClass)
,还可以使用SubClass.callSuper(this, 'functionName', [argument1, argument2...])
以下方法调用覆盖的方法:
function Transform() {
this.type = "2d";
}
Transform.prototype.toString = function() {
return "Transform";
}
function Translation(x, y) {
Translation.callSuper(this, arguments);
this.x = x;
this.y = y;
}
Translation.setSuperclass(Transform);
Translation.prototype.toString = function() {
return Translation.callSuper(this, 'toString', arguments) + this.type + " Translation " + this.x + ":" + this.y;
}
function Rotation(angle) {
Rotation.callSuper(this, arguments);
this.angle = angle;
}
Rotation.setSuperclass(Transform);
Rotation.prototype.toString = function() {
return Rotation.callSuper(this, 'toString', arguments) + this.type + " Rotation " + this.angle;
}
translation = new Translation(10, 15);
console.log(translation instanceof Transform);
console.log(translation instanceof Translation);
console.log(translation instanceof Rotation);
console.log(translation.toString())
诚然,即使使用了辅助功能,这里的语法也很尴尬。值得庆幸的是,在ECMAScript 6中,添加了一些语法糖(最大类),使事情变得更漂亮。例如:
class Transform {
constructor() {
this.type = "2d";
}
toString() {
return "Transform";
}
}
class Translation extends Transform {
constructor(x, y) {
super();
this.x = x;
this.y = y;
}
toString() {
return super(...arguments) + this.type + " Translation " + this.x + ":" + this.y;
}
}
class Rotation extends Transform {
constructor(angle) {
super(...arguments);
this.angle = angle;
}
toString() {
return super(...arguments) + this.type + " Rotation " + this.angle;
}
}
translation = new Translation(10, 15);
console.log(translation instanceof Transform);
console.log(translation instanceof Translation);
console.log(translation instanceof Rotation);
console.log(translation.toString())
请注意,此时ECMAScript 6仍处于起草阶段,据我所知,没有在任何主要的Web浏览器中实现。但是,如果您愿意,可以使用Traceur编译器之类的东西编译为ECMAScript 6
普通的ECMAScript 5
基于旧式的JavaScript。您可以在此处看到使用Traceur编译的上述示例。