为什么“这个”不应该在这种情况下应该是什么?

时间:2013-04-28 23:20:49

标签: javascript prototype

我有一个我在画布上使用的函数,我正在尝试清除使用.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?
    }
}

更新

我打电话给unbind:

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

2 个答案:

答案 0 :(得分:3)

您的animate功能搞砸了。你已经看到有必要将this reference存储在一个额外的变量(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;
    }
})();

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

相反,您似乎想要使用该本地active变量。那就做吧!您不必使用某些Java - this - like关键字来引用“local” - 该变量只是范围链中的下一个,因此将使用它。

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

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

答案 1 :(得分:0)

Bergi所说的是:

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

在这里你设置top来引用它,这是实例(我宁愿称之为字符,所以你知道它是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;

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

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

如果你只是传递一个固定值,就没有任何需要IIFE,只需在0处使用i并移除IIFE,只需使用函数体,你就不应该在范围链上需要额外的对象。

最后,两个IIFE都没有返回任何内容,因此 queue 仍未定义,因此:

    })();
    return queue;

返回udefined值。