json.stringify不处理对象方法

use*_*759 21 javascript json local-storage

我正在尝试开发一个适用于大多数现代浏览器(Chrome,Firefox,IE 9 +,Safari,Opera)的离线HTML5应用程序.由于Safari尚未支持IndexedDB,并且不推荐使用WebSQL,因此我决定使用localStorage来存储用户生成的JavaScript对象和JSON.stringify()/ JSON.parse()以放入或拔出对象.但是,我发现JSON.stringify()不处理方法.这是一个带有简单方法的示例对象:

    var myObject = {};
    myObject.foo = 'bar';
    myObject.someFunction = function () {/*code in this function*/}
Run Code Online (Sandbox Code Playgroud)

如果我对这个对象进行字符串化(后来将其放入localStorage),那么所有将保留的对象myObject.foo都不是myObject.someFunction().

    //put object into localStorage
    localStorage.setItem('myObject',JSON.stringify(myObject));

    //pull it out of localStorage and set it to myObject
    myObject = localStorage.getItem('myObject');

    //undefined!
    myObject.someFunction
Run Code Online (Sandbox Code Playgroud)

我相信你们中的许多人可能已经知道这个限制/功能/无论你想要什么.我提出的解决方法是使用methods(myObject = new objectConstructor())创建一个对象,从localStorage中提取对象属性,并将它们分配给我创建的新对象.我觉得这是一个迂回的方法,但我是JavaScript世界的新手,所以这就是我解决它的方法.所以这是我的大问题:我希望将整个对象(属性+方法)包含在localStorage中.我该怎么做呢?如果您可以向我展示一个更好的算法,或者我可能不知道的其他JSON方法,我将非常感激.

Ale*_*yne 37

javascript中的函数不仅仅是他们的代码.他们也有范围.代码可以进行字符串化,但范围不能.

JSON.stringify()将编码JSON支持的值.具有可以是对象,数组,字符串,数字和布尔值的值的对象.其他任何内容都将被忽略或抛出错误.函数不是JSON中受支持的实体.JSON仅处理纯数据,函数不是数据,而是具有更复杂语义的行为.


那说你可以改变JSON.stringify()工作方式.第二个参数是一个replacer函数.所以你可以通过强制函数的强制来强制你想要的行为:

var obj = {
  foo: function() {
    return "I'm a function!";
  }
};

var json = JSON.stringify(obj, function(key, value) {
  if (typeof value === 'function') {
    return value.toString();
  } else {
    return value;
  }
});

console.log(json);
// {"foo":"function () { return \"I'm a function!\" }"}
Run Code Online (Sandbox Code Playgroud)

但是当你读回来时,你必须评估函数字符串并将结果设置回对象,因为JSON 不支持函数.


JSON中的所有编码功能都可以变得非常毛茸茸.你确定你要这么做吗?可能有更好的方法......

也许您可以保存原始数据,并将其传递给页面上加载的JS中的构造函数.localStorage只会保存数据,但是加载到页面上的代码将提供操作该数据的方法.

// contrived example...

var MyClass = function(data) {
  this.firstName = data.firstName;
  this.lastName = data.lastName;
}

MyClass.prototype.getName() {
  return this.firstName + ' ' + this.lastName;
}

localStorage.peopleData = [{
  firstName: 'Bob',
  lastName:  'McDudeFace'
}];

var peopleData = localStorage.peopleData;

var bob = new MyClass(peopleData[0]);
bob.getName() // 'Bob McDudeFace'
Run Code Online (Sandbox Code Playgroud)

我们不需要将getName()方法保存到localStorage.我们只需要将该数据提供给将提供该方法的构造函数.

  • 好的,我明白你在说什么。我只是想看看有没有我遗漏的东西。我最终只会存储数据并将该数据传递给构造函数。感谢您解决这个问题! (2认同)