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

JavaScript类与模块练习代码异常,请求故障排查帮助

JavaScript类与模块练习故障排查求助

我正在做一个涉及JavaScript类的练习,完全照着示例写代码却无法正常运行,求帮忙找出问题并解释,谢谢。

我的代码文件

Modules.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>classes and modules</title>
    <link rel="stylesheet" href="stylesheet.css">
    <script src="moduleScript.js" type="module" defer></script>
</head>
<body>
    <h1>Classes and Modules</h1>
    <canvas id="canvas" width="250" height="150"></canvas>
</body>
</html>

thing.js

export default class Thing {
    constructor(x, y, size, hue) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.fillStyle = `hsl(${hue}, 30%, 60%)`;
        this.angle = angle;
        this.rotationRate = 0;
        this.speed = 100;
    }
    
    get xSpeed() {
        return Math.cos(this.angle) * this.speed;
    }
    get ySpeed() {
        return Math.sin(this.angle) * this.speed;
    }

    update(elapsed) {
        this.rotattionRate += (Math.random() - 0.5);
        this.rotationRate = Math.max(this.rotationRate, -2 * Math.PI);
        this.rotationRate = Math.min(this.rotationRate, 2 * Math.PI);
        this.angle += this.rotationRate * elapsed;
        this.x += this.xSpeed * elapsed;
        this.y += this.ySpeed * elapsed;
    }

    draw(ctx) {
        ctx.save();
        ctx.fillStyle = this.fillStyle;
        ctx.translate(this.x, this.y);
        ctx.rotate(this.angle);
        ctx.beginPath();
        ctx.arc(0, 0, this.size/2, Math.PI / 2, 1.5 * Math.PI)
        ctx.lineTo(this.size, 0);
        ctx.restore();
    }
}

follower.js

export default class Follower {
    constructor(x, y, speed, target) {
        this.target = target;
        this.speed = speed;
        this.x = x;
        this.y = y;
    }
    
    get angle() {
        const dy = this.target.y - this.y;
        const dx = this.target.x - this.x;
        return Math.atan2(dy, dx);
    }

    get xSpeed() {
        return Math.cos(this.angle) * this.speed;
    }

    get ySpeed() {
        return Math.sin(this.angle) * this.spped;
    }

    update(elapsed) {
        this.x += this.xSpeed * elapsed;
        this.y += this.ySpeed * elapsed;
    }

    draw(ctx) {
        ctx.save();
        ctx.strokeStyle = this.target.fillStyle;
        ctx.lineWidth = 2;
        ctx.translate(this.x, this.y);
        ctx.rotate(this.x, this.y);
        ctx.beginPath();
        ctx.moveTo(-10, 0);
        ctx.lineTo(10, 0);
        ctx.moveTo(5, -5);
        ctx.lineTo(10, 0);
        ctx.lineTo(5, 5);
        ctx.stroke();
        ctx.restore();
    }
}

scene.js

import Thing from './thing.js';
import Follower from './follower.js';

export default class Scene {
    constructor(nThings, canvas) {
        this.things = Array.from({length: nThings}, () => {
            return new Thing(
                Math.random() * canvas.width,
                Math.random() * canvas.height,
                20 + Math.random() * 10,
                Math.random() * 360, 
                Math.random() * 2 * Math.PI
            );
        });
        this.followes = this.things.map((thing) => {
            return new Follower(
                canvas.width / 2,
                canvas.height / 2,
                thing.speed / 2, thing
            );
        });
    }
    
    draw(ctx) {
        ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas,height);
        this.followers.forEach(thing => {
            thing.draw(ctx);
        });
        this.things.forEach(things => {
            thing.draw(ctx);
        });
    }

    update (elapsed) {
        this.things.forEach(thing => {
            thing.update(elapsed);
        });
        this.followers.forEach(thing => {
            thing.update(elapsed);
        });
    }
}

moduleScript.js

import Scene from './scene.js';

const ctx = canvas.getContext("2d");
const scene = new Scene(100, canvas);

let p;
function frame(ts) {
    const elapsed = ts - p || 0;
    scene.update(elapsed / 1000);
    scene.draw(ctx);
    p = ts;
    requestAnimationFrame(frame);
} 
requestAnimationFrame(frame);

stylesheet.css

body {
    background: #ffffff;
    color: #d6d6d6;
    font-family: monospace;
    max-width: auto;
}
canvas {
    background: #a1a1a1;
    width: 100%;
}

代码中的问题及修复方案

1. thing.js 中的错误

  • 参数缺失与未定义变量:constructor 里使用了未定义的 angle 参数,需要在构造函数参数列表中添加 angle 并赋值:
    constructor(x, y, size, hue, angle) {
        this.x = x;
        this.y = y;
        this.size = size;
        this.fillStyle = `hsl(${hue}, 30%, 60%)`;
        this.angle = angle;
        this.rotationRate = 0;
        this.speed = 100;
    }
    
  • 拼写错误:update 方法中 this.rotattionRate 应为 this.rotationRate:
    this.rotationRate += (Math.random() - 0.5);
    
  • 未填充图形:draw 方法中绘制路径后需调用 ctx.fill() 才能显示图形:
    ctx.beginPath();
    ctx.arc(0, 0, this.size/2, Math.PI / 2, 1.5 * Math.PI);
    ctx.lineTo(this.size, 0);
    ctx.fill(); // 新增
    ctx.restore();
    

2. follower.js 中的错误

  • 拼写错误:ySpeed getter 中 this.spped 应为 this.speed:
    get ySpeed() {
        return Math.sin(this.angle) * this.speed;
    }
    
  • rotate 参数错误:draw 方法中 ctx.rotate(this.x, this.y) 错误,rotate 仅接受角度参数,应改为:
    ctx.rotate(this.angle);
    

3. scene.js 中的错误

  • 属性名拼写错误:constructor 中 this.followes 应为 this.followers:
    this.followers = this.things.map((thing) => {
        // ...
    });
    
  • clearRect 参数错误:draw 方法中 ctx.clearRect 的最后一个参数多了逗号,应为:
    ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    
  • forEach 变量名不匹配:遍历 this.things 时参数名与内部使用的变量名不一致,需统一:
    this.things.forEach(thing => {
        thing.draw(ctx);
    });
    

4. moduleScript.js 中的错误

  • 未获取 canvas 元素:直接使用 canvas 变量前需先从 DOM 中获取:
    const canvas = document.getElementById('canvas');
    const ctx = canvas.getContext("2d");
    
  • 初始时间变量未定义:第一次执行 frame 时 p 为 undefined,导致时间计算错误,修改逻辑:
    let p;
    function frame(ts) {
        const elapsed = p ? ts - p : 0;
        scene.update(elapsed / 1000);
        scene.draw(ctx);
        p = ts;
        requestAnimationFrame(frame);
    } 
    

修复后效果

修复以上所有错误后,代码可正常运行:彩色扇形物体会随机旋转移动,小箭头会跟随对应物体移动。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 17:14:57