Clone Entire JavaScript ScriptEngine

只谈情不闲聊 提交于 2019-11-30 14:37:30

Aside from "edge cases", jQuery.extend can be used in the way you mention. a b and their clones will all reference the same object 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

But it seems like you want to clone all the objects (including c) while keeping track of the objects' relationships. For this, it may be best to use object relation tables.

I see this a lot with nested javascript objects and JSON because people tend to forget that JSON is purely a text format. There are no actual javascript objects in a JSON file except for a single string of text instanceof String. There are no beans or pickles or any preservative-heavy foods in javascript.

In an object relation table, each 'table' is just an array of "flat" objects with only primitive valued properties and pointers (not references) to other objects in the table (or in another table). The pointer can just be the index of the target object.

So a JSON version of the above object relationship might look something like

{
    "table-1":[
        { "a": { "fa":["table-2",0] } },
        { "b": { "fb":["table-2",0] } }
    ],
    "table-2":[
        { "c": { "name":"see" } },
        { "d": { "name":"dee" } },
        { "e": { "name":"eh.."} }
    ]
}

And a parser might look like

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

I realize object relationship mapping has it's downfalls, but taking snapshots of the scripting engine does sound a bit crazy. Especially since your intention is to be able to recall each previous step, because then you need a new snapshot for every step... that will very quickly take up shit ton of disk space.. unless you're just keeping track of the snapshot diffs between each step, like a git repo. That sounds like an awful lot of work to implement a seemingly simple "undo" method.

Damn.. come to think of it, why not just store each step in a history file? Then if you need to step back, just truncate the history file at the previous step, and run each step over again in a fresh environment.

Not sure how practical that would be (performance wise) using java. Nodejs (as it exists today) is faster than any java scripting engine will ever be. In fact, I'm just gonna call it ECMAscript from now on. Sorry bout the rant, its just that

Java is slow, but you already know.
Because it readily shows, that's as fast as it goes.

May I suggest a different approach.

  • Don't try to clone the ScriptEngine. It doesn't implement Serializable/Externalizable and the API doesn't support cloning. Attempts to force a clone will be workarounds that might break in some future Java version.

  • Serialize Bindings to JSON using cycle.js. It will encode object references in the form {$ref: PATH}. When you deserialize it will restore the references.

    As far as I can tell cycle.js doesn't serialize functions but its possible to add function serialization yourself using Function.toString() (See below and Example)

Alternatively if using a library is not an option its fairly straightforward to implement your own serialization to suit your needs:

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
})
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!