JavaScript序列化和方法

时间:2012-03-12 13:54:19

标签: javascript json serialization

我是“面向对象”JavaScript的新手。目前,我有一个需要跨页面传递的对象。我的目标定义如下:

function MyObject() { this.init(); }
MyObject.prototype = {
    property1: "",
    property2: "",

    init: function () {
        this.property1 = "First";
        this.property2 = "Second";
    },

    test: function() {
      alert("Executing test!");
    }
}

在我的应用程序的第1页上,我正在创建一个MyObject实例。然后我将序列化对象并将其存储在本地存储中。我这样做是这样的:

var mo = new MyObject();
mo.test();                                    // This works
window.localStorage.setItem("myObject", JSON.stringify(mo));

现在,在第2页,我需要获取该对象并使用它。要检索它,我使用以下内容:

var mo = window.localStorage.getItem("myObject");
mo = JSON.parse(mo);
alert(mo.property1);    // This shows "First" as expected.
mo.test();              // This does not work. In fact, I get a "TypeError"  that says "undefined method" in the consol window.

根据输出,看起来当我序列化对象时,不知何故函数被删除。我仍然可以看到属性。但我不能与我的任何功能互动。我做错了什么?

6 个答案:

答案 0 :(得分:6)

JSON不会序列化函数。

看看第二段here

  

如果需要保留这些值,可以在序列化时或在反序列化之前转换值,以使JSON能够表示其他数据类型。

换句话说,如果您真的想要JSONify函数,可以在序列化之前将它们转换为字符串:

mo.init = ''+mo.init;
mo.test = ''+mo.test;

反序列化后,将它们转换回函数。

mo.init = eval(mo.init);
mo.test = eval(mo.test);

但是,没有理由这样做。相反,您可以让MyObject构造函数接受一个简单的对象(如解析JSON字符串所示)并将对象的属性复制到自身。

答案 1 :(得分:3)

无法将函数序列化为JSON对象。

所以我建议你为实际的属性创建一个单独的对象(或对象内的属性),然后序列化这个部分。 之后,您可以使用其所有功能实例化对象,并重新应用所有属性以重新获得对工作对象的访问权。

按照您的示例,这可能如下所示:

function MyObject() { this.init(); }
MyObject.prototype = {
    data: {
      property1: "",
      property2: ""
    },

    init: function () {
        this.property1 = "First";
        this.property2 = "Second";
    },

    test: function() {
      alert("Executing test!");
    },


   save: function( id ) {
     window.localStorage.setItem( id, JSON.stringify(this.data));
   },
   load: function( id ) {
     this.data = JSON.parse( window.getItem( id ) );
   }

}

答案 2 :(得分:1)

为了避免改变结构,我更喜欢在对象检索上使用Object.assign方法。此方法合并第一个参数对象。要获取对象方法,我们只需要一个空的新对象作为目标参数。

var mo = window.localStorage.getItem("myObject");
// this object has properties only
mo = JSON.parse(mo);
// this object will have properties and functions
var completeObject = Object.assign(new MyObject(), mo);

请注意,Object.assign的第一个参数被修改并由函数返回。

答案 3 :(得分:0)

那是因为我认为JSON.stringify()没有序列化函数。

答案 4 :(得分:0)

你是对的,功能被丢弃了。此页面可能有所帮助:

http://www.json.org/js.html

“排除了在JSON中没有表示的值(例如函数和未定义的值)。”

答案 5 :(得分:0)

<块引用>

看起来当我序列化对象时,函数以某种方式被删除......我做错了什么?

是的,使用 JSON.stringify()JSON.parse() 时函数会被删除,并且您的代码没有任何问题。

为了在序列化和反序列化期间保留函数,我制作了一个名为 esserializer 的 npm 模块来解决这个问题——JavaScript 类实例值将在第 1 页的序列化期间以纯 JSON 格式保存在一起及其类名信息:

var ESSerializer = require('esserializer');

function MyObject() { this.init(); }
MyObject.prototype = {
    property1: "",
    property2: "",

    init: function () {
        this.property1 = "First";
        this.property2 = "Second";
    },

    test: function() {
      alert("Executing test!");
    }
}
MyObject.prototype.constructor=MyObject; // This line of code is necessary, as the prototype of MyObject has been overridden above.

var mo = new MyObject();
mo.test();                                    // This works
window.localStorage.setItem("myObject", ESSerializer.serialize(mo));

稍后,在第 2 页的反序列化阶段,esserializer 可以递归反序列化对象实例,保留所有类型/函数信息:

var mo = window.localStorage.getItem("myObject");
mo = ESSerializer.deserialize(mo, [MyObject]);
alert(mo.property1);    // This shows "First" as expected.
mo.test();              // This works too.