gpt4 book ai didi

javascript - 较大对象中的 this.objectName 在执行期间变为未定义

转载 作者:行者123 更新时间:2023-12-02 20:58:31 25 4
gpt4 key购买 nike

我使用 HTML Canvas 创建了一个项目,它运行良好。一开始是这样的:

let canvas = document.querySelector('canvas');

canvas.width = window.innerWidth;
canvas.height = window.innerHeight;

let ctx = canvas.getContext('2d');

function Line(x, y, context, length, speed) {
this.x = x;
this.y = y;
this.ctx = context;
this.length = length;
this.speed = speed;
this.isDrawingNow = false;
this.initialCoordinates = {
x: this.x,
y: this.y
}
console.log(this.initialCoordinates);

this.ctx.beginPath();
this.ctx.moveTo(this.x, this.y);

this.draw = function() {
this.ctx.lineTo(this.x, this.y);
this.ctx.stroke();
}

this.updateRight = function() {
this.x += this.speed;
this.draw();
}

// Same functions as the above one, but for the other directions
}

let line = new Line(50, 50, ctx, 30, 1);

function animateRight() {
if (line.initialCoordinates.x + line.length <= canvas.width) {
line.isDrawingNow = true;
if (line.x < line.initialCoordinates.x + line.length) {
requestAnimationFrame(animateRight);
line.updateRight();
} else {
line.initialCoordinates.x = line.x;
line.isDrawingNow = false;
}
}
}

// Same functions as the above one, but for left, up, down directions

window.addEventListener('keydown', keyDown); // Event listener for the arrow keys

function keyDown(e) {
if (e.key === 'ArrowLeft' && !line.isDrawingNow) {
animateLeft();
} else if (e.key === 'ArrowRight' && !line.isDrawingNow) {
animateRight();
// the other keys
}
}

然后我认为我必须在 Line 对象中包含 animateRight() (animateDirection 函数)。我这样做了:

// Same as the old object plus:
this.animateRight = function() {
console.log(this.initialCoordinates);
if (this.initialCoordinates.x + this.length <= canvas.width) {
this.isDrawingNow = true;
if (this.x < this.initialCoordinates.x + this.length) {
requestAnimationFrame(this.animateRight);
this.updateRight();
} else {
this.initialCoordinates.x = this.x;
this.isDrawingNow = false;
}
}
}

// The other directions...
// Now I have to call the animateDirection on arrowkey press like this (line is the new Line):

function keyDown(e) {
if (e.key === 'ArrowLeft' && !line.isDrawingNow) {
line.animateLeft();
} else if (e.key === 'ArrowRight' && !line.isDrawingNow) {
line.animateRight();
}

不幸的是,新代码不起作用,当我按右箭头时,我收到错误“this.initialCooperatives 未定义”。我使用firefox调试器找到了问题所在。我看到 animateRight 被调用一次,requestAnimationFrame 再次调用 animateRight,但是这次 this.initialCooperatives 未定义,this.length 相同,因此程序停止。我不明白有什么问题。请帮我!我是面向对象编程的新手...

最佳答案

在 JavaScript 中,this 的值取决于函数的调用方式。如果函数像方法一样被调用,obj.func()this将是obj。如果函数正常调用,func()this将是undefined(或者非严格模式下的全局对象)。

您正在将一个函数 (this.animateRight) 传递给 requestAnimationFrame,它像普通函数一样调用该函数,因此在其中,this无法正常工作。

在 JS 的旧时代,通常通过将 this 分配给变量(通常称为 self)来解决这个问题。不过,现在有更好的方法来解决这个问题:

1。 Arrow funtions

箭头函数是上述 this 规则的一个异常(exception)。它们从定义它们的范围中获取值。

// [...]
if (this.x < this.initialCoordinates.x + this.length) {
requestAnimationFrame(() => {
this.animateRight();
});
this.updateRight();
} else {
// [...]

2。 Function.prototype.bind()

函数的bind方法返回一个新函数,该函数将使用指定的this值调用该函数。 (将函数中的 this 绑定(bind)到指定值。)

// [...]
if (this.x < this.initialCoordinates.x + this.length) {
requestAnimationFrame(this.animateRight.bind(this));
this.updateRight();
} else {
// [...]

这种方法不如箭头函数灵活,因为只能直接调用一个函数。

关于javascript - 较大对象中的 this.objectName 在执行期间变为未定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61410727/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com