为什么我的接收者的 class 实例方法没有接收到任何数据?

Why does my receiver's class instance method not receive any data?

我创建了一个基本的发射器和接收器。请告诉我为什么当我控制台记录接收者消息时它 returns 是一个空数组?

class Emitter {
  constructor(messages = []) {
    this.messages = messages;
    this.event = () => {};
  }
  setEvent(fn) {
    this.event = fn;
  }
  trigger() {
    this.messages.forEach(message => this.event(message));
  }
}

class Reciever {
  constructor() {
    this.messages = []
  }
  ping(message) {
    console.log(message)
    this.messages.push(message)
  }
}

const myReciever = new Reciever();
const myEmitter = new Emitter(message = ["A", "B", "C"]);

myEmitter.setEvent(myReciever.ping);
myEmitter.trigger();

console.log(myReciever.messages);

您在 ping 通话中失去了上下文:

myEmitter.setEvent(myReciever.ping);

需要绑定。

myEmitter.setEvent(myReciever.ping.bind(myReciever));

您将所有内容都存储在发射器中,而不是接收器中。如果您打印发射器,条目会重复。

这是因为当您将函数传递给 .setEvent(...) 时,您使用的是 this - 在这种情况下 - 指的是来自发射器的消息;它丢失了它所属对象的上下文。

如@MinusFour 所示,您需要绑定函数。

查看下面的演示

class Emitter {
  constructor(messages = []) {
    this.messages = messages;
    this.event = () => {};
  }

  setEvent(fn) {
    this.event = fn;
  }

  trigger() {
    this.messages.forEach(message => this.event(message));
  }
}

class Reciever {
  constructor() {
    this.messages = []
  }

  ping(message) {
    console.log(message)
    this.messages.push(message)
  }
}

const myReciever = new Reciever();
const myEmitter = new Emitter(message = ["A", "B", "C"]);

myEmitter.setEvent(myReciever.ping.bind(myReciever));
myEmitter.trigger();

console.log(myReciever.messages);

从上面的评论...

"At the time of setEvent the code doesn't care about the this context of myReciever.ping. ... ping gets assigned to an emitters own event just as function, immediately getting oblivious where it originally did belong to."

除了已经建议的主动 binding thisArg 方法的解决方案之外,还可以以一种可以或必须传递给 setEvent 的方式调整代码方法的 target/context 与 method/function 本身。在 trigger 时间,将在此存储的上下文中调用该方法 ...

class Emitter {
  constructor(messages = []) {
    this.messages = messages;
    this.handler = () => {};
    this.target = null;
  }
  setEvent(handler, target) {
    // `setEvent` might be better renamed to
    // `setHandler` or `assignHandler`, etc.
    this.handler = handler ?? (() => {});
    this.target = target ?? null;
  }
  trigger() {
    this.messages.forEach(message =>
      this.handler.call(this.target, message)
    );
  }
}

class Reciever {
  constructor() {
    this.messages = []
  }
  ping(message) {
    console.log(message)
    this.messages.push(message)
  }
}

const myReciever = new Reciever();
const myEmitter = new Emitter(message = ["A", "B", "C"]);

myEmitter.setEvent(myReciever.ping, myReciever);
myEmitter.trigger();

console.log(myReciever.messages);