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

TypeScript跨文件调用Map时get()返回undefined问题求助

问题根源与解决方案

1. Map未初始化导致的隐性异常

你的SpriteSet类中map属性仅做了类型声明,但未在构造函数中显式初始化。虽然JavaScript会自动将未赋值的属性设为undefined,但后续调用this.map.set()时浏览器会隐式创建Map实例——这种隐式创建会引发引用一致性问题,叠加异步加载的时序问题后,就出现了控制台显示有数据但实际访问不到的诡异现象。

修复方法:在SpriteSet构造函数中显式初始化Map:

export class SpriteSet {
    map: Map<string, Sprite>;

    constructor() {
        this.map = new Map<string, Sprite>(); // 显式初始化Map实例
    }

    // ... 其他代码
}

2. 异步加载的时序错误

addToSpriteSet中的img.onload是异步回调,调用addToSpriteSet后代码会继续执行,而Map的填充操作要等到图片加载完成后才会触发。当你调用MapBuilder.load()时,大概率图片还未加载完成,此时map实际是空的(size为0,get()返回undefined)。

浏览器控制台显示Map有数据,是因为控制台会保留对象引用,后续异步操作填充Map后,控制台会更新显示,但此时你的代码已经执行过get()逻辑了。

修复方法:将addToSpriteSet改为返回Promise,确保图片加载完成后再执行load():

export class SpriteSet {
    map: Map<string, Sprite>;

    constructor() {
        this.map = new Map<string, Sprite>();
    }

    addToSpriteSet(path: string, arr: string[]): Promise<void> {
        return new Promise((resolve) => {
            const img = new Image();
            img.src = path;
            img.onload = () => {
                const spriteCountX = img.width / 16;
                for (let i = 0; i < img.height / 16; i++) {
                    for (let j = 0; j < spriteCountX; j++) {
                        const spr = new Sprite(img.src, j * 16, i * 16);
                        const keyIndex = i * spriteCountX + j;
                        this.map.set(arr[keyIndex], spr);
                    }
                }
                resolve(); // 加载完成后通知外部
            };
            // 可选:处理图片加载失败场景
            img.onerror = () => {
                console.error(`加载图片失败: ${path}`);
                resolve();
            };
        });
    }
}

调用时需等待addToSpriteSet完成后再执行load():

// 示例初始化逻辑
async function init() {
    const spriteSet = new SpriteSet();
    await spriteSet.addToSpriteSet("path/to/your/sprite.png", ["grass", ...其他键名]);
    
    const mapBuilder = new MapBuilder();
    mapBuilder.sprites = spriteSet;
    // 初始化tiles、code等其他属性...
    mapBuilder.load();
}

init();

额外优化点

  • 修复上述问题后,无需再使用Map.prototype.get.call这种怪异写法,直接用this.sprites.map.get(key)即可正常访问。
  • 给MapBuilder添加background属性的类型声明,当前代码中setBackground方法操作的this.background未在类中声明,会触发TypeScript报错。

内容的提问来源于stack exchange,提问作者Ian G.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 06:47:04