7

我试图在redis中存储一个对象,它是一个类的实例,因此具有功能,这是一个例子:

function myClass(){
    this._attr = "foo";
    this.getAttr = function(){
        return this._attr;
    }
}

有没有办法将此对象与函数一起存储在 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'"

foo打电话的时候怎么接parsedObj.getAttr()

先感谢您!

编辑

有人建议修改 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;
    }
}

我试图说明一个函数,它在调用时计算诸如计数或平均值之类的东西,除了做其他事情。

4

5 回答 5

10

首先,您没有定义一个类。

它只是一个对象,其属性的值是一个函数(它在构造函数中定义的所有成员函数将在创建新实例时被复制,这就是为什么我说它不是一个类。)

使用时会被剥离JSON.stringify

考虑到您使用的是使用 V8 的 node.js,最好的方法是定义一个真实的类,并使用__proto__. 无论您在类中使用了多少属性(只要每个属性都使用原始数据类型),哪个都可以正常工作。)

这是一个例子:

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

这将输出:

true "foo"
于 2012-11-27T18:12:12.947 回答
4

不,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;
};
于 2012-11-27T18:06:21.723 回答
0

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

            }
于 2013-04-27T12:18:57.487 回答
-1

看起来你试图对一个封闭的函数进行字符串化。您可以使用 ()=>{} 来解决范围问题。

function myClass(){
    this._attr = "foo";
    this._accessCounts = 0;
    this.getAttr = ()=>{
        this._accessCounts++;
        return this._attr;
    }
    this.getCount = ()=>{
        return this._accessCounts;
    }
}
于 2016-12-13T07:21:13.680 回答
-3

你得到的 grom JSON.stringify() 是一个字符串。字符串没有方法。您需要先评估该字符串,然后才能获取原始对象及其方法。

var myObj = new myClass();
var stringObj = JSON.stringify(myObj);

- - 编辑 - - -

//Sorry use this:
var getBackObj  = JSON.parse(stringObj);
//Not this
var getBackObj = eval(stringObj);

console.log(getBackObj.getAttr()); // this should work now
于 2012-11-27T17:52:10.160 回答