2015-11-05 36 views
-3

我有一个JSON格式的JavaScript对象,需要根据set输入修改(删除foo或添加栏等)。此输入可能具有级联效果(删除foo可能需要先根据一组规则删除foobar)。如果通过级联的一半中断,我不希望JavaScript对象有一半的修改,我想回到原来的未修改的对象。修改JavaScript对象里面的功能,如果错误返回到原始

我明显可以发送一个对象的副本到修改函数中,然后在函数返回错误时不会替换原始对象。与此相关的问题是JavaScript对象大约25兆字节,因此它的副本将意味着浏览器的内存使用量显着增加。所以我想在不创建对象副本的情况下执行此操作。我可以将初始对象作为函数的输入并递归修改,但如果在某些调用后出现错误,它可能会在我不需要时返回修改后的对象。

会有办法做我想做的事吗?跟踪更改并在发生错误或其他情况后轻松撤消它们?谢谢。

+2

“写少勿多”! –

+1

这里我关心的是为什么你有一个25mb的JavaScript对象... – taxicala

+0

这听起来像你需要让你的检查返回原先的对象,然后跟进你的检查,实际上修改对象。 –

回答

3

可以创建一个事务数组,记录对对象所做的每个更改并记录有关更改的足够数据,以便可以将其撤消。这并不是一项微不足道的工作。例如,它与字处理程序或电子表格中的撤消功能有点类似。如果您记录了正确的信息级别并将其保存在一个数组中,则应该可以撤消所有更改。这不是火箭科学,但它是一些编写和测试的代码。

正如在评论中提到的,这里提出的一个更大的问题是关于一个单一的25MB对象,必须通过一个函数来操作。我个人怀疑是否可以将数据分解成更小的部分,并且能够使用更小的副本来不必编写整个撤消操作。

此外,值得考虑的是,您是否可以预先足够的操作来提前知道在修改对象之前代码是否会失败。例如,我之前使用的代码与修改对象的代码运行所有相同的逻辑,但实际上并未修改对象。这使您可以运行整个操作的预执行,从而确定在实际修改对象之前是否有任何操作失败。写得恰当的话,你可以使用相同的代码进行飞行前的实际修改,只需传入一个额外的标志。这是多么可行取决于修改操作的确切性质,您还没有透露。

下面是处理特定对象属性更改的代码示例。这可以扩展到包括数组操作。

工作演示:http://jsfiddle.net/jfriend00/ohqL0p06/

代码:

function TransactionSummary() { 
    this.transactions = []; 
} 

TransactionSummary.prototype = { 
    deleteProperty: function(parent, property) { 
     this.rememberTransaction(parent, property, "delete", parent[property]); 
     delete parent[property]; 
    }, 
    modifyProperty: function(parent, property, newVal) { 
     this.rememberTransaction(parent, property, "modify", parent[property]); 
     parent[property] = newVal; 
    }, 
    addProperty: function(parent, property, newVal) { 
     this.rememberTransaction(parent, property, "add"); 
     parent[property] = newVal; 
    }, 
    rememberTransaction: function(parent, property, type, oldVal) { 
     this.transactions.push({parent: parent, property: property, type: type, oldVal: oldVal}); 
    }, 
    undoTransactions: function() { 
     var t; 
     while (this.transactions.length) { 
      t = this.transactions.pop(); 
      switch(t.type) { 
       case "delete": 
       case "modify": 
        t.parent[t.property] = t.oldVal; 
        break; 
       case "add": 
        delete parent[property]; 
        break; 
      } 
     } 
    } 
} 
+0

不幸的是,在这个时候,将对象分解成更小的对象并不是真正的选择。将来可能会分配给它,但是在其他代码中需要进行很多重写,因此到目前为止,最好的选择是复制25MB的对象并使内存变得沉重。我承认这是一个非常奇怪的情况,但现在是这样。 事务数组选项似乎很有趣,但使用它将取决于创建需要多长时间。有没有一个很好的例子(只是类似于从看看想法)? –

+1

@JediWolf - 我添加了一个可以撤销更改的事务记录器示例。 – jfriend00

+0

谢谢,这看起来很有希望。我必须看看我能否在我的最终目标中实现它,但这可能是根据我的情况得到的最好结果。 –

相关问题