我一直遇到奇怪的问题。经过研究后,我一直找不到他们的任何东西,所以我想来这里介绍他们。我有一个很长的课程,但我将包括相关的内容:
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();
}
}
到目前为止,如果我是手动(即从控制台)进行操作,则可以无限期地致电AnimatedSnake.next()
。但是,当我将函数放在一个间隔或超时中时-setInterval(AnimatedSnake.next, 100)
-突然,在第一次运行时就声称AnimatedSnake.erase is not a function
。我尝试将AnimatedSnake.erase()
直接放在间隔中,当我这样做时,由于某种荒谬的原因,它去了,并告诉我它不能采用AnimatedSnake.coordinates
的length属性,它声称是不确定的。在我的代码中没有任何地方可以重新定义这些内容。 coordinates
已更改,但在任何时候都不应未定义。 erase
当然是我永远不会改变的方法。有谁知道为什么用setInterval
或setTimeout
调用它们时会发生奇怪的事情,但是如果我重复调用这些函数(即使在for循环中)却没有JavaScript计时函数,那么一切都会正常进行精细?我真的很沮丧。
答案 0 :(得分:3)
考虑以下两个片段:
animatedSnake.next()
并且:
let method = animatedSnake.next;
method();
在第一个代码段中,next
被称为animatedSnake
对象的成员,因此this
方法上下文中的next
是指animatedSnake
对象
在第二个片段中,next
方法是与对象分离的,因此,this
不再引用animatedSnake
实例,而{{1} }函数被调用。这就是将方法传递给另一个函数(例如method
)的方式。您可以使用setInterval
方法手动设置上下文:
Function.prototype.bind
或用另一个函数包装语句:
setInterval(animatedSnake.next.bind(animatedSnake), 100)