1

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!

2
  • This is not related to prototypical inheritance. If you want to transfer data along the wire, you need to serialize them. Serializing functions is not exactly trivial. Commented Dec 19, 2012 at 6:04
  • I don't think I want to serialize them, just use them both places. I have definitions for the functions on both client and server, I want to be able to say foo.someMethod() on the client, pass the object over to the server, and add the methods back from the server's copy of their definitions. Commented Dec 19, 2012 at 6:12

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

Now.js looks like it could help me out a lot! Thanks for your help.
@ZachHall It appears that the now.js project has been abandoned by its developers (despite being very promising) - I wonder if there's a suitable replacement for it. groups.google.com/forum/?fromgroups=#!topic/nowjs/FZXWZr22vn8

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.