web-dev-qa-db-ja.com

オブジェクトプロトタイプメソッド内のsetInterval / setTimeout内で「this」を参照する

通常、setInterval内で「this」を参照するときは、代替の「自己」参照を割り当てます。プロトタイプメソッドのコンテキスト内で同様のことを達成することは可能ですか?次のコードエラー。

function Foo() {}
Foo.prototype = {
    bar: function () {
        this.baz();
    },
    baz: function () {
        this.draw();
        requestAnimFrame(this.baz);
    }
};
33
Huck

Pythonのような言語とは異なり、JavaScriptメソッドは、それを抽出して別の場所に渡した後、それがメソッドであることを忘れます。あなたはどちらか

匿名関数内でメソッド呼び出しをラップする

このようにして、bazプロパティへのアクセスと呼び出しが同時に行われます。これは、thisがメソッド呼び出し内で正しく設定されるために必要です。

内部関数は別のthisオブジェクトを参照するため、外部関数のthisをヘルパー変数に保存する必要があります。

var that = this;
setInterval(function(){
    return that.baz();
}, 1000);

ファットアロー関数内でメソッド呼び出しをラップする

矢印関数 機能を実装するJavascript実装では、太矢印の構文を使用することにより、上記のソリューションをより簡潔な方法で記述できます。

setInterval( () => this.baz(), 1000 );

ファットアローの匿名関数は、周囲の関数のthisを保持するため、var that = thisトリックを使用する必要はありません。この機能を使用できるかどうかを確認するには、 これ のような互換性の表を参照してください。

バインディング関数を使用する

最後の代替手段は、Function.prototype.bindなどの関数またはお気に入りのJavaScriptライブラリの同等の関数を使用することです。

setInterval( this.baz.bind(this), 1000 );

//dojo toolkit example:
setInterval( dojo.hitch(this, 'baz'), 100);
66
hugomg

私はプロキシクラスを作りました:)

function callback_proxy(obj, obj_method_name)
{
    instance_id = callback_proxy.instance_id++;
    callback_proxy.instances[instance_id] = obj;
    return eval('fn = function() { callback_proxy.instances['+instance_id+'].'+obj_method_name+'(); }');
}
callback_proxy.instance_id = 0;
callback_proxy.instances = new Array();

function Timer(left_time)
{
    this.left_time = left_time; //second
    this.timer_id;

    this.update = function()
    {
        this.left_time -= 1;

        if( this.left_time<=0 )
        {
            alert('fin!');
            clearInterval(this.timer_id);
            return;
        }
    }

    this.timer_id = setInterval(callback_proxy(this, 'update'), 1000);
}

new Timer(10);
0
gloryonjesus