Javascript 在自定义类上使用 JSON.stringify
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13589880/
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
Using JSON.stringify on custom class
提问by scanales
I'm trying to store an object in redis, which is an instance of a class, and thus has functions, here's an example:
我正在尝试在 redis 中存储一个对象,它是一个类的实例,因此具有函数,这是一个示例:
function myClass(){
this._attr = "foo";
this.getAttr = function(){
return this._attr;
}
}
Is there a way to store this object in redis, along with the functions? I tried JSON.stringify()but only the properties are preserved. How can I store the function definitions and be able to perform something like the following:
有没有办法将这个对象和函数一起存储在 redis 中?我试过了,JSON.stringify()但只保留了属性。如何存储函数定义并能够执行如下操作:
var myObj = new myClass();
var stringObj = JSON.stringify(myObj);
// store in redis and retreive as stringObj again
var parsedObj = JSON.parse(stringObj);
console.log(myObj.getAttr()); //prints foo
console.log(parsedObj.getAttr()); // prints "Object has no method 'getAttr'"
How can I get foowhen calling parsedObj.getAttr()?
我怎样才能foo打电话时parsedObj.getAttr()?
Thank you in advance!
先感谢您!
EDIT
编辑
Got a suggestion to modify the MyClass.prototype and store the values, but what about something like this (functions other than setter/getter):
得到了修改 MyClass.prototype 并存储值的建议,但是像这样的东西(除 setter/getter 之外的函数)怎么样:
function myClass(){
this._attr = "foo";
this._accessCounts = 0;
this.getAttr = function(){
this._accessCounts++;
return this._attr;
}
this.getCount = function(){
return this._accessCounts;
}
}
I'm trying to illustrate a function that calculates something like a count or an average whenever it is called, apart from doing other stuff.
我试图说明一个函数,它在调用时计算诸如计数或平均值之类的东西,除了做其他事情。
回答by xiaoyi
First, you are not defining a class.
首先,你没有定义一个类。
It's just an object, with a property whose value is a function (All its member functions defined in constructor will be copiedwhen create a new instance, that's why I say it's not a class.)
它只是一个对象,其属性的值是一个函数(它在构造函数中定义的所有成员函数在创建新实例时都会被复制,这就是为什么我说它不是类的原因。)
Which will be stripped off when using JSON.stringify.
使用JSON.stringify.
Consider you are using node.js which is using V8, the best way is to define a real class, and play a little magic with __proto__. Which will work fine no matter how many property you used in your class (as long as every property is using primitive data types.)
考虑到您使用的是使用 V8 的 node.js,最好的方法是定义一个真正的类,并使用__proto__. 无论您在类中使用多少个属性,这都可以正常工作(只要每个属性都使用原始数据类型。)
Here is an example:
下面是一个例子:
function MyClass(){
this._attr = "foo";
}
MyClass.prototype = {
getAttr: function(){
return this._attr;
}
};
var myClass = new MyClass();
var json = JSON.stringify(myClass);
var newMyClass = JSON.parse(json);
newMyClass.__proto__ = MyClass.prototype;
console.log(newMyClass instanceof MyClass, newMyClass.getAttr());
which will output:
这将输出:
true "foo"
回答by Bergi
No, JSON does not store functions (which would be quite inefficient, too). Instead, use a serialisation method and a deserialisation constructor. Example:
不,JSON 不存储函数(这也会非常低效)。相反,使用序列化方法和反序列化构造函数。例子:
function MyClass(){
this._attr = "foo";
this.getAttr = function(){
return this._attr;
}
}
MyClass.prototype.toJSON() {
return {attr: this.getAttr()}; // everything that needs to get stored
};
MyClass.fromJSON = function(obj) {
if (typeof obj == "string") obj = JSON.parse(obj);
var instance = new MyClass;
instance._attr = obj.attr;
return instance;
};
回答by Ian Ippolito
Scanales, I had the same issue and tried a technique similar to Bergi's recommendation of creating new serialization/deserialization methods...but found it didn't work for me because I have objects nested in objects (several deep). If that's your case then here's how I solved it. I wrote a base class (clsPersistableObject) from which all objects that I wanted to persist inherited from. The base class has a method called deserialize, which is passed the JSON string. This method sets the properties one by one (but does not wipe out the exist methods) and then recursively defer to the child object to do the same (as many times as necessary).
Scanales,我遇到了同样的问题,并尝试了一种类似于 Bergi 推荐的创建新序列化/反序列化方法的技术......但发现它对我不起作用,因为我有对象嵌套在对象中(几个深)。如果那是你的情况,那么这就是我解决它的方法。我写了一个基类 (clsPersistableObject),我想从它继承的所有对象。基类有一个名为 deserialize 的方法,它传递 JSON 字符串。此方法一一设置属性(但不会清除现有方法),然后递归地遵循子对象执行相同操作(根据需要多次)。
deserialize: function (vstrString) {
//.parse: convert JSON string to object state
//Use JSON to quickly parse into temp object (does a deep restore of all properties)
var tmpObject = JSON.parse(vstrString);
//objZoo2.animal.move();
//Note: can't just do something like this:
// CopyProperties(tmpObject, this);
//because it will blindly replace the deep objects
//completely...inadvertently wiping out methods on it. Instead:
//1) set the properties manually/one-by-one.
//2) on objects, defer to the deserialize on the child object (if it inherits clsPersistableObject)
//2b) if it doesn't inherit it, it's an intrinsic type, etc...just do a JSON parse.
//loop through all properties
var objProperty;
for (objProperty in tmpObject) {
//get property name and value
var strPropertyName = objProperty;
var strPropertyValue = tmpObject[objProperty]; //note: doing this .toString() will cause
if (objProperty !== undefined) {
//check type of property
if (typeof strPropertyValue == "object") {
//object property: call it recursively (and return that value)
var strPropertyValue_AsString = JSON.stringify(strPropertyValue);
//see if has a deserialize (i.e. inherited from clsPeristableObject)
if ("deserialize" in this[objProperty]) {
//yes: call it
this[objProperty]["deserialize"](strPropertyValue_AsString);
}
else {
//no: call normal JSON to deserialize this object and all below it
this[objProperty] = JSON.parse(strPropertyValue_AsString);
} //end else on if ("deserialize" in this[objProperty])
}
else {
//normal property: set it on "this"
this[objProperty] = tmpObject[objProperty];
} //end else on if (typeof strPropertyValue == "object")
} //end if (objProperty !== undefined)
}
}
回答by Cery
it looks like you attempt to stringify a closed function. you can use ()=>{} to solve the scope problem.
看起来您试图对一个封闭的函数进行字符串化。您可以使用 ()=>{} 来解决范围问题。
function myClass(){
this._attr = "foo";
this._accessCounts = 0;
this.getAttr = ()=>{
this._accessCounts++;
return this._attr;
}
this.getCount = ()=>{
return this._accessCounts;
}
}
回答by kante
What you get back grom JSON.stringify() is a String. A string has no methods. You need to eval first that string and then you'll be able to get the original object and its methods.
你从 JSON.stringify() 中得到的是一个字符串。字符串没有方法。您需要先评估该字符串,然后才能获得原始对象及其方法。
var myObj = new myClass();
var stringObj = JSON.stringify(myObj);
---- EDIT -----
- - 编辑 - - -
//Sorry use this:
var getBackObj = JSON.parse(stringObj);
//Not this
var getBackObj = eval(stringObj);
console.log(getBackObj.getAttr()); // this should work now

