【问题标题】:Object in Javascript undefined when calling a method调用方法时未定义Javascript中的对象
【发布时间】:2020-05-09 19:27:20
【问题描述】:

我正在构建一个类似于 Vanilla JS 中的 Chrome 恐龙的游戏。为了使障碍物动画化,我创建了一个 Obstacle 类,它存储了它们的位置和大小,并定义了一个改变位置的方法。

var Obstacle = function (type, w, h, sprite) {
    this.h = h;                    // Obstacle height
    this.w = w;                    // Obstacle width
    this.x = 600;                    // Starting horizontal position
    this.y = GROUND - this.h;           // Starting vertical position
    this.type = type;
    this.sprite = sprite;
    this.speed = -4;

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

这些存储在一个数组中,定义为不同类的属性:

var ObstacleBuffer = function () {

    this.bufferFront = [];

    this.createObstacle = function () {
        this.bufferFront.push(this.createBox());
    }
    // Obstacle creators
    this.createBox = function () {
        if (Math.random() < 0.5) return new Obstacle ("box1", OBSTACLES.box1.w, OBSTACLES.box1.h, OBSTACLES.box1.sprite);
        return new Obstacle ("box2", OBSTACLES.box2.w, OBSTACLES.box2.h, OBSTACLES.box2.sprite);
    }

    //Obstacle animation
    this.animateObstacle = function () {
        this.bufferFront[0].move();
    }
}

运行时会弹出一个错误:

TypeError: Cannot read property 'move' of undefined.

我记录了this.bufferFront[0] 的内容,它正确显示了其中存储的Obstacle

我还尝试将this.bufferFront[0] 在本地分配给一个变量,然后尝试从那里调用该方法。存储的数据是正确的,但每次尝试访问Obstacles 方法或属性时都会弹出错误。

有什么想法吗?非常感谢你。

编辑 - 我已根据您的建议查看了代码,问题似乎出在我调用该函数的地方。在生成障碍物之前,我预加载了一系列图像,并且只有在这些图像加载后才生成障碍物:

this.loadWhenReady = function () {
        if (self.resources.isLoadComplete()) {
            self.sound.load(self.resources.list.sfx);
            drawGround();
            this.obstacles.createObstacle();  // <--
            self.startGame();
            return;
        } else {
            setTimeout(self.loadWhenReady, 300);
        }
    }

这被称为:

setTimeout(self.loadWhenReady, 300);

当然 const self = this 之前已经定义过了。

当在SetTimeout 之外调用该方法时,一切似乎都在向前发展。

为什么会发生这种情况?有没有办法在调用那里的方法时解决这个问题?

已解决 - 正如@Bergi 和@Jaime-Blandon 所说,这是一个上下文问题。从 setTimeout 循环外部调用该方法或使用 self.obstacle.createObstacle() 而不是 this.obstacle.createObstacle() 可以解决问题。

【问题讨论】:

  • "运行时" - 请向我们展示运行这些构造函数和方法的代码
  • 感谢您的评论。事实上,我已经改变了调用该方法的方式,它肯定会产生一些结果。我已经相应地编辑了我的原始帖子。
  • 您在loadWhenReady 中使用this.obstacles 而不是self.obstacles?阿苏,你在哪里打电话animateObstacle
  • 再次感谢您的回复!这正是问题所在。我没有使用self.obstacles。无论如何,为了安全起见,并且由于我不需要从该特定循环内部调用该方法,因此我将其移至代码中的外部行:更清洁,更安全。感谢您的评论并尝试 @Jaime-Blandon 建议我能够跟踪问题。不过,我不知道如何将您的评论标记为“有效解决方案”。无论如何,非常感谢您的帮助!!
  • 奇怪的是,这并没有在loadWhenReady 中引起异常。你(不小心)有一个全局变量 (window.)obstactles 吗?

标签: javascript arrays javascript-objects


【解决方案1】:

在 ObstacleBuffer 类上尝试此更改:

var ObstacleBuffer = function () {

    this.bufferFront = [];

    this.createObstacle = function () {
        //this.bufferFront.push(this.createBox());
        this.createBox();
    }
    // Obstacle creators
    this.createBox = function () {
        if (Math.random() < 0.5) this.bufferFront.push(new Obstacle ("box1", OBSTACLES.box1.w, OBSTACLES.box1.h, OBSTACLES.box1.sprite));            
        this.bufferFront.push(new Obstacle ("box2", OBSTACLES.box2.w, OBSTACLES.box2.h, OBSTACLES.box2.sprite));
    }

    //Obstacle animation
    this.animateObstacle = function () {
        this.bufferFront[0].move();
    }
}

最好的问候!

【讨论】:

  • 感谢您更改为编辑。如果您知道,请解释为什么这会解决问题中的问题
  • previos return "new Obstacle..." 刚刚在它自己的上下文中结束,并且实例化后的缓冲区刚刚运行到一个空数组中,现在你强制数组将障碍物保留在内存中并且move 方法将可用
  • 感谢您的回复,但更改后调用 move() 会产生相同的错误。
  • 编辑——我又跑了一次,这肯定与上下文有关。事实上,我改变了调用该方法的方式,它在再次中断之前突然起作用了。我已经相应地编辑了我的原始代码。
  • 你强制数组将障碍物保留在内存中” - 这根本没有意义。您答案中的代码与问题中的代码没有什么不同。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-10-02
  • 2015-03-26
  • 2020-08-03
  • 1970-01-01
  • 1970-01-01
  • 2016-01-30
  • 1970-01-01
相关资源
最近更新 更多