Reputation: 209
I have a Javascript library that I want to use on a web browser and also on a Node.js backend. In the library, I have multiple objects with methods defined like so:
function foo() {
this.bar = 200;
this.someMethod = function(baz) {
return this.bar + baz;
};
}
var x = new foo();
And I can use it in the client or the Node.js server by doing the following:
x.someMethod(5);
=> (returns 205)
Now, when I JSON.stringify
my object, it shows up without the method.
var string = JSON.stringify(x);
=> {"bar":200}
Which means I can't unpack the JSON on my server and use the same methods.
var parsed = JSON.parse(string);
document.write(parsed.someMethod(5));
=> (doesn't do anything. the methods are gone!)
In a class based system I'd just use a copy constructor. Something that would reconstruct the object from JSON.
function foo_copy_constructor(parsed_json) {
f = new foo();
f.bar = parsed_json.bar;
return f;
}
var z = foo_copy_constructor(parsed);
z.someMethod(5);
=> (returns 205 like it should)
( jsfiddle: http://jsfiddle.net/7FdDe/ )
Basically, Is there a better way than this?
Many of my objects contain instances of other objects I've written with their own methods, and this seems like it would get tedious to build a constructor for every object since both the client and the server use the same library and object definitions. I know that JavaScript is based on prototypes, but I don't really understand them since I've just started with JavaScript and am used to Python and class-based languages.
Thanks for any and all help!
Upvotes: 1
Views: 400
Reputation: 60767
JSON.stringify
only stringifies the objects that have the toJSON
method. So you could simply add the toJSON
method to your methods. (Remember, functions are objects too.)
function A() {
this.method = function() { console.log(1); };
}
var c = new A();
JSON.stringify(c);
"{}"
A.prototype.otherMethod = function() { console.log(1); };
var c = new A();
JSON.stringify(c);
"{}"
Function.prototype.toJSON = function() { return this.toString(); };
JSON.stringify(c);
"{"method":"function () { console.log(1); }"}"
However, when parsing this back, you get the function as a string. So you have to the strings back to functions with something like this:
var d = JSON.parse(JSON.stringify(c));
Object.keys(d).forEach(function(k) {
// If it starts with "function"
if (/^function/.test(d[k])) {
// Get the body of the function
var f = d[k].match(/{(.*)}/).pop();
// Replace the string with a real function
d[k] = new Function(f);
}
});
d.method();
1
However, instead of messing with javascript like this, I'd rather suggest that you use a well-tested library like now.js.
Upvotes: 1