0

Javascript のスコープ規則を理解しているとは思えないため、助けを求めています。以下の例で私がやろうとしているのは、ページ上のボタンを押して、キーボード入力のリッスンを開始することです。2 秒間入力が中断された場合にキーボード入力が開始されたら、入力のキャプチャを停止し、その時点までに収集された入力の完全な内容でアラートをポップしたいと考えています。これは、この質問のために純粋に作成した例です。

私が見ているのは、ボタンをクリックして入力を開始することです。キーを押すたびに、その時点までに収集された文字列が通知されます。2 秒間アクションなしのタイムアウトが発生した後、内容が「未定義」のアラートが表示されます。上記の最初のアラートは、startLog() からのものです。2 番目のアラートは、stopLog() から発生します。this.message が未定義であることを教えてくれる stopLog を呼び出すと、何が間違っていますか?

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();
});
4

2 に答える 2

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()
});
于 2012-05-01T17:04:50.433 に答える
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
    });
};
于 2012-05-01T16:50:49.297 に答える