首页 > 解决方案 > 确保 `this` 指向 API 实例方法中的类的实例

问题描述

考虑以下示例:

class Test {
  constructor() {
    this.x = 42;
  }
  
  someMethod() {
    console.log(this.x);
  }
}

testBtn.x = -42;

var TestInstance = new Test()

testBtn.addEventListener('click', TestInstance.someMethod);
<button id="testBtn" type="button">Click me</button>

单击该按钮将登录-42到控制台。

我知道我可以通过显式绑定TestInstance到事件处理程序引用来解决这个问题:

class Test {
  constructor() {
    this.x = 42;
  }
  
  someMethod() {
    console.log(this.x);
  }
}

testBtn.x = -42;

var TestInstance = new Test()

testBtn.addEventListener('click', TestInstance.someMethod.bind(TestInstance));
<button id="testBtn" type="button">Click me</button>

这样做的缺点是我不能再删除那个事件监听器。

我知道这也可以解决:

class Test {
  constructor() {
    this.x = 42;
    this.someMethod = this._someMethod.bind(this);
  }
  
  _someMethod() {
    console.log(this.x);
    testBtn.removeEventListener('click', this.someMethod);
  }
}

testBtn.x = -42;

var TestInstance = new Test()

testBtn.addEventListener('click', TestInstance.someMethod);
<button id="testBtn" type="button">Click me</button>

但这基本上意味着要在需要this指向实例的每个方法上公开类 API,我必须在构造函数中创建该方法的绑定版本。

这是预期的工作方式,还是我错过了一种不同的、希望更好的方法?

编辑:所以我会一直这样做,直到公共类字段语法提案通过提案状态:

class Test {
  constructor() {
    this.x = 42;
    
    const boundMethodNames = ['someMethod'];
    boundMethodNames.forEach(method => this[method] = this[method].bind(this));
  }
  
  someMethod() {
    console.log(this.x);
    testBtn.removeEventListener('click', this.someMethod);
  }
}

testBtn.x = -42;

var TestInstance = new Test();

testBtn.addEventListener('click', TestInstance.someMethod);
<button id="testBtn" type="button">Click me</button>

标签: javascriptecmascript-6thises6-class

解决方案


推荐阅读