Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/386.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Javascript(Node.js)中保存/加载复杂的对象结构_Javascript_Json_Node.js - Fatal编程技术网

在Javascript(Node.js)中保存/加载复杂的对象结构

在Javascript(Node.js)中保存/加载复杂的对象结构,javascript,json,node.js,Javascript,Json,Node.js,我已经用javascript编写代码有一段时间了,但我对Node还是相当陌生的。我最近承担了一个项目,该项目涉及一个复杂的对象结构,具有多个层次的原型继承和子对象。此结构需要定期保存/加载。保存和加载JSON是可取的 问题 有没有比我当前的方法(如下所述)更优雅的方法来完成保存/加载这些复杂Javascript对象的任务?有没有可能以这样一种方式设计它:构造函数可以像初始化普通对象一样初始化自己,而不受所有恢复功能的约束 我的解决方案 基类(根据设计,所有其他考虑中的对象都从该类继承原型)有一个

我已经用javascript编写代码有一段时间了,但我对Node还是相当陌生的。我最近承担了一个项目,该项目涉及一个复杂的对象结构,具有多个层次的原型继承和子对象。此结构需要定期保存/加载。保存和加载JSON是可取的

问题 有没有比我当前的方法(如下所述)更优雅的方法来完成保存/加载这些复杂Javascript对象的任务?有没有可能以这样一种方式设计它:构造函数可以像初始化普通对象一样初始化自己,而不受所有恢复功能的约束

我的解决方案 基类(根据设计,所有其他考虑中的对象都从该类继承原型)有一个处理“选项”参数的函数,将其所有属性添加到当前对象。所有派生对象必须包含一个选项参数作为最后一个参数,并在其构造函数中调用处理函数

每个对象还必须将其函数名添加到特定属性,以便在需要重建对象时调用正确的构造函数

解包函数获取保存的对象JSON,使用JSON.parse创建一个普通对象,然后将该对象作为“选项”参数传递给对象的构造函数

每个对象都有一个唯一的id,并存储在一个查找表中,这样,一个正在构建的函数(带有指向其他对象的链接)就可以指向正确的对象,或者在需要时创建它们

下面是一个示例,演示了这个想法(显然是以非节点的方式)

如果您不想加载plunker,这里有一段摘录,希望能提供我要做的事情的要点:

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友好原语的状态对象。在编码时,它会产生一个额外的点段,但会将数据和方法分开,这在这些情况下是一个巨大的胜利。