0

キャンバスで使用する関数があります。関数で呼び出された間隔をクリアしようとしてい.animateますが、それを呼び出す.unbind(); と未定義のままログが記録され、タイムアウトをログに記録する必要がある場合、なぜそうでないのかわかりません働いている、多分あなたたちは助けることができます

function Character(model, srcX, srcY, srcW, srcH, destX, destY, destW, destH) {
    this.model  = model;
    this.srcX  = srcX;
    this.srcY  = srcY;
    this.srcW  = srcW;
    this.srcH  = srcH;
    this.destX = destX;
    this.destY = destY;
    this.destW = destW;
    this.destH = destH;
    this.timeout = undefined;

}

Character.prototype = {
    draw: function() {
        return ctx.drawImage(this.model, this.srcX, this.srcY, this.srcW, this.srcH,
                    this.destX, this.destY, this.destW, this.destH);
    },

    animate: function(claymation) {
        var top = this; <<<<<--------Set the this variable
        var queue = (function() {
            var that = this;
            var active = false;
            if (!this.active) {
                (function runQueue(i) {
                    that.active = true;
                    var length = claymation.length -1;      
    >>>>-Set the timeout    top.timeout = setTimeout(function() {
                        claymation[i].action();
                        if ( i < length ) {
                            runQueue(i + 1);
                            if (i === length - 1) {
                                that.active = false;
                            }
                        }
                    }, claymation[i].time);
                })(0);
            }
        })();
        return queue;
    },

    update: function(callback) {
        callback();
    },
    unbind: function() {
        console.log(this.timeout); < Logs undefined
        clearTimeout(this.timeout);
        console.log(this.timeout); < Also logs undefined?
    }
}

アップデート:

私はアンバインドを呼び出しています:

player = new Character(playerModel, 0, 130, 100, 100, 150, 150, 100, 100)
        if (e.which === 39) {
            player.unbind();
            key = undefined;
        }

完全なソース コード: https://github.com/Gacnt/FirstGame/blob/master/public/javascripts/superGame.js#L50-L77

4

2 に答える 2

3

あなたのanimate機能はめちゃくちゃです。呼び出しごと、関数ごとに変更されるため、追加の変数 ( 、など) にthis参照を格納する必要があることは既に確認しましたが、正しく実行できませんでした。thattop

var top = this;
var queue = (function() {
    var that = this;
    var active = false;
    if (!this.active) {
        // use
        that.active = true;
        // or
        top.timeout = …;
        // or
        that.active = false;
    }
})();

whiletopは正しくCharacter、メソッドを呼び出したインスタンスを参照しますが、そうでthatはありません。グローバル コンテキスト ( ) を参照します。これは、通常の (即時に) 呼び出される関数 (式) のwindowデフォルト値です。thisしたがって、this.active値もほとんどなく、timeoutプロパティは設定されません。また、IIFE はreturn何もしないことqueueに注意してくださいundefined

active代わりに、そのローカル変数を使用したいようです。あとはやるだけ!this「ローカル」のものを参照するためにJavaのようなキーワードを使用する必要はありません。変数はスコープチェーンの次のものであるため、使用されます。

完全にはわかりませんが、あなたが望んでいるようです

Character.prototype.animate = function(claymation) {
    var that = this; // variable pointing to context
    var active = false; // again, simple local variable declaration
    if (!active) {
       (function runQueue(i) {
            active = true; // use the variable
            var length = claymation.length -1;      
            that.timeout = setTimeout(function() { // use property of "outer" context
                claymation[i].action();
                if ( i < length ) {
                    runQueue(i + 1);
                    if (i + 1 === length) {
                        active = false; // variable, again!
                    }
                }
            }, claymation[i].time);
        })(0);
    }
};
于 2013-04-28T23:38:16.227 に答える
0

ベルギが言っていることは次のとおりです。

animate: function(claymation) {
    var top = this;

ここでは、インスタンスである this を参照するように top を設定します (Character のインスタンスであることがわかるように、これを character と呼びたいと思います)。次に、独自の実行コンテキストとthisの新しい値を持つ IIFE があります。

    var queue = (function() {
        var that = this;

ここでは、IIFE のthisが設定されています。これは設定されていないため、デフォルトでグローバル/ウィンドウ オブジェクトになるか、厳密モードの場合は未定義のままになります。

        var active = false;
        if (!this.active) {

したがって、ここではwindow.activeを取得していますが、これは最初は未定義である可能性が高いため、テストは true です。後で次のようにします。

            (function runQueue(i) {
                that.active = true;

window.activeaを true に設定します。また、あなたはやっています:

            (function runQueue(i) {
               ...
            })(0);

固定値を渡すだけの場合、IIFE は必要ありません。0どこでも使用iして IIFE を削除し、関数本体を使用するだけです。スコープ チェーンに余分なオブジェクトは必要ありません。

最後に、どちらの IIFE も何も返さないため、キューは未定義のままです。

    })();
    return queue;

値を返しudefinedます。

于 2013-04-29T00:19:03.307 に答える