Utilisation de JSON.stringify sur classe personnalisée

J'essaie de stocker un objet dans redis, qui est une instance d'une classe, et a donc des fonctions, voici un exemple:

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

Existe-t-il un moyen de stocker cet objet en redis, ainsi que les fonctions? J'ai essayé JSON.stringify() mais seules les propriétés sont préservées. Comment puis-je stocker les définitions de fonction et pouvoir effectuer quelque chose comme suit:

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

Comment puis-je obtenir foo en appelant parsedObj.getAttr() ?

Merci d'avance!

MODIFIER

Vous avez une suggestion pour modifier le MyClass.prototype et stocker les valeurs, mais qu'en est-il de quelque chose comme ça (fonctions autres que setter / getter):

 function myClass(){ this._attr = "foo"; this._accessCounts = 0; this.getAttr = function(){ this._accessCounts++; return this._attr; } this.getCount = function(){ return this._accessCounts; } } 

J'essaie d'illustrer une fonction qui calcule quelque chose comme un compte ou une moyenne chaque fois qu'on l'appelle, en dehors de faire d'autres choses.

D'abord, vous ne définissez pas de classe.

C'est juste un objet, avec une propriété dont la valeur est une fonction (Toutes ses fonctions membres définies dans le constructeur seront copiées lors de la création d'une nouvelle instance , c'est pourquoi je dis que ce n'est pas une classe.)

Ce qui sera éliminé lors de l'utilisation de JSON.stringify .

Considérons que vous utilisez node.js qui utilise V8, la meilleure façon est de définir une classe réelle et de jouer un peu de magie avec __proto__ . Ce qui fonctionnera bien, peu importe le nombre de propriétés que vous avez utilisées dans votre classe (tant que chaque propriété utilise des types de données primitives).

Voici un exemple:

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

Qui produira:

 true "foo" 

Non, JSON ne stocke pas les fonctions (ce qui serait assez inefficace aussi). Au lieu de cela, utilisez une méthode de sérialisation et un constructeur de désérialisation. Exemple:

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

Scanales, j'ai eu le même problème et j'ai essayé une technique similaire à la recommandation de Bergi de créer de nouvelles méthodes de sérialisation / désérialisation … mais j'ai trouvé que cela ne fonctionnait pas pour moi parce que j'ai des objets imbriqués dans des objets (plusieurs en profondeur). Si c'est votre cas, voici comment je l'ai résolu. J'ai écrit une classe de base (clsPersistableObject) à partir de laquelle tous les objets dont je voulais persister héritent. La classe de base a une méthode appelée désérialiser, qui passe la chaîne JSON. Cette méthode définit les propriétés un par un (mais ne supprime pas les méthodes existantes) puis renvoie récursivement à l'objet enfant pour faire la même chose (autant de fois que nécessaire).

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

Ce que vous obtenez, grom JSON.stringify () est une chaîne. Une chaîne n'a pas de méthodes. Vous devez d'abord numéroter cette chaîne et ensuite vous pourrez obtenir l'objet original et ses méthodes.

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

—- MODIFIER —–

 //Sorry use this: var getBackObj = JSON.parse(stringObj); //Not this var getBackObj = eval(stringObj); console.log(getBackObj.getAttr()); // this should work now 

Il semble que vous essayez de restreindre une fonction fermée. Vous pouvez utiliser () => {} pour résoudre le problème de portée.

 function myClass(){ this._attr = "foo"; this._accessCounts = 0; this.getAttr = ()=>{ this._accessCounts++; return this._attr; } this.getCount = ()=>{ return this._accessCounts; } }