我需要以某种方式深入克隆我的ScriptEngine对象的整个绑定集。
我试过的
System.out.println()停止工作一样.jQuery.extend() (例如)克隆时,克隆的a和b的字段a.fa和b.fb将引用不同的c克隆,而不是引用同一个克隆。还有很多其他的边缘问题。我为什么要这么做
我需要这样做,因为我必须能够将整个ScriptEngine绑定的值还原到以前的某个点。我需要对绑定做精确的快照。
该应用程序是我的博士研究项目的一部分,该项目包括运行带有带有js代码的节点(用java实现)的状态机。js代码由最终用户输入,并在运行时进行评估。当无法通过路径到达最终状态时,该算法向后执行步骤,试图找到可选路径。在每一步后退时,它都必须撤消js引擎绑定中可能发生的任何更改。
所有的全局变量名在js certain之前都是已知的,并且都是对象(用户在节点的代码类型中,然后(在java中)组织成具有特定名称模式的js对象)。但是它们的内容可以是任何内容,因为它是由用户js代码控制的。
因此,我想我现在唯一的解决办法是使用js代码克隆js对象。
发布于 2014-07-10 09:52:56
除了“边缘案例”之外,jQuery.extend还可以用于您提到的方式。a b和它们的克隆都将引用相同的对象c。
var c = { f:'see' };
var a = { fa: c };
var b = { fb: c };
var cloneA = $.extend({}, a);
var cloneB = $.extend({}, b);
console.log(a.fa === b.fb, cloneA.fa === cloneB.fb, a.fa === cloneB.fb);
// true true true但是,您似乎希望克隆所有对象(包括c),同时跟踪对象的关系。为此,最好使用对象关系表。
我在嵌套的javascript对象和JSON中看到了很多这种情况,因为人们往往忘记JSON纯粹是一种文本格式。除了一个文本instanceof String字符串之外,JSON文件中没有实际的javascript对象。在javascript中没有豆类、泡菜或任何防腐剂含量高的食物。
在对象关系表中,每个“表”只是一个“平面”对象数组,只有原始值属性和指向表(或其他表中的其他对象)的指针(而不是引用)。指针可以只是目标对象的索引。
因此,上述对象关系的JSON版本可能如下所示
{
"table-1":[
{ "a": { "fa":["table-2",0] } },
{ "b": { "fb":["table-2",0] } }
],
"table-2":[
{ "c": { "name":"see" } },
{ "d": { "name":"dee" } },
{ "e": { "name":"eh.."} }
]
}解析器看起来可能像
var tables = JSON.parse(jsonString);
for(var key in tables){
var table = tables[key];
for(var i = 0; i < table.length; i++){
var name = Object.keys(table[i])
var obj = table[i][name];
for(var key2 in obj){
if(obj[key2] instanceof Array && obj[key2][0] in tables){
var refTable = obj[key2][0];
var refID = obj[key2][1];
var refObj = tables[refTable][refID];
var refKey = Object.keys(refObj)[0];
obj[key2] = refObj[refKey];
}
}
this[name] = obj;
}
}
console.log(a.fa === b.fb, b.fb === c);
// true true我意识到对象关系映射有它的缺点,但是使用脚本引擎的快照听起来确实有点疯狂。特别是因为你的意图是能够回忆起前一步,因为你需要一个新的快照为每一步.很快就会占用大量的磁盘空间。除非你只是在跟踪每个步骤之间的快照差异,比如git。要实现一个看似简单的“撤销”方法,这听起来很费劲。
该死的..。想想看,为什么不把每一步都存储在历史文件中呢?然后,如果需要退一步,只需在前一步截断历史文件,然后在新的环境中再次运行每一步。
不确定使用java会有多实际(从性能上讲)。Nodejs (现在已经存在)比任何java脚本引擎都要快。实际上,从现在开始我就叫它ECMAscript。很抱歉你的咆哮,只是
Java很慢,但您已经知道了。
因为它很容易表现出来,所以它的速度是一样快的。
发布于 2014-07-11 09:49:23
请允许我提出另一种方法。
{$ref: PATH}中编码对象引用。反序列化时,它将恢复引用。
据我所知,cycle.js不序列化函数,而是可以使用Function.toString()自己添加函数序列化(请参见下面和示例)或者,如果使用库不是一个选项,那么实现您自己的序列化以满足您的需要是相当简单的:
var jsonString = JSON.stringify(obj, function(key, val) {
if (typeof(value) === 'function')
return val.toString();
// or do something else with value like detect a reference
return val
})https://stackoverflow.com/questions/11116120
复制相似问题