json.stringfy不处理对象方法

json.stringify does not process object methods

本文关键字:对象 方法 处理 stringfy json      更新时间:2023-09-26

我正在尝试开发一个离线HTML5应用程序,该应用程序应该适用于大多数现代浏览器(Chrome、Firefox、IE 9+、Safari、Opera)。由于Safari还不支持IndexedDB,而且WebSQL也不受欢迎,所以我决定使用localStorage来存储用户生成的JavaScript对象,并使用JSON.stringify()/JSON.parse()来放入或取出对象。但是,我发现JSON.stringify()不处理方法。下面是一个带有简单方法的示例对象:

    var myObject = {};
    myObject.foo = 'bar';
    myObject.someFunction = function () {/*code in this function*/}

如果我将这个对象字符串化(稍后将其放入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

我相信你们中的许多人可能已经知道这个限制/功能/你想怎么称呼它。我想出的解决办法是用方法(myObject = new objectConstructor())创建一个对象,从localStorage中提取对象属性,并将它们分配给我创建的新对象。我觉得这是一种迂回的方法,但我是JavaScript世界的新手,所以我就是这样解决的。所以我的大问题是:我希望整个对象(属性+方法)都包含在localStorage中。我该怎么做?如果你能给我看一个更好的算法,或者另一个我不知道的JSON方法,我将不胜感激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!'" }"}

但是,当您读回来时,您必须评估函数字符串并将结果设置回对象,因为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'

我们不需要将getName()方法保存到localStorage。我们只需要将数据输入一个构造函数,该构造函数将提供该方法。

如果您想字符串化对象,但它们有函数,可以将JSON.stringify()与第二个参数replacer一起使用。为了防止对对象的循环依赖,可以使用var cache = []

在我们的项目中,我们使用lodash。我们使用以下函数来生成日志。可以使用它将对象保存到localStorage

var stringifyObj = function(obj) {
  var cache = []
  return JSON.stringify(obj, function(key, value) {
    if (
      _.isString(value) ||
      _.isNumber(value) ||
      _.isBoolean(value)
    ) {
      return value
    } else if (_.isError(value)) {
      return value.stack || ''
    } else if (_.isPlainObject(value) || _.isArray(value)) {
      if (cache.indexOf(value) !== -1) {
        return
      } else {
        // cache each item 
        cache.push(value)
        return value
      }
    }
  })
}
// create a circular object
var circularObject = {}
circularObject.circularObject = circularObject
// stringify an object
$('body').text(
  stringifyObj(
    {
      myBooblean: true,
      myString: 'foo',
      myNumber: 1,
      myArray: [1, 2, 3],
      myObject: {},
      myCircularObject: circularObject,
      myFunction: function () {}
    }
  )
)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

不按请求修复函数,而是一种本地存储变量的方法。。。

<html>
  <head>
    <title>Blank</title>
    <script>
      if(localStorage.g===undefined) localStorage.g={};
      var g=JSON.parse(localStorage.g);
    </script>
  </head>
  <body>
    <input type=button onClick="localStorage.g=JSON.stringify(g, null, '  ')" value="Save">
    <input type=button onClick="g=JSON.parse(localStorage.g)" value="Load">
  </body>
</html>

将所有变量保留在对象g中。示例:

  g.arr=[1,2,3];
  • 注意某些类型,例如Date,您需要执行以下操作:
  g.date=new Date(g.date);
  • 按页面本地存储:不同的页面具有不同的g