2016-05-11 55 views
5

我有两个对象实例,它们扩展了EventEmitter并侦听了一个名为finish的事件。如果我在构造函数外部设置事件处理函数,所有方面都按预期工作。每个实例都会听到它触发的finish的发生。但是如果我在构造函数中设置了事件处理函数,那么只有第二个创建的实例会听到并且对事件作出反应,或者看起来如此。构造函数中的事件处理函数与构造函数中的事件处理函数行为不同

下面是代码:

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 

注意,LISTENER ID为建立内MyEmitter构造函数总是属于第二创建的实例事件处理程序的版本,使得它看起来该实例总是首先捕获事件,并且由于某种原因,第一个创建的实例从未触发该处理程序。

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

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

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

这让我想到了另外一件事情:事件是否应始终由发出事件的EventEmitter“听到”?这就是我的想法,当然这似乎是最常见的用例。但是,如果这不是一个限制,例如,按钮上的某个事件如何不触发所有其他按钮的点击处理程序?

回答

6

问题是您没有使用var self = this;self变量固定到发射器范围。当您离开var时,Javascript会将变量提升到范围内,直到找到与var一致的变量名称。由于您从未宣布过,所以self将一直托管到全球范围,因此每个发射器都将使用相同的参考创建。

添加var self = this将解决问题。您还可以添加use strict来捕捉这些类型的问题,因为它不允许您在不使用var的情况下声明变量。

+0

简直不敢相信我是多么的愚蠢。正试图在某人的旧代码中解决这个问题,并且看起来太深了。完全错过了自我面前的缺乏。谢谢! – spectorar

相关问题