You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript报错:this.Update不是函数,已定义类成员仍出问题

解决JavaScript中setInterval导致的this指向错误

我不常使用JavaScript,但想要制作网页浏览器游戏,于是开发了一个平台游戏框架,编写了可被继承创建游戏的Project类:

export class Project {
    constructor() {
        this.player = new Player(new Vec2(16, 16));
        this.level  = new Level(100, 100);

        // create a canvas
        let canvas = document.createElement("canvas");
        canvas.setAttribute("id", "gameCanvas");
        document.body.appendChild(canvas);
    }
    UpdateCanvas() {
        let canvas = document.getElementById("gameCanvas");
        canvas.width  = window.innerWidth;
        canvas.height = window.innerHeight;
    }
    Start() {}
    Update() {}
    DoFrame() {
        this.Update();

        // render
        const canvas = document.getElementById("gameCanvas");
        const ctx    = canvas.getContext("2d");

        ctx.fillStyle = "#00ff00";
        ctx.fillRect(this.player.pos.x, this.player.pos.y, this.player.hitbox.x, this.player.hitbox.y);
    }
    Run() {
        this.Start();
        setInterval(this.DoFrame, 1000 / 60);
        setInterval(this.UpdateCanvas, 1000 / 5);
    }
}

随后编写了继承自Project类的YJump类:

class YJump extends Project {
    constructor() {
        super();
    }
    Start() {
        console.log("Game started");
    }
    Update() {
        
    }
}

运行时DoFrame方法第一行this.Update();出现如下报错:

engine.js:143 Uncaught TypeError: this.Update is not a function
    at DoFrame (engine.js:143:8)

问题原因

这个错误不是继承导致的,而是setInterval调用函数时改变了this的指向。当你直接把this.DoFrame和this.UpdateCanvas传给setInterval时,函数会脱离原实例的作用域执行,此时this指向全局对象(非严格模式下为window),自然找不到属于Project实例的Update方法。

解决方法

方法1:使用箭头函数绑定this

箭头函数会继承外层作用域的this,确保函数执行时指向当前游戏实例:

Run() {
    this.Start();
    setInterval(() => this.DoFrame(), 1000 / 60);
    setInterval(() => this.UpdateCanvas(), 1000 / 5);
}

方法2:使用bind显式绑定this

通过bind方法将函数的this固定为当前实例:

Run() {
    this.Start();
    setInterval(this.DoFrame.bind(this), 1000 / 60);
    setInterval(this.UpdateCanvas.bind(this), 1000 / 5);
}

方法3:在构造函数中提前绑定方法

在Project的构造函数里提前完成方法的this绑定,避免每次调用Run时重复绑定:

export class Project {
    constructor() {
        this.player = new Player(new Vec2(16, 16));
        this.level  = new Level(100, 100);

        // 提前绑定this到当前实例
        this.DoFrame = this.DoFrame.bind(this);
        this.UpdateCanvas = this.UpdateCanvas.bind(this);

        // create a canvas
        let canvas = document.createElement("canvas");
        canvas.setAttribute("id", "gameCanvas");
        document.body.appendChild(canvas);
    }

    // ... 其他方法保持不变

    Run() {
        this.Start();
        setInterval(this.DoFrame, 1000 / 60);
        setInterval(this.UpdateCanvas, 1000 / 5);
    }
}

内容的提问来源于stack exchange,提问作者MESYETI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 15:25:14