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