7

我注意到每个关于如何进行 JavaScript 继承的教程都是这样做的:

SubClass.prototype = new SuperClass();

但这将创建超类的单个实例并在子类的所有实例之间共享它。

问题是我想将参数传递给超类构造函数,该构造函数源自传递给子类的参数。

在 Java 中,这将是这样完成的:

class SubClass extends SuperClass {
  public SubClass(String s) {
    super(s);
  }
}

我试着做这样的事情:

function SubClass(args) {
  this.constructor.prototype = new SuperClass(args);
}

但这行不通。那么有没有办法在 JavaScript 中做到这一点?

4

5 回答 5

6

一个常见的模式如下:

创建了一个临时构造函数,它继承自父构造函数的原型。然后将子构造函数的原型设置为临时构造函数的一个实例。

function inherits(Child, Parent) {
    var Tmp = function() {};
    Tmp.prototype = Parent.prototype;
    Child.prototype = new Tmp();
    Child.prototype.constructor = Child;
}

在子构造函数中,您必须调用父构造函数:

function Child(a, b, c) {
    Parent.call(this, a, b);
}

inherits(Child, Parent);

// add prototype properties here

在这个函数调用中,this将引用调用时创建的新对象new Child(),因此,无论在内部执行什么初始化Parent,它都会应用于我们传递的新对象。

于 2012-01-05T00:46:11.457 回答
2

但这将创建超类的单个实例并在子类的所有实例之间共享它。

是的,这就是 JavaScript 中继承的工作原理。

那么有没有办法在 JavaScript 中做到这一点?

并非没有可怕地颠覆/扭曲/滥用现有范式。我建议采取不同的方法来实现您的目标。

于 2012-01-05T00:42:49.787 回答
2

这就是我一直这样做的方式。

// Parent object
function Thing(options)
{ 
    //do stuff
}

Thing.prototype.someMethod = function(){
    // some stuff
   console.log('hello');
}

// child object which inherits from the parent
function OtherThing(options)
{       
    Thing.call(this, options);
    // do stuff for otherthing
}

OtherThing.prototype = new Thing();

OtherThing.prototype.someMethod = function(){
   // call things original function
   Thing.prototype.someMethod.call(this);

   // now do anything different
   console.log('other thing says hi');
}


var testObj = new OtherThing();
    testObj.someMethod();

现场演示

于 2012-01-05T00:45:53.953 回答
0

另一种方法是摆脱涉及使用构造函数的类类(但不是基于类)的继承。

将 Object.create 与 Object.defineProperties 一起使用。这是基于 JavaScript 内部遵循的基于原型的原生继承系统。

您可以在 MDN 和 ECMAScript 规范上找到更多信息。

然而,这些方法仅适用于兼容 ECMAScript 5 的浏览器。这不包括 IE8 和更早版本。幸运的是,IE9 和其他主流浏览器一样支持它。从长远来看,我认为这是要走的路。

于 2012-01-05T04:51:17.267 回答
0

现在Object.create()可以简化“临时构造函数”模式。这是文档中的一个示例-使用 Object.create() 的经典继承

// Shape - superclass
function Shape() {
  this.x = 0;
  this.y = 0;
}

// superclass method
Shape.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

// Rectangle - subclass
function Rectangle() {
  Shape.call(this); // call super constructor.
}

// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);

//If you don't set Rectangle.prototype.constructor to Rectangle,
//it will take the prototype.constructor of Shape (parent).
//To avoid that, we set the prototype.constructor to Rectangle (child).
Rectangle.prototype.constructor = Rectangle;

var rect = new Rectangle();

console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle); // true
console.log('Is rect an instance of Shape?', rect instanceof Shape); // true
rect.move(1, 1); // Outputs, 'Shape moved.'
于 2021-02-10T19:29:04.273 回答