对 JavaScript 中的事件调用 class 方法不会更改 class 属性

Calling a class method on event in JavaScript does not change class property

考虑这段代码:

var states = {
  "default" : {
    foo: "foo",
    mouseReleased: function() {
      console.log("Mouse released");
      this.foo = "bar";
    }
  }
}

var canvas = function(states) {
  return {
    states: states,
    currentState: "default",
    draw: function() {
      if (this.states[this.currentState].mouseReleased != undefined) {
        window.mouseReleased = this.states[this.currentState].mouseReleased
      }
    }
  }
}

当我释放鼠标时,控制台显示“鼠标已释放”,但 states.default.foo 不会更改为 bar。有没有办法不使用 window.mouseReleasedthis?我读过一些关于 bind 的内容,但我不确定它是什么意思。我在正确的地方搜索吗?

尽管共享代码在其他方面无效且非常不寻常,但看起来确实是 classic 函数绑定问题。

问题是 this 关键字的含义在 Javascript 中有些不寻常。默认情况下,在函数体中,this 将引用调用函数时点左侧的对象。所以,例如:

let objectA = {
  whoAmI: 'A',
  sayA: function() {
    console.log(this.whoAmI);
  }
};

let objectB = {
  whoAmI: 'B'
};

objectB.sayA = objectA.sayA;

// Logs 'A'
objectA.sayA();
// Logs 'B' because `this` now refers to `objectB`
objectB.sayA();

let defaultThis = objectA.sayA;
// This will log undefined because `this` defaults to the global scope, or `window`
defaultThis();

当您想锁定 this 的特定值时,bind() 就派上用场了。因此,如果我有一个 class 方法想直接用作事件处理程序,我将需要调用 bind() 并使用我希望 this 引用的对象:

let obj = {
  state: 0,
  handler: function() { console.log(this.state); this.state++; }
}

// This logs undefined, NaN, NaN, NaN because `this` will be `window` which does not have a `state` property
window.addEventListener('click', obj.handler);
// This logs 0, 1, 2, 3
window.addEventListener('click', obj.handler.bind(obj));

同样的原则也适用于 p5.js 事件处理函数。