javascript json.stringify 不处理对象方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/18089033/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 10:42:11  来源:igfitidea点击:

json.stringify does not process object methods

javascriptjsonlocal-storage

提问by user2649759

I am trying to develop an offline HTML5 application that should work in most modern browsers (Chrome, Firefox, IE 9+, Safari, Opera). Since IndexedDB isn't supported by Safari (yet), and WebSQL is deprecated, I decided on using localStorage to store user-generated JavaScript objects and JSON.stringify()/JSON.parse()to put in or pull out the objects. However, I found out that JSON.stringify()does not handle methods. Here is an example object with a simple method:

我正在尝试开发一个可以在大多数现代浏览器(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*/}

If I stringify this object (and later put it into localStorage), all that will be retained is myObject.foo, not myObject.someFunction().

如果我对该对象进行字符串化(然后将其放入 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

I'm sure many of you probably already know of this limitation/feature/whatever you want to call it. The workaround that I've come up with is to create an object with the methods(myObject = new objectConstructor()), pull out the object properties from localStorage, and assign them to the new object I created. I feel that this is a roundabout approach, but I'm new to the JavaScript world, so this is how I solved it. So here is my grand question: I'd like the whole object (properties + methods) to be included in localStorage. How do I do this? If you can perhaps show me a better algorithm, or maybe another JSON method I don't know about, I'd greatly appreciate it.

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

回答by Alex Wayne

Functions in javascript are more than just their code. They also have scope. Code can be stringified, but scope cannot.

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

JSON.stringify()will encode values that JSON supports. Objects with values that can be objects, arrays, strings, numbers and booleans. Anything else will be ignored or throw errors. Functions are not a supported entity in JSON. JSON handles pure data only, functions are not data, but behavior with more complex semantics.

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



That said you can change how JSON.stringify()works. The second argument is a replacerfunction. So you could force the behavior you want by forcing the strinigification of functions:

也就是说,您可以更改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!\" }"}

But when you read that back in you would have to eval the function string and set the result back to the object, because JSON does not support functions.

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



All in all encoding functions in JSON can get pretty hairy. Are you sure you want to do this? There is probably a better way...

总而言之,JSON 中的所有编码函数都会变得非常麻烦。你确定要这么做吗?可能有更好的方法......

Perhaps you could instead save raw data, and pass that to a constructor from your JS loaded on the page. localStoragewould only hold the data, but your code loaded onto the page would provide the methods to operate on that data.

也许您可以改为保存原始数据,并将其从加载到页面上的 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'

We don't need to save the getName()method to localStorage. We just need to feed that data into a constructor that will provide that method.

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

回答by Miguel del Mazo

If you want to stringify your objects, but they have functions, you can use JSON.stringify()with the second parameter replacer. To prevent cyclic dependencies on objects you can use a var cache = [].

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

In our project we use lodash. We use the following function to generate logs. Can be used it to save objects to localStorage.

在我们的项目中,我们使用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>

回答by iAmOren

Does not fix functions as requested, but a way to store variables locally...

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

<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>

Keep all variables in object g. Example:

将所有变量保存在 object 中g。例子:

  g.arr=[1,2,3];
  • note some types, such as Date, you'll need to do something like:
  • 请注意某些类型,例如Date,您需要执行以下操作:
  g.date=new Date(g.date);
  • stores locally per page: different pages have different gs
  • 每页本地存储:不同的页面有不同的gs