在Javascript(Node.js)中保存/加载复杂的对象结构
我已经用javascript编写代码有一段时间了,但我对Node还是相当陌生的。我最近承担了一个项目,该项目涉及一个复杂的对象结构,具有多个层次的原型继承和子对象。此结构需要定期保存/加载。保存和加载JSON是可取的 问题 有没有比我当前的方法(如下所述)更优雅的方法来完成保存/加载这些复杂Javascript对象的任务?有没有可能以这样一种方式设计它:构造函数可以像初始化普通对象一样初始化自己,而不受所有恢复功能的约束 我的解决方案 基类(根据设计,所有其他考虑中的对象都从该类继承原型)有一个处理“选项”参数的函数,将其所有属性添加到当前对象。所有派生对象必须包含一个选项参数作为最后一个参数,并在其构造函数中调用处理函数 每个对象还必须将其函数名添加到特定属性,以便在需要重建对象时调用正确的构造函数 解包函数获取保存的对象JSON,使用JSON.parse创建一个普通对象,然后将该对象作为“选项”参数传递给对象的构造函数 每个对象都有一个唯一的id,并存储在一个查找表中,这样,一个正在构建的函数(带有指向其他对象的链接)就可以指向正确的对象,或者在需要时创建它们 下面是一个示例,演示了这个想法(显然是以非节点的方式) 如果您不想加载plunker,这里有一段摘录,希望能提供我要做的事情的要点:在Javascript(Node.js)中保存/加载复杂的对象结构,javascript,json,node.js,Javascript,Json,Node.js,我已经用javascript编写代码有一段时间了,但我对Node还是相当陌生的。我最近承担了一个项目,该项目涉及一个复杂的对象结构,具有多个层次的原型继承和子对象。此结构需要定期保存/加载。保存和加载JSON是可取的 问题 有没有比我当前的方法(如下所述)更优雅的方法来完成保存/加载这些复杂Javascript对象的任务?有没有可能以这样一种方式设计它:构造函数可以像初始化普通对象一样初始化自己,而不受所有恢复功能的约束 我的解决方案 基类(根据设计,所有其他考虑中的对象都从该类继承原型)有一个
function BaseClass(name, locale, options){
if(name) this.name = name;
if(locale) this.locale = locale;
// If options are defined, apply them
this.processOptions(options);
// create the classList array which keeps track of
// the object's prototype chain
this._classList = [arguments.callee.name];
// Create a unique id for the object and add it to
// the lookup table
if(!this.id) this.id = numEntities++;
lookupTable[this.id] = this;
if(!this.relations) this.relations = [];
// other initialization stuff
}
BaseClass.prototype = {
processOptions: function(options) {
if(options && !options._processed){
for(var key in options){
if(options.hasOwnProperty(key)){
this[key] = options[key];
}
}
options._processed = true;
}
},
addNewRelation: function(otherObj){
this.relations.push(otherObj.id);
}
// Other functions and such for the base object
}
function DerivedClassA(name, locale, age, options){
if(age) this.age = age;
this.processOptions(options);
if(options && options.connectedObj){
// Get the sub object if it already exists
if(lookupTable[options.subObj.id]){
this.subObj = lookupTable[options.subObj.id];
}
// Otherwise, create it from the options
else {
this.subObj = new OtherDerivedClass(options.subObj);
}
}
else {
// If no options then construct as normal
this.subObj = new OtherDerivedClass();
}
// If something needs to be done before calling the super
// constructor, It's done here.
BaseClass.call(this, name, locale, options);
this._classList.push(arguments.callee.name);
}
DerivedClassA.prototype = Object.create(BaseClass.prototype);
如前所述,这项工作已经完成,但我忍不住觉得这样会更好。它似乎对继承的“类”及其构造函数的行为施加了荒谬的限制。它使特定的执行顺序变得至关重要,并要求每个对象都深入参与并了解恢复过程,这远远不够理想。setPrototypeOf()和BaseClass.prototype.toJSON()可以减少大量的工作量。如果您的toJSON方法在构造函数名称中滑入,那么您可以只设置proto,而不是重新构造所有内容。@dandavis我实际上忘记了setPrototypeOf方法。这可能会派上用场。但不幸的是,我可能必须通过构造函数来初始化JSON中未枚举的属性(例如函数),以及执行其他可能不属于JSON的操作。您也可以执行function.prototype.toJSON()操作。它需要一个在JSON.parse中传递的自定义恢复器函数来恢复函数,但是如果您设置了proto,并且方法在proto上,那么您就不需要迭代它们来获得完全格式的对象。您也可以考虑不直接在实例上存储属性,而是形成一个保持JSON友好原语的状态对象。在编码时,它会产生一个额外的点段,但会将数据和方法分开,这在这些情况下是一个巨大的胜利。