2012-05-01 57 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() 
});