JavaScript如何存储自定义类复杂对象实现浏览器端持久化
为什么直接存localStorage不生效
localStorage 仅支持存储字符串类型的值,直接传入自定义类实例时,会默认调用实例的toString()方法,最终存入的是"[object Object]"这种无效字符串,既丢了属性值,也完全丢失了类上定义的方法,自然没法正常读取使用。
可行实现方案
方案1:JSON序列化+构造函数还原(兼容性最好,适合绝大多数场景)
存储时只提取实例的自有属性转成JSON字符串存入,读取时把解析出的属性传入Person构造函数,重新生成完整实例即可。
// 存储代码 const person = new Person('Paul', 27, 'Haïti'); localStorage.setItem('userInfo', JSON.stringify({ name: person.name, age: person.age, country: person.country })); // 读取还原代码 const savedConfig = JSON.parse(localStorage.getItem('userInfo')); const restoredPerson = new Person(savedConfig.name, savedConfig.age, savedConfig.country); // 还原后的实例可以正常调用所有类方法 console.log(restoredPerson.getName()); // 输出 Paul
如果类属性较多,不想逐一字段写映射,只要保证constructor参数顺序和属性顺序一致,可以直接用解构传参:const restoredPerson = new Person(...Object.values(savedConfig));
方案2:给类加自定义序列化/反序列化方法(适合复杂类场景)
在类内部封装专属的序列化、静态还原方法,后续存取不需要重复手动维护属性列表,可维护性更高:
class Person { constructor(name, age, country) { this.name = name; this.age = age; this.country = country; } setName(name) { if (name !== null) this.name = name; } setAge(age) { if (age !== null) this.age = age; } setCountry(country) { if (country !== null) this.country = country; } getName() { return this.name; } // 自定义序列化规则,返回可直接转JSON的普通对象 toJSON() { return { name: this.name, age: this.age, country: this.country } } // 静态方法:从解析后的JSON数据还原实例 static fromJSON(jsonData) { return new Person(jsonData.name, jsonData.age, jsonData.country) } } // 存储 const person = new Person('Paul', 27, 'Haïti'); localStorage.setItem('userInfo', JSON.stringify(person)); // 读取 const restoredPerson = Person.fromJSON(JSON.parse(localStorage.getItem('userInfo')));
方案3:IndexedDB存储(适合大数据量场景)
localStorage单域名一般只有5MB左右的存储上限,如果你需要存储大量这类结构化对象,可以用浏览器原生的IndexedDB,它支持直接存储结构化数据、存储上限高,但API是异步形式,写法相对复杂,小数据量场景没必要使用。
注意:不推荐通过修改原型链的方式强行给解析出的普通对象绑定Person方法,这种方式会绕过类构造函数的校验逻辑,后续类逻辑迭代时很容易出现数据异常,走构造函数重新生成实例是最稳妥的方案。
内容的提问来源于stack exchange,提问作者Madel M6TM
相关产品推荐
相关产品推荐

