JavaScript含类继承与数组的结构序列化问题:数组丢失及three.js对象处理
解决JavaScript类继承结构的数组序列化丢失问题及Three.js对象序列化方案
一、当前代码的问题分析
你遇到的数组“丢失”,实际根源有两个:
- Math.random用法错误:
Math.random(0, this.greet.length)是无效写法(Math.random无参数),导致get_greet_random大概率返回null,让你误以为数组没被保留。 - 继承类的序列化/反序列化逻辑不严谨:虽然
greet是实例自有属性,JSON.stringify会默认序列化,但用Object.assign混合实例和反序列化数据时,可能因初始化顺序导致预期外的覆盖。
二、修复数组序列化丢失的方案
方案1:修正核心逻辑错误+优化反序列化
先修正随机取值代码,再用类静态方法实现更可靠的序列化/反序列化:
class Greet { greet; constructor() { this.greet = []; } add_greet(new_greet) { this.greet.push(new_greet); } get_greet_random() { if(this.greet.length !== 0) // 修正Math.random用法:用乘法取指定范围随机数 return this.greet[Math.floor(Math.random() * this.greet.length)]; else return null; } // 父类序列化方法 toJSON() { return { greet: [...this.greet] // 浅拷贝数组,避免引用问题 }; } // 父类反序列化静态方法 static fromJSON(data) { const instance = new Greet(); instance.greet = data.greet || []; return instance; } } class CheckGreet extends Greet { constructor() { super(); this.has_say_greet = false; } check_if_has_greetings() { console.log("in check"); if(this.get_greet_random() != null) this.has_say_greet = true; return this.has_say_greet; } // 子类继承并扩展序列化方法 toJSON() { return { ...super.toJSON(), has_say_greet: this.has_say_greet }; } // 子类继承并扩展反序列化静态方法 static fromJSON(data) { const instance = super.fromJSON(data); instance.has_say_greet = data.has_say_greet ?? false; return instance; } } // 使用示例 let checkGreet = new CheckGreet(); checkGreet.add_greet("Hello World"); // 序列化 let serialized_data = JSON.stringify(checkGreet); // 反序列化 let deserialized_data = JSON.parse(serialized_data); let checkGreet_from_deserialized = CheckGreet.fromJSON(deserialized_data); console.log(checkGreet_from_deserialized.check_if_has_greetings()); // 现在会输出true
方案2:简化版(无需自定义方法)
如果不想写自定义序列化方法,确保实例属性可枚举,并直接手动赋值:
// 修正Math.random后,序列化时展开实例确保所有自有属性被序列化 let serialized_data = JSON.stringify({...checkGreet}); // 反序列化时先创建实例,再手动覆盖属性 let deserialized_data = JSON.parse(serialized_data); let checkGreet_from_deserialized = new CheckGreet(); checkGreet_from_deserialized.greet = deserialized_data.greet; checkGreet_from_deserialized.has_say_greet = deserialized_data.has_say_greet;
三、数组存储Three.js对象的序列化方案
Three.js内置对象(如Mesh、Vector3、Geometry等)自带序列化/反序列化机制,无需手动处理:
序列化Three.js对象数组
// 示例:存储Mesh数组 const greetMeshes = [ new THREE.Mesh(new THREE.BoxGeometry(), new THREE.MeshBasicMaterial()), new THREE.Mesh(new THREE.SphereGeometry(), new THREE.MeshBasicMaterial()) ]; // 逐个将Three.js对象转为JSON格式 const serializedMeshes = greetMeshes.map(mesh => mesh.toJSON()); // 整体序列化 const serialized_data = JSON.stringify({ greet: serializedMeshes });
反序列化Three.js对象数组
const deserialized_data = JSON.parse(serialized_data); const loader = new THREE.ObjectLoader(); // 逐个解析JSON为Three.js对象 const restoredMeshes = deserialized_data.greet.map(meshJson => loader.parse(meshJson));
注意:如果是自定义的Three.js扩展对象,需要先注册对应的加载器,否则ObjectLoader无法解析。
内容的提问来源于stack exchange,提问作者stickske
相关产品推荐
相关产品推荐

