为什么 this.name 未定义?

Why is this.name undefined?

为什么 this.name returns 我未定义?

function EventEmitter() {
  var events = {};
  this.name = "Google"
  this.on = function(name, fn) {
    events[name] = events[name] || [];
    events[name].push(fn);
  }
  this.trigger = function(name, args) {
    events[name] = events[name] || [];
    args = args || [];
    events[name].forEach(function(fn) {
      fn.apply(this, args);
    });
  }
}

var my_event_emitter = new EventEmitter();
my_event_emitter.on('curtain_dropped', function() {
  console.log(this.name);
});
my_event_emitter.trigger('curtain_dropped', [true]);

当我调用 fn.apply(this, args)this 不是 EventEmitter 的实例 my_event_emitter?

否; this 是调用您的 forEach 回调的上下文。
默认情况下,这是全局对象。

您需要将第二个参数传递给 forEach() 以告诉它 this 应该在其回调中是什么。

因为下面的代码行:

events[name].forEach(function(fn) {
  fn.apply(this, args);
});

当您调用 apply 时,您给出了错误的 this 引用,因为您在 forEach 闭包中。

如果您想在 this 上提供 EventEmitter 实例引用,您需要将其存储在一个变量中并在闭包中使用它:

function EventEmitter() {
  var events = {};
  var that = this; // <-- Current instance reference!
  this.name = "Google"
  this.on = function(name, fn) {
    events[name] = events[name] || [];
    events[name].push(fn);
  }
  this.trigger = function(name, args) {
    events[name] = events[name] || [];
    args = args || [];
    events[name].forEach(function(fn) {
      fn.apply(that, args); // Provide "that" instead of "this"
    });
  }
}

forEach 有自己的上下文。使用 3 种方式之一绑定新上下文,例如:

events[name].forEach(function(fn) {
  fn.apply(this, args);
}.bind(this));

您还可以传递(作为 forEach 的第 2 个参数)上下文。回调的参数是 (value, index, originalArray, context);

events[name].forEach(function(fn) {
  fn.apply(this, args);
},this);