反序列化JavaScript对象实例

反序列化JavaScript对象实例,javascript,oop,Javascript,Oop,我正在开发一款大量使用JavaScript的应用程序。我试图包括一些面向对象的实践。在这次尝试中,我创建了一个基本类,如下所示: function Item() { this.init(); } Item.prototype = { init: function () { this.data = { id: 0, name: "", description: "" } }, save: function() {

我正在开发一款大量使用JavaScript的应用程序。我试图包括一些面向对象的实践。在这次尝试中,我创建了一个基本类,如下所示:

function Item() { this.init(); }
Item.prototype = {
  init: function () {
    this.data = {
      id: 0,
      name: "",
      description: ""     
    }
  },

  save: function() {
    alert("Saving...");
    $.ajax({
      url: getUrl(),
      type: "POST",
      data: JSON.stringify(this.data),
      contentType: "application/json"
    });
  }
}
我正在我的应用程序中创建项目实例,然后将它们保存到本地存储,如下所示:

Item item = new Item();
window.localStorage.setItem("itemKey", JSON.stringify(item));
var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
在另一个页面上,或在另一个时间,我正在从本地存储中检索该项,如下所示:

Item item = new Item();
window.localStorage.setItem("itemKey", JSON.stringify(item));
var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
不幸的是,save函数似乎没有达到。在console窗口中,有一个错误显示:

*单击“保存” 匿名函数 onclick*

我有一种预感,匿名函数是控制台窗口调用item.save的方式,但item是匿名类型,所以我尝试访问匿名函数。我的问题是,我不确定如何将var item再次转换为item类实例。有人能给我看看吗?

简短回答:

无法将函数序列化为JSON

说明:

JSON是一种基于JS文本语法子集的跨平台序列化方案。在这种情况下,它只能存储某些东西。Per:

对象:对象是一组无序的名称/值对。对象以{左大括号开始,以}右大括号结束。每个名称后面跟着:冒号,名称/值对之间用逗号分隔。 数组:数组是值的有序集合。数组以[左括号]开始,以[右括号]结束。值之间用逗号分隔。 值:值可以是双引号中的字符串、数字、true或false或null、对象或数组。这些结构可以嵌套。 函数无法序列化为JSON,因为另一个非JS平台将无法取消序列化并使用它。反过来考虑这个例子。假设我的服务器上有一个PHP对象,其中包含属性和方法。如果我用PHP的json_编码序列化该对象,并且输出中包含方法,那么我的JavaScript如何能够解析和理解方法中的PHP代码,更不用说使用这些方法了

您在生成的JSON中看到的是您正在使用的平台上函数的toString值。JSON序列化程序对任何不适合JSON的被序列化对象调用toString

我相信您的解决方案是停止在JSON/本地存储中存储实例。相反,请保存实例的相关数据,并在需要时将其设置回新实例。

简短回答:

无法将函数序列化为JSON

说明:

JSON是一种基于JS文本语法子集的跨平台序列化方案。在这种情况下,它只能存储某些东西。Per:

对象:对象是一组无序的名称/值对。对象以{左大括号开始,以}右大括号结束。每个名称后面跟着:冒号,名称/值对之间用逗号分隔。 数组:数组是值的有序集合。数组以[左括号]开始,以[右括号]结束。值之间用逗号分隔。 值:值可以是双引号中的字符串、数字、true或false或null、对象或数组。这些结构可以嵌套。 函数无法序列化为JSON,因为另一个非JS平台将无法取消序列化并使用它。反过来考虑这个例子。假设我的服务器上有一个PHP对象,其中包含属性和方法。如果我用PHP的json_编码序列化该对象,并且输出中包含方法,那么我的JavaScript如何能够解析和理解方法中的PHP代码,更不用说使用这些方法了

您在生成的JSON中看到的是您正在使用的平台上函数的toString值。JSON序列化程序对任何不适合JSON的被序列化对象调用toString


我相信您的解决方案是停止在JSON/本地存储中存储实例。相反,保存实例的相关数据,在需要时将其设置回新实例。

您只能将普通对象存储在DOMstorages cookies、urlparams…,所有需要通过JSON.stringify/JSON.parse进行[反]序列化的内容中。那么您在发送ajax数据时做了什么

ajaxsend(this.data);
也适用于字符串序列化。您只能存储数据,不能存储prototype、constructor等实例属性。。所以使用

savestring(JSON.stringify(item.data));
这是可能的,因为item.data是一个简单的对象。当恢复它时,您将只返回该普通数据对象。在您的情况下,很容易从普通数据重建项实例,因为您的项仅在公共可用属性中保留其值:

var item = new Item;
item.data = JSON.parse(getjsonstring());

您只能将普通对象存储在DOMstorages cookies、urlparams…,以及需要通过JSON.stringify/JSON.parse进行[de]序列化的所有内容中。那么您在发送ajax数据时做了什么

ajaxsend(this.data);
也适用于字符串序列化。您只能存储数据,不能存储prototype、constructor等实例属性。。所以 使用

这是可能的,因为item.data是一个简单的对象。当恢复它时,您将只返回该普通数据对象。在您的情况下,很容易从普通数据重建项实例,因为您的项仅在公共可用属性中保留其值:

var item = new Item;
item.data = JSON.parse(getjsonstring());

您不能这样做,javascript怎么可能知道该项具有保存功能?json不允许函数作为数据。只要阅读json规范,就无法保存函数


您需要做的是在要存储的哈希中创建一个序列化和反序列化方法。这将指定要导出的内容以及在解析相应的json字符串后如何唤醒对象。

如果不能这样做,javascript怎么可能知道该项具有保存功能?json不允许函数作为数据。只要阅读json规范,就无法保存函数

您需要做的是在要存储的哈希中创建一个序列化和反序列化方法。这将指定要导出的内容以及在解析相应的json字符串后如何唤醒对象。

免责声明

不是全职的J.S.开发者,answer可能有一些小错误:

冗长乏味的解释

正如@JAAulde所提到的,您的对象不能序列化为JSON,因为它有函数,您使用的技术不允许它

许多人忘记或忽略了应用程序中使用的对象可能与从存储中保存/恢复的对象不完全相同

简短快速的回答

由于您已经将对象的数据成员封装到单个字段中, 您可能想尝试以下方法:

// create J.S. object from prototype
Item item = new Item();

// assign values as you app. logic requires
item.data.name = "John Doe";
item.data.description = "Cool developer, office ladies, love him";

// encoded item into a JSON style string, not stored yet
var encodedItem = JSON.stringify(item.data)

// store string as a JSON string
window.localStorage.setItem("itemKey", encodedItem);

// do several stuff

// recover item from storage as JSON encoded string
var encodedItem = window.localStorage.getItem("itemKey");

// transform into J.S. object
item.data = JSON.parse(encodedItem);

// do other stuff
// get serialized JSON
var itemData = window.localStorage.getItem("itemKey");
//instantiate new Item object
var item = new Item();
// extend item with data
$.extend(item, JSON.parse(itemData));

// this should now work
item.save();
干杯。

免责声明

不是全职的J.S.开发者,answer可能有一些小错误:

冗长乏味的解释

正如@JAAulde所提到的,您的对象不能序列化为JSON,因为它有函数,您使用的技术不允许它

许多人忘记或忽略了应用程序中使用的对象可能与从存储中保存/恢复的对象不完全相同

简短快速的回答

由于您已经将对象的数据成员封装到单个字段中, 您可能想尝试以下方法:

// create J.S. object from prototype
Item item = new Item();

// assign values as you app. logic requires
item.data.name = "John Doe";
item.data.description = "Cool developer, office ladies, love him";

// encoded item into a JSON style string, not stored yet
var encodedItem = JSON.stringify(item.data)

// store string as a JSON string
window.localStorage.setItem("itemKey", encodedItem);

// do several stuff

// recover item from storage as JSON encoded string
var encodedItem = window.localStorage.getItem("itemKey");

// transform into J.S. object
item.data = JSON.parse(encodedItem);

// do other stuff
// get serialized JSON
var itemData = window.localStorage.getItem("itemKey");
//instantiate new Item object
var item = new Item();
// extend item with data
$.extend(item, JSON.parse(itemData));

// this should now work
item.save();

干杯。

我知道这个问题已经得到了回答,但是我无意中发现了这个问题,如果有人感兴趣,我想分享这个问题的解决方案

而不是这样做:

var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
这样做:

// create J.S. object from prototype
Item item = new Item();

// assign values as you app. logic requires
item.data.name = "John Doe";
item.data.description = "Cool developer, office ladies, love him";

// encoded item into a JSON style string, not stored yet
var encodedItem = JSON.stringify(item.data)

// store string as a JSON string
window.localStorage.setItem("itemKey", encodedItem);

// do several stuff

// recover item from storage as JSON encoded string
var encodedItem = window.localStorage.getItem("itemKey");

// transform into J.S. object
item.data = JSON.parse(encodedItem);

// do other stuff
// get serialized JSON
var itemData = window.localStorage.getItem("itemKey");
//instantiate new Item object
var item = new Item();
// extend item with data
$.extend(item, JSON.parse(itemData));

// this should now work
item.save();
只要你想调用ie,save的函数是原型,而不是一个实例方法,它就可以正常工作。通常情况下,OP的原始问题就是这样


$.extend方法是jquery的一种实用方法,但是您自己的方法并不重要。

我知道这个问题已经得到了回答,但是我无意中发现了这个问题,如果有人感兴趣的话,我想分享这个问题的解决方案

而不是这样做:

var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();
这样做:

// create J.S. object from prototype
Item item = new Item();

// assign values as you app. logic requires
item.data.name = "John Doe";
item.data.description = "Cool developer, office ladies, love him";

// encoded item into a JSON style string, not stored yet
var encodedItem = JSON.stringify(item.data)

// store string as a JSON string
window.localStorage.setItem("itemKey", encodedItem);

// do several stuff

// recover item from storage as JSON encoded string
var encodedItem = window.localStorage.getItem("itemKey");

// transform into J.S. object
item.data = JSON.parse(encodedItem);

// do other stuff
// get serialized JSON
var itemData = window.localStorage.getItem("itemKey");
//instantiate new Item object
var item = new Item();
// extend item with data
$.extend(item, JSON.parse(itemData));

// this should now work
item.save();
只要你想调用ie,save的函数是原型,而不是一个实例方法,它就可以正常工作。通常情况下,OP的原始问题就是这样


$.extend方法是jquery的一种实用方法,但是你自己使用它是很简单的。

有什么特别的原因来尝试模仿经典模式而不仅仅是使用原型模式吗?我不知道原型模式是什么。是的,我的错。我实际上是想说原型继承成语。什么是原型继承成语?你有链接吗?我在谷歌上搜索的时候运气不好。有没有什么特别的理由来模仿经典模式而不仅仅是使用原型模式?我不知道原型模式是什么。是的,我的错。我实际上是想说原型继承成语。什么是原型继承成语?你有链接吗?我在谷歌上搜索了它,但运气不好。OP不存储实例,也没有任何函数。他只想知道如何从他的数据中重新实例化一个项目。@Bergi一点也不正确。她明确表示她有一个带有方法的对象实例,尝试JSON序列化然后取消序列化,并且在取消序列化的一侧丢失了方法。我提出的解决方案可能无法完全解决如何序列化JS对象W/方法,但我清楚地说明了她的方法有什么问题,并提出了我认为是一个更好的方法去做它。我看过ajax函数,OP不存储实例,也没有函数。他只想知道如何从他的数据中重新实例化一个项目。@Bergi一点也不正确。她明确表示她有一个带有方法的对象实例,尝试JSON序列化然后取消序列化,并且在取消序列化的一侧丢失了方法。我提出的解决方案可能无法完全解决如何用方法序列化JS对象的问题,但我清楚地说明了她的方法的错误,并建议
我认为这是一个更好的方法。我明白了。我已经看过ajax函数了。