可以创建一个事务数组,记录对对象所做的每个更改并记录有关更改的足够数据,以便可以将其撤消。这并不是一项微不足道的工作。例如,它与字处理程序或电子表格中的撤消功能有点类似。如果您记录了正确的信息级别并将其保存在一个数组中,则应该可以撤消所有更改。这不是火箭科学,但它是一些编写和测试的代码。
正如在评论中提到的,这里提出的一个更大的问题是关于一个单一的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;
}
}
}
}
“写少勿多”! –
这里我关心的是为什么你有一个25mb的JavaScript对象... – taxicala
这听起来像你需要让你的检查返回原先的对象,然后跟进你的检查,实际上修改对象。 –