构造函数中的事件处理程序与构造函数之外的事件处理程序的行为不同

我有一个扩展EventEmitter的对象的两个实例,并监听一个名为finish的事件。 如果我在构造函数外部设置事件处理程序,一切都按预期工作。 每个实例都会听到它触发的finish的发生。 但是,如果我在构造函数中设置了事件处理程序,那么只有第二个创build的实例才会听到该事件,并对事件做出反应。

这里是代码:

 var util = require('util'); var EventEmitter = require('events').EventEmitter; var fs = require('fs'); var NEXT_ID = 0; var MyEmitter = function() { EventEmitter.call(this); this.id = NEXT_ID; NEXT_ID++; console.log('CREATED EMITTER WITH ID:', this.id) self = this; this.on('finish', function() { console.log('FINISH EVENT . CONSTRUCTOR LISTENER .', 'LISTENER ID:', self.id, '. ORIGINATOR ID:', this.id); }); }; util.inherits(MyEmitter, EventEmitter); var setFinishListener = function(emitter) { emitter.on('finish', function() { console.log('FINISH EVENT . NON-CONSTRUCTOR LISTENER .', 'LISTENER ID:', emitter.id, '. ORIGINATOR ID:', this.id); }); } var emitter0 = new MyEmitter(); var emitter1 = new MyEmitter(); setFinishListener(emitter0); setFinishListener(emitter1); emitter0.emit('finish'); emitter1.emit('finish'); // The following is logged to the console: // FINISH EVENT . CONSTRUCTOR LISTENER . LISTENER ID: 1 . ORIGINATOR ID: 0 // FINISH EVENT . NON-CONSTRUCTOR LISTENER . LISTENER ID: 0 . ORIGINATOR ID: 0 // FINISH EVENT . CONSTRUCTOR LISTENER . LISTENER ID: 1 . ORIGINATOR ID: 1 // FINISH EVENT . NON-CONSTRUCTOR LISTENER . LISTENER ID: 1 . ORIGINATOR ID: 1 

请注意,在MyEmitter构造函数中设置的事件处理函数版本的LISTENER ID总是属于第二个创build的实例,看起来这个实例总是首先捕获事件,由于某种原因,第一个创build的实例从来没有处理器触发。

我假设我理解正确的两个事实:

  1. 事件处理程序中的this应该始终是发送事件的对象。
  2. this在构造函数中应该始终是构造函数返回的对象(因为它是用new来调用的)。

如果这两个都是真的,我不知道还有什么我不理解的结果在展出的行为。

还有一件事情让我想到:一个事件是否总是被发出事件的EventEmitter“听到”? 这是我的想法,当然这似乎是最常见的用例。 但是,如果这不是一个限制,那么如何在一个button上的click事件不会触发所有其他button的点击处理程序?

问题是你没有使用var self = this;selfvariables固定到“发射器”范围。 当你离开这个var ,Javascript会把这个variables提升到范围内,直到find一个用var声明的variables名。 既然你从来没有宣布过,那么self将一直被托pipe到全球的范围,因此每个发射器都将被创build为具有相同的参考。

添加var self = this将解决问题。 您还可以添加use strict来捕获这些types的问题,因为它不会允许您声明一个variables而不使用var