用命名函数覆盖箭头函数时会发生什么?

问题描述 投票:0回答:1

我有如下代码:

class ClickModule {
   constructor() {
      this.handleClick = this.handleClick.bind(this);
   }

   handleClick = (evt) => {}
}

class ImageModule extends ClickModule {
   handleClick(evt) {
      //some logic that never gets called
   }
}

handleClick 是用作回调的函数。 我知道你不能绑定箭头函数,但由于它被重写为类方法,为什么它不起作用?

修复是将初始 handleClick 声明为

handleClick(evt) {}

但是我不太明白是什么导致 ImageModule 中的 handleClick 从未被调用过。

谢谢

我在这个codePen上测试过https://codepen.io/mpfrancog/pen/rNZREdx

javascript inheritance callback bind es6-class
1个回答
3
投票

handleClick
上的
ImageModule
根本没有被使用,因为
ClickModule
的类property(不是方法)在构造时分配给instance,所以它优先于
handleClick 
在原型上,实例来自
ImageModule.prototype
.

这是当你这样做时会发生什么

new ImageModule

  1. (自动生成的)

    ImageModule
    构造函数被调用。

  2. 它调用

    ClickModule
    的构造函数。

  3. 就在调用

    ClickModule
    的构造函数之前,使用
    ImageModule.prototype
    作为原型创建了一个实例。
    ImageModule.prototype
    具有来自
    handleClick
    ImageModule
    ,因此在这个短暂的时刻,实例将继承该方法。但是……

  4. 调用

    ClickModule
    的构造函数中的代码

    • 该构造函数中的第一件事是您在此处定义的类属性:
      handleClick = (evt) => {}
      
      构建类时,该代码被放入构造函数中,就好像构造函数以此开头:
      Object.defineProperty(this, "handleClick", {
           "value": (evt) => {},
           "writable": true,
           "enumerable": true,
           "configurable": true
      });
      
      也就是说,它将属性放在实例上(替换任何存在的属性,但在这种情况下没有),因此实例从其原型继承的属性将不会被使用。
    • 构造函数的代码继续调用
      bind
      ,使用instance(不是原型)属性然后写入它。
      bind
      调用没有任何效果(在本例中),因为它不绑定任何参数并尝试绑定箭头函数已经关闭的
      this
      值。

所以

ImageModule
handleClick
根本没有用到

如果你想要一个子类可以覆盖的方法,定义一个method,而不是类属性:

class ClickModule {
    constructor() {
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick(evt) {
        // ...presumably some code here...
    }
}

class ImageModule extends ClickModule {
    handleClick(evt) {
        // ...some logic that now _will_ get called...
    }
}

这样,

bind
中的
ClickModule
调用与实例原型上的
handleClick
一起工作,这是来自
ImageModule
的原型。

© www.soinside.com 2019 - 2024. All rights reserved.