JavaScript持久化框架/Google v8

3

是否有适用于JavaScript和/或Google v8引擎的任何类型的持久化框架?

我想要存储(序列化)一个包含对象图的整个图形(包括例如函数),并在以后重新加载它。JSON是不够的,因为它不允许函数被存储,并且只允许树状结构(即没有两个对象引用相同的对象)。

我需要能够通用地做到这一点(即在编写嵌入v8的程序时不知道JavaScript代码),因为我希望我的程序的用户能够使用JavaScript自定义它,但我需要存储我的程序的状态(包括自定义状态)并在以后重新加载它。因此,我需要存储JavaScript引擎的状态。

编辑:

例如:

假设我们有以下代码:

var obj = { a: 4, b: function (x) { return x + this.a; } }
// ...
if ( ... ) { obj.a = 5; }
// ...
if ( ... ) { var c = 1; obj.b = function (x) { return x + this.a + c; } }
// ...
// now I want to serialize obj

那么,在没有关于程序逻辑的任何元信息的情况下,能否对 obj 进行序列化,并在以后进行反序列化,以使得在反序列化后 obj.b (2) 的结果与序列化之前相同?

第二次编辑:请注意闭包函数。


我不明白为什么你需要持久化函数?因为你可以从对象原型继承中恢复函数(假设是方法)。 - Kyaw Tun
我并不完全理解你的问题。不过,我会尝试通过一个例子来阐述我的问题。 - JohnB
为什么不把所有 JavaScript 代码存储起来,然后使用 eval 命令还原它(就像从服务器返回一样)?或者使用 "toString()" 方法反序列化每个函数。再次强调,无法避免使用 eval 命令。 - Kyaw Tun
这是一种可能性,但并不是很好的选择,因为运行脚本时,并非所有数据都需要由脚本自身生成。例如,可能存在用户输入或从网络获取的数据等。因此,我仍在寻找类似于序列化框架的东西。如果我的智力能力范围内,我可以为Google v8编写一个程序。 - JohnB
我明白了。原型继承只能与预定义的函数(方法)一起使用。如果这些函数很简单,也可以考虑在S表达式中表达它们。这样可以避免eval,但仍然具有灵活性。 - Kyaw Tun
3个回答

6
很遗憾,您在Javascript中想要做的事情目前是不可能的。原因是闭包不仅仅是对象,它们还绑定于执行上下文。
解决“在Javascript中无法完成此项操作”问题并进入“如果为V8编写一个补丁来允许此项操作”阶段,这在概念上是很困难的。基本上,对于每个要序列化的闭包,您都必须序列化该闭包所在的“Context”对象。能够序列化“HandleScope”将是很好的,但闭包的本质是您无法接触其中的内容。
好吧,假设您已经编写了可以序列化闭包所在上下文的函数,并且甚至可以对其进行反序列化。那么该怎么办呢?
答案是“没什么用”。Javascript只能在一个上下文中执行。您反序列化的闭包不存在于您试图将其重新引入的上下文中。您无法真正地在上下文之间传递数据,如果您的函数绑定到自由变量,您是否使用反序列化器调用上下文中存在的变量,还是覆盖它?从概念上讲,这是一场噩梦。
Ecmascript Harmony曾考虑给我们提供几乎一流的连续性,但它已经被推迟了,我在这里抱怨了一下,但是这不会很快发生。

感谢您提供这个有见地的答案。然而,我尝试做的事情在Jurassic(C# JavaScript引擎)中是可能的,因此应该可以实现类似于Google v8的东西。 - JohnB
你在Jurassic中怎么做?我从未使用过,但很想知道它是如何工作的。从架构上看,我猜它与V8不同。 - saml

0
我认为持久化函数不是一个好的实践。我可以建议您采用以下方法。将您的JSON数据转换为类似于“MyData”的类。您可以找到两个函数fromJSON,toJSON,它们将实现您想要的魔法。
var MyData = function(props){

    this.temp = "a";

    this.getTemp = function(){
        return this.temp;
    }

    this.fromJSON = function(props){
        if(props){
            this.temp = props.temp;
        }

    }
    this.toJSON = function(){
        var props = {};
        props.temp = this.temp;
        return props;
    }

    this.fromJSON(props);

}

var obj = new MyData({"temp" : "b"});
var state = obj.toJSON();
// persist state about the object as JSON string
LOCALSTORAGE.put(state); // You can write some HTML5 local storage stuff to persist

var persistedState = LOCALSTORAGE.get(); // You can use the above HTML5 local storage stuff to read the persisted stuff
var newBornObj = new MyData(persistedState);

我认为你误解了他的问题,他问的是如何持久化闭包,而不是 JSON。闭包无法转换成 JSON。 - saml

0

HTML5本地存储允许通过javascript在客户端级别进行持久化。

我不确定它是否适合您的需求,因为如果要存储函数,您需要给它一些标记,以便在从存储中检索时对其进行反序列化(或者只是将其存储为纯文本,并尝试在检索时进行评估)

http://diveintohtml5.info/storage.html


嗯,将函数存储为纯文本的问题在于,如果函数涉及闭包,我将失去捕获的变量。 - JohnB
你需要将闭包内获取的值复制到函数作用域的变量中。这很糟糕,但我想这可能会奏效。 - Bardo
我认为这个建议最大的问题在于它链接到w3schools。W3Schools不是任何信息的可靠来源。 - saml

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接