是否可以在JavaScript中从ECMAScript 6类继承旧式类?

时间:2022-09-25 11:58:51

When running the following code on Node.js 4.2.1:

在Node.js 4.2.1上运行以下代码时:

'use strict';

var util = require('util');

class MyClass {
  constructor(name) {
    this.name = name;
  }
}

function MyDerived() {
  MyClass.call(this, 'MyDerived');
}

util.inherits(MyDerived, MyClass);

var d = new MyDerived();

I get the following error:

我收到以下错误:

constructor(name) {
         ^

TypeError: Class constructors cannot be invoked without 'new'

I wonder if it is at all possible to inherit old-style JavaScript "classes" from ECMAScript 6 classes? And, if possible, then how?

我想知道是否可以从ECMAScript 6类继承旧式JavaScript“类”?并且,如果可能的话,那怎么样?

1 个解决方案

#1


8  

There's not really a way out once you've opted in to class syntax.

一旦你选择了类语法,就没有出路了。

The problem is that inheritance in ES6 is done by late-initialising the this keyword with the return value from super(), which is a constructor call like with new. The old idiom of "applying" (.call()) the parent constructor on the currently "uninitialised" child instance does work no more.

问题是ES6中的继承是通过使用super()的返回值来初始化this关键字来完成的,这是一个像new一样的构造函数调用。在当前“未初始化的”子实例上“应用”(.call())父构造函数的旧习惯不再起作用。

What you can still do is to resort to "parasitic inheritance" - you'll have to explicitly construct the instance, extend it, and return it:

您仍然可以做的是求助于“寄生继承” - 您必须显式构造实例,扩展它并返回它:

function MyDerived() {
  var derived = new MyClass('MyDerived');
  … // set up properties
  return derived;
}

When you do this with new MyClass, you won't get the prototype set up correctly however. For that, you will need to use the new ES6 Reflect.construct function, which takes the child class as an optional third parameter:

当您使用新的MyClass执行此操作时,您将无法正确设置原型。为此,您需要使用新的ES6 Reflect.construct函数,该函数将子类作为可选的第三个参数:

function MyDerived() {
  var derived = Reflect.construct(MyClass, ['MyDerived'], new.target||MyDerived);
  … // set up properties
  return derived;
}

This has the additional benefit that MyDerived doesn't need to be called with new any more (as long as you supply MyDerived when new.target is empty).

这样做的另一个好处是MyDerived不再需要再调用new(只要你在new.target为空时提供MyDerived)。

#1


8  

There's not really a way out once you've opted in to class syntax.

一旦你选择了类语法,就没有出路了。

The problem is that inheritance in ES6 is done by late-initialising the this keyword with the return value from super(), which is a constructor call like with new. The old idiom of "applying" (.call()) the parent constructor on the currently "uninitialised" child instance does work no more.

问题是ES6中的继承是通过使用super()的返回值来初始化this关键字来完成的,这是一个像new一样的构造函数调用。在当前“未初始化的”子实例上“应用”(.call())父构造函数的旧习惯不再起作用。

What you can still do is to resort to "parasitic inheritance" - you'll have to explicitly construct the instance, extend it, and return it:

您仍然可以做的是求助于“寄生继承” - 您必须显式构造实例,扩展它并返回它:

function MyDerived() {
  var derived = new MyClass('MyDerived');
  … // set up properties
  return derived;
}

When you do this with new MyClass, you won't get the prototype set up correctly however. For that, you will need to use the new ES6 Reflect.construct function, which takes the child class as an optional third parameter:

当您使用新的MyClass执行此操作时,您将无法正确设置原型。为此,您需要使用新的ES6 Reflect.construct函数,该函数将子类作为可选的第三个参数:

function MyDerived() {
  var derived = Reflect.construct(MyClass, ['MyDerived'], new.target||MyDerived);
  … // set up properties
  return derived;
}

This has the additional benefit that MyDerived doesn't need to be called with new any more (as long as you supply MyDerived when new.target is empty).

这样做的另一个好处是MyDerived不再需要再调用new(只要你在new.target为空时提供MyDerived)。