2016-05-11 98 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

相關問題