2012-05-01 58 views
0

我正在尋找一些幫助,因爲我不太認爲我理解Javascript範圍規則。我在下面的例子中試圖做的是按下頁面上的一個按鈕,然後開始監聽鍵盤輸入。一旦鍵盤輸入已經開始,如果輸入中斷了兩秒鐘,我想停止捕捉輸入,並彈出一個警報,其中收集到的輸入的全部內容都顯示在該點上。這是我純粹爲這個問題做的一個例子。Javascript對象方法和綁定函數

我看到的是我點擊按鈕並開始輸入輸入。在每次按鍵時,我都會收到關於收集到的字符串的警報。兩秒鐘後,無動作超時發生,我看到一個警告,內容「未定義」。上面列出的第一個警報來自startLog()。第二個警報來自stopLog()。當我調用stopLog時,我做錯了什麼,它告訴我this.message是未定義的?

function Logger() { 
    this.message = ''; 
    this.listenTimer; 

    this.startLog = function() { 
     this.message = ''; 
     $(document).bind('keypress', {this_obj:this}, function(event) { 
      event.preventDefault(); 
      var data = event.data; 
      clearTimeout(data.this_obj.listenTimer); 
      data.this_obj.message += String.fromCharCode(event.which); 
      alert(data.this_obj.message); 
      data.this_obj.listenTimer = setTimeout(data.this_obj.stopLog, 2000); 
     }); 
    }; 

    this.stopLog = function() { 
     $(document).unbind("keypress"); 
     alert(this.message); 
    }; 
} 

var k = new Logger(); 
$('.logging-button').click(function() { 
    k.startLog(); 
}); 

回答

0

問題是this。當您將對象方法作爲事件處理程序傳遞時,它會丟失其對象上下文; this將引用window對象。

有不同的方法來解決這個問題,但主要的問題是,你需要傳遞setTimeout封閉,將仍然指向正確的上下文:

setTimeout(function() { data.this_obj.stopLog() }, 2000); 

在一個單獨的說明,您可以保存自己通過只使用一個關閉一些不必要的代碼來引用的對象,而不是結合它作爲event.data

this.startLog = function() { 
    this.message = ''; 
    var this_obj = this; 
    $(document).bind('keypress', function(event) { 
     event.preventDefault(); 
     clearTimeout(this_obj.listenTimer); 
     // etc 
    }); 
}; 
+0

非常感謝您的答案和提示。我的代碼現在運行並看起來更清晰。 – rebekswr

0
var k = new Logger(); 

$('.logging-button').click(function() { 
    k.startLog.apply(this); 
    //Setting context of "this" so that it refers to element even in startLog() 
});