1

我正在开发一个大量使用 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 item = new Item();
window.localStorage.setItem("itemKey", JSON.stringify(item));

在另一个页面上,或者在另一个时间,我正在从本地存储中检索该项目,如下所示:

var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();

不幸的是,似乎没有达到“保存”功能。在控制台窗口中,有一条错误提示:

*save_Click(匿名函数)onclick*

我有一种预感,“(匿名函数)”是控制台窗口的表达方式“调用 item.save(),但 item 是匿名类型,所以我正在尝试访问匿名函数”。我的问题是,我不确定如何再次将“var item”转换为 Item 类实例。有人可以告诉我吗?

4

5 回答 5

3

简短的回答:

函数不能序列化为 JSON。

解释:

JSON 是一种基于 JS 文字语法子集的跨平台序列化方案。既然如此,它只能存储某些东西。根据http://www.json.org/

  • 对象:对象是一组无序的名称/值对。对象以 {(左大括号)开始,以 }(右大括号)结束。每个名称后跟 :(冒号),名称/值对用 ,(逗号)分隔。
  • 数组:数组是值的有序集合。数组以 [(左括号)开头,以 ](右括号)结尾。值用 ,(逗号)分隔。
  • values:值可以是双引号中的字符串,也可以是数字,也可以是 true 或 false 或 null,也可以是对象或数组。这些结构可以嵌套。

函数无法序列化为 JSON,因为另一个非 JS 平台将无法反序列化和使用它。反过来考虑这个例子。假设我的服务器上有一个 PHP 对象,其中包含属性和方法。如果我用 PHP 序列化该对象,json_encode()并且输出中包含方法,我的 JavaScript 将如何解析和理解方法中的 PHP 代码,更不用说使用这些方法了?

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

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

于 2012-04-27T12:45:43.883 回答
2

我知道这个问题已经得到解答,但是我偶然发现了这个问题,如果有人感兴趣,我想分享一个解决这个问题的方法。

而不是这样做:

var item = window.localStorage.getItem("itemKey");
item = JSON.parse(item);
item.save();

做这样的事情:

// 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();

只要您要调用的函数(即 save())是原型而不是实例方法(通常是这种情况,并且确实是 OP 的原始问题中的情况),这将起作用。

$.extend方法是jquery的实用方法,但自己滚动很简单。

于 2013-03-12T23:17:33.010 回答
0

您只能将普通对象存储在 DOMstorages 中(cookies、urlparams...、所有需要通过JSON.stringify/进行序列化的东西JSON.parse)。那么你在发送ajax数据时做了什么

ajaxsend(this.data);

也适用于字符串序列化。您只能存储数据,不能存储实例属性(如原型、构造函数等)。所以使用

savestring(JSON.stringify(item.data));

这是可能的,因为它item.data是一个普通的对象。而当恢复它时,你只会得到那个纯数据对象。在您的情况下,很容易Item从纯数据重建实例,因为您的 Items 将它们的值(仅)保存在公共可用属性中:

var item = new Item;
item.data = JSON.parse(getjsonstring());
于 2012-04-27T12:46:55.480 回答
0

你不能那样做,javascript怎么可能知道那个项目有保存功能?json 不允许函数作为数据。只需阅读 json 规范,您无法保存函数。

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

于 2012-04-27T12:47:07.573 回答
0

免责声明

不是全职 JS 开发者,答案可能有一些小错误:

长无聊的解释

正如@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

干杯。

于 2012-04-27T17:11:54.237 回答