为什么'this'在这种情况下不应该是这样

Why is 'this' not what it should be in this context?

本文关键字:不应该 this 为什么 这种情况下      更新时间:2023-09-26

我有一个我在画布上使用的函数,我试图清除一个与.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 on:

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

您的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变量。那就去做吧!您不必使用一些类似Java- this的关键字来引用"本地"变量—变量只是作用域链中的下一个,因此将使用它。

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

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

Bergi的意思是:

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

这里你设置top引用this,这是一个实例(我宁愿叫它character,这样你就知道它是character的一个实例)。然后你有一个IIFE,它有自己的执行上下文和一个新值this:

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

这里that被设置为IIFE的this,它没有被设置,因此将默认为全局/window对象,或者如果处于严格模式,将保持未定义。

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

这里你得到了窗口。活动,第一次可能未定义,因此测试为真。之后你做:

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

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

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

如果你只是传递一个固定的值,就不需要IIFE,只要在有i的地方使用0并删除IIFE,只使用函数体,你不应该在作用域链上需要额外的对象。

最后,两个iife都没有返回任何东西,所以queue仍然是未定义的,所以:

    })();
    return queue;

返回udefined的值