Javascript I';我在setInterval和class方法方面遇到了很多麻烦

Javascript I';我在setInterval和class方法方面遇到了很多麻烦,javascript,Javascript,我总是遇到奇怪的问题。在做了一些研究之后,我找不到关于它们的任何东西,所以我想我应该来这里展示它们。我有一个相当长的课程,但我将包括相关的部分: class AnimatedSnake { constructor(canvasId, coordinates) { this.coordinates = coordinates; this.direction = 2; this.ctx = document.getElementById(canvasId).getCon

我总是遇到奇怪的问题。在做了一些研究之后,我找不到关于它们的任何东西,所以我想我应该来这里展示它们。我有一个相当长的课程,但我将包括相关的部分:

class AnimatedSnake {

constructor(canvasId, coordinates) {

    this.coordinates = coordinates;
    this.direction = 2;

    this.ctx = document.getElementById(canvasId).getContext("2d");

    // 0 - .99, describes how far along snake is between coordinates
    this.progress = 0;
}

erase() {
    for (let i = 0; i < this.coordinates.length; i++) {
        let c1 = this.coordinates[i][0],
            c2 = this.coordinates[i][1];
        this.ctx.clearRect(c1 * 31, c2 * 31, 31, 31);
    }
}

next() {
    this.progress += 0.01;

    if (this.progress >= 1) {
        this.progress %= 1;

        let nextCoord = this.coordinates[4].slice();
        nextCoord[0] += ((this.direction % 2) * this.direction);
        nextCoord[1] += ((!(this.direction % 2) * (this.direction / 2)));
        this.coordinates.push(nextCoord);
        this.coordinates.shift();
    }
    console.log(this.erase);
    this.erase();
    this.draw();

}

}
class AnimatedSnake{
构造函数(canvasId,坐标){
这个。坐标=坐标;
这个方向=2;
this.ctx=document.getElementById(canvasId.getContext(“2d”);
//0-.99,描述了蛇在坐标之间的距离
这个进度=0;
}
抹去{
for(设i=0;i=1){
这1.3%=1;
设nextcord=this.coordinates[4].slice();
下一个命令[0]+=((this.direction%2)*this.direction);
下一个命令[1]+=((!(this.direction%2)*(this.direction/2));
这个.coordinates.push(下一个命令);
this.coordinates.shift();
}
console.log(this.erase);
这个;
这个.draw();
}
}

到目前为止,如果我手动(即从控制台)调用
AnimatedSnake.next()
,我可以无限期地调用它。但是,当我将函数置于间隔或超时状态时-
setInterval(AnimatedSnake.next,100)
,在第一次运行时,它突然声称
AnimatedSnake.erase不是一个函数。我尝试将
AnimatedSnake.erase()
直接放在间隔中,当我这样做时,出于某种荒谬的原因,它会告诉我它不能接受
AnimatedSnake.coordinates
的长度属性,它声称该属性未定义。在我的代码中,没有任何地方可以重新定义这些东西<代码>坐标
已更改,但不应在任何点取消定义。当然,
erase
是一种我永远不会改变的方法。有人知道为什么用
setInterval
setTimeout
调用这些函数时会发生奇怪的事情,但是如果我在没有JavaScript计时函数的情况下重复调用这些函数(即使是在for循环中),一切都会正常进行吗?我真的被难住了。

想想这两个片段:

animatedSnake.next()
以及:

在第一个片段中,
next
被称为
animatedSnake
对象的一个成员,因此
next
的上下文中,此
方法引用
animatedSnake
对象

在第二个代码段中,
next
方法与对象分离,因此调用
方法
函数时,此
不再引用
animatedSnake
实例。这就是如何将一个方法传递给另一个函数,如
setInterval
。您可以使用
Function.prototype.bind
方法手动设置上下文:

setInterval(animatedSnake.next.bind(animatedSnake), 100)
或使用另一个函数包装语句:

setInterval(() => animatedSnake.next(), 100)

当您将函数传递给
setIntverval
时,您会失去绑定
的上下文,因为它只传递函数引用。您可以尝试
setInterval(()=>AnimatedSnake.next,100)
setInterval(AnimatedSnake.next.bind(AnimatedSnake),100)
为函数调用保留正确的上下文。AnimatedSnake的实例在哪里?它们不是用作
动画snake的静态方法。接下来
@sajalpreetsin我有一个实例,我只是觉得我不需要显式地显示一个来描述我的问题。不用担心:)我将把它包装在另一个函数中-我可能在调试时就应该想到这一点,但我仍然很高兴我问了这个问题,因为我没有意识到回调将方法与对象/类分离。谢谢你的解释@ElleNolan不客气!由于主题是
this
关键字,我想您可能会发现这个问题的答案很有用:
setInterval(() => animatedSnake.next(), 100)