如何为泛型类型分配原型,解决sessionStorage解析后丢失对象方法的问题
解决方案
核心问题是JSON.parse只会生成无自定义原型的普通对象,且TypeScript泛型仅存在于编译阶段,运行时无法直接获取泛型T的构造函数信息,因此需要显式传入目标类的构造函数作为参数,再做原型绑定或实例初始化。
方案1:手动挂载原型(适合简单类场景)
直接给反序列化得到的普通对象挂载目标类的原型,无需修改原有类定义:
public static getObject<T>(key: string, clazz: new () => T): T | null { const storageStr = sessionStorage.getItem(key); if (!storageStr) return null; const plainObj = JSON.parse(storageStr); Object.setPrototypeOf(plainObj, clazz.prototype); return plainObj as T; }
调用示例
假设你有自定义类User,调用时传入构造函数即可:
const user = YourService.getObject('current-user', User); // 可正常调用User类的原型方法 user?.sayHello();
方案2:构造函数注入数据(适合复杂类场景)
如果你的类包含构造初始化逻辑、私有属性、访问器等,更推荐通过构造函数接收反序列化数据创建实例,完全规避原型修改带来的隐患:
- 先在自定义类中支持传入普通对象初始化:
class User { name: string; id: number; constructor(plainObj?: Partial<User>) { if (plainObj) { Object.assign(this, plainObj); } } // 自定义方法 getUserIdStr() { return `user_${this.id}`; } }
- 调整
getObject方法,用反序列化数据生成类实例:
public static getObject<T>(key: string, clazz: new (plain: any) => T): T | null { const storageStr = sessionStorage.getItem(key); if (!storageStr) return null; const plainObj = JSON.parse(storageStr); return new clazz(plainObj); }
注意事项
- JSON序列化会自动丢弃函数、Symbol、undefined、循环引用等类型的值,如果类中包含这类属性,序列化存储前需要做自定义转换,反序列化后再手动恢复。
Object.setPrototypeOf存在一定性能损耗,大数据量场景优先选择方案2。
内容的提问来源于stack exchange,提问作者preshu
相关产品推荐
相关产品推荐

