TypeScript静态方法访问prototype undefined 游戏实体序列化问题
问题根源
存在两个核心问题:
- this指向丢失:注册实体时直接传递
XWingEntity.create,该方法被取出后作为独立函数调用,严格模式下this默认指向undefined,自然无法读取到prototype属性。 - 逻辑错误:原代码直接对
this.prototype执行Object.assign会修改类的原型对象,所有该类的实例都会被本次赋值的参数影响,完全不符合创建单个实例的需求。
修复方案
1. 修正create静态方法逻辑
不要修改原型,改为创建独立的新实例:
static create(registryName: string, args: Record<string, any>) { // 创建继承自当前类原型的空实例,保证实例能调用类的成员方法(如tick) const object = Object.create(this.prototype); // 将参数赋值给新实例而非原型 Object.assign(object, args); // 兼容直接传x、y的场景,自动组装vec属性 if (!object.vec && args.x !== undefined && args.y !== undefined) { object.vec = {x: args.x, y: args.y}; } object.registryName = registryName; return object as IGameEntity; }
如果希望走构造函数初始化更规范,也可以改写为:
static create(registryName: string, args: Record<string, any>) { const instance = new this( args.vec ?? {x: args.x ?? 0, y: args.y ?? 0}, args.rotation ?? 0, args.scale ?? 1 ); instance.registryName = registryName; // 批量赋值其他自定义属性 Object.assign(instance, args); return instance; }
2. 修复注册时的this指向
注册实体时给create方法绑定正确的this指向,保证调用时this指向对应子类:
register(){ // 方案1:用bind绑定this为XWingEntity this.reg(EntityRegistry.ENTITY_X_WING, XWingEntity.create.bind(XWingEntity)); // 方案2:用箭头函数包裹,固定this指向 // this.reg(EntityRegistry.ENTITY_X_WING, (name, args) => XWingEntity.create(name, args)); }
3. 补充类型定义修正
你的EntityRegistry里的entities属性实际是作为键值对对象使用,不是数组,修正定义避免TS报错:
// 替换原数组类型定义 entities: Record<string, (registryName: string, data: {}) => IGameEntity> = {};
优化建议
如果不想手动维护注册、赋值逻辑,可以引入class-transformer工具库,直接实现类实例和JSON的双向转换,自动补全类方法和类型,不用手动写create逻辑。如果希望轻量化不引入额外依赖,以上修改后的方案已经可以稳定运行。
内容的提问来源于stack exchange,提问作者matez
相关产品推荐
相关产品推荐

