TypeScript类循环引用报错:exports is not defined 求助
解决TypeScript循环实例化类时的exports未定义错误
问题根源
你的代码存在两个核心问题:
- 循环导入+提前实例化:GamePanel和Player互相导入,且GamePanel在类属性定义阶段就直接实例化Player,此时GamePanel的实例还未完成构造,模块加载时会出现循环引用死锁。
- 模块编译目标不兼容浏览器:TypeScript默认编译为CommonJS模块,浏览器原生不支持
exports/require语法,因此抛出exports is not defined错误。
修复步骤
1. 解决循环依赖与实例化时机问题
- 不要在类属性初始化阶段直接创建Player实例,移到GamePanel的构造函数中执行,确保实例已完成基础属性初始化。
- 对Player中的GamePanel引用使用类型导入(
import type),因为这里仅用它做类型校验,不需要运行时的模块引用,避免循环加载。
修改后的代码:
GamePanel.ts
import { Player } from "./Player"; export class GamePanel { canvas: HTMLCanvasElement; c: CanvasRenderingContext2D; count: number = 0; public player: Player; // 仅声明,不提前初始化 constructor() { this.canvas = <HTMLCanvasElement>document.querySelector("canvas"); const c = this.canvas.getContext("2d"); if (!c) { throw new Error("获取Canvas上下文失败"); } this.c = c; this.player = new Player(this); // 构造函数内初始化Player,此时实例已就绪 } }
Player.ts
// 类型导入,编译后会被移除,不会产生运行时循环依赖 import type { GamePanel } from "./GamePanel"; export class Player { gp: GamePanel; constructor(gp: GamePanel) { this.gp = gp; } public draw(c: CanvasRenderingContext2D): void { c.fillStyle = "red"; c.fillRect(200, 200, 200, 200); console.log("appeared"); const image = new Image(); image.src = "../img/down.png"; // 图片加载是异步的,必须等待加载完成再绘制 image.onload = () => { c.drawImage(image, 300, 300, 100, 100); c.drawImage(image, 300, 400, 100, 100); }; } }
2. 修复浏览器模块兼容性问题
修改tsconfig.json,将编译目标设置为浏览器支持的ES模块:
{ "compilerOptions": { "target": "ESNext", "module": "ESNext", "moduleResolution": "Bundler", "strict": true, "outDir": "./dist" // 编译后的文件输出目录 }, "include": ["**/*.ts"] // 包含所有TS文件 }
然后在HTML中引入编译后的JS文件时,必须加上type="module":
<script type="module" src="./dist/GamePanel.js"></script>
额外说明
- 图片加载的异步问题:原代码直接调用
drawImage时图片尚未加载完成,会导致绘制失败,因此需要通过onload事件确保图片加载完成后再执行绘制逻辑。 - 如果项目规模较大,建议使用Vite、Webpack等打包工具,它们能更好地处理模块依赖和浏览器兼容性。
内容的提问来源于stack exchange,提问作者sikkokunootubasa
相关产品推荐
相关产品推荐

