为什么我不能使用"这个"在一个箭头函数中调用超级构造函数?

时间:2018-06-15 00:00:36

标签: javascript class ecmascript-6 arrow-functions

我试图创建一个延迟的promise构造函数,如下所示:

class DeferredPromise extends Promise {
  constructor() {
    super((resolve, reject) => {
      this.resolve = resolve
      this.reject = reject
    })
  }
}

但是,当我尝试使用new DeferredPromise()时,我在Firefox 60.0.01中收到以下错误

ReferenceError: must call super constructor before using |this| in arrow function in derived class constructor

为什么我会收到此错误,如何解决此问题?另外,如果有更好的解决方案,请告诉我。

1 个答案:

答案 0 :(得分:2)

在父构造函数调用(this)之前,子类中不允许

super,因为this在此之前不存在(父类可以返回另一个对象)而不是this)。此规范强制执行此ES6类限制。

the reference所述,

  

如果子类中存在构造函数,则需要在使用&#34之前首先调用super();这个"。

如果知道只有在父构造函数调用之后才在函数内部使用this,则可以安全地使用它:

class Foo {
  constructor(callback) {
    this.doFoo = callback;
  }
}

class Bar extends Foo {
  constructor() {
    super(() => {
      this.doBar();
    })
  }

  doBar() {}
}

new Bar().doFoo();

否则this只能在父构造函数调用之后引用:

class DeferredPromise extends Promise {
  constructor() {
    let resolve, reject;

    super((_resolve, _reject) => {
      resolve = _resolve;
      reject = _reject;
    });

    this.resolve = resolve;
    this.reject = reject;
  }
}

这会导致Promise特有的问题并在this answer中有所描述,建议的解决方案是:

DeferredPromise.prototype.constructor = Promise;

这意味着需要存储DeferredPromise个实例来访问resolvereject方法,它们不会在链式承诺中提供:

let deferred = new DeferredPromise();
let nonDeferred = deferred.catch(() => {});
// nonDeferred.reject === undefined

composition over inheritance就属于这种情况。延迟模式不需要延长承诺类,这样做没有明显的好处。实现可以简单如下:

class Deferred {
  constructor() {
    this.promise = new Promise((resolve, reject) => {
      this.resolve = resolve;
      this.reject = reject;
    });
  }
}