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引用存储在一个额外的变量(that, top,无论什么)中,因为它从一个调用到另一个调用以及从一个函数到另一个函数发生变化,但是您没有正确地做到这一点。

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

虽然top是正确的,并且会引用Character您调用该方法的实例,但that绝对不是 - 它会引用全局上下文 ( window),这是正常(立即)调用的函数(表达式)中的默认this值。因此,this.active也几乎没有值,并且您的timeout属性没有被设置。另请注意,IIFE 没有return任何作用,queue因此undefined.

相反,您似乎想使用该局部active变量。那就去做吧!您不必使用一些类似 Javathis的关键字来引用“本地”变量 - 变量只是作用域链中的下一个,因此将使用它。

我不完全确定,但看起来你想要

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;

在这里,您设置 top 来引用 this,它是实例(我宁愿称它为 character 以便您知道它是 Character 的实例)。然后你有一个 IIFE,它有自己的执行上下文和this的新值:

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

这里设置了IIFE的this,没有设置所以默认为全局/窗口对象,或者如果在严格模式下,将保持未定义。

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

所以在这里你得到了window.active,这可能是第一次未定义的,所以测试是正确的。稍后你会这样做:

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

将 a 设置window.active为 true。另外,你正在做:

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

如果您只是传入一个固定值,则不需要 IIFE,只需0在您拥有的任何地方使用i并删除 IIFE,只需使用函数体,您就不需要作用域链上的那个额外对象。

最后,两个 IIFE 都没有返回任何东西,所以queue保持未定义,所以:

    })();
    return queue;

返回udefined值。

于 2013-04-29T00:19:03.307 回答