1

I am stuck with a greater JavaScript application (using jQuery Mobile) with big parts of the program logic realized already. Now I want to add serialization to it (using a plugin called JStorage). In this code example, I stringify an object to JSON and then turn it into an object again (all without JStorage), but the methods I added to the original object get lost as in this code:

function TestObject() {
    this.lang = "English";
}

// This is the method I want to keep
TestObject.prototype.showLang = function() {
    console.log(this.lang)
};

var test1 = new TestObject();
var test2 = $.parseJSON(JSON.stringify(test1)); // After save and reload
test1.showLang(); // This works
test2.showLang(); // This causes an error

The problem has one other constraint: In the code, I often use the point operator to call functions as in test1.showLang(). I know I could add a "global" function like this, it works with the original as well as with the copy:

function showLang(obj) {
    console.log(obj.lang);
}

But then I'd have to change each and every existing call to the function from test1.showLang() to showLang(test1) which - in my real project - I would have to do hundreds of times within the entire code. So is there an easier solution how I can use my existing functions on objects after serialization?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131

2 Answers2

1

As far as I am aware JSON does not have the capacity to serialize methods and then deserialize them. It is used primarily for DTOs (data transfer objects), not object brokering.

A side note is the fact that if JSON does support it, it could be quiet a significant security hole.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
RabidDog5150
  • 101
  • 6
  • I know, and I do not want to serialize the method. JSON serializes the variables only, and $.parseJSON() puts them into a new object again. But how can I use TestObject.prototype.showLang() for object test2? – user3742403 Nov 24 '14 at 13:28
0

You could change your TestObject constructor function so that it can accept an object containing optional initial values for all its properties:

function TestObject(properties) {
    this.lang = (properties && !(properties.lang === undefined)) ? properties.lang : "English";
}

And then use your deserialised object to create a new object using the constructor function, instead of using the deserialised object directly:

var test2 = new TestObject( $.parseJSON(JSON.stringify(test1)) );

This seems to work: http://jsfiddle.net/wubfckez/

Paul D. Waite
  • 96,640
  • 56
  • 199
  • 270
  • 1
    I put your solution into practice in my project and it worked, however I had to do tons of changes in the code because I need to rewrite each single constructor and since my objects can be nested (include other objects) that can be tricky to do. So thanks, but if someone has another solution that requires less changes I'd love to hear about it for the future. – user3742403 Nov 27 '14 at 17:28
  • @user3742403: glad to hear it worked. In some browsers you can change an object’s prototype after it’s created (I believe using the `__proto__` property), but as far as I can tell, this is unlikely to become a standard JavaScript feature in the future. – Paul D. Waite Nov 27 '14 at 19:07
  • Then I'll continue using prototype. Just one more thing: The code you posted seems to work fine for strings but integers (if 0) and booleans (if false) may become a problem because the "||" operator would then behave is if the integer/boolean was undefined. In that cases I'd prefer: this.myInt = (properties && typeof properties.myInt !== 'undefined') ? properties.myInt : 55; If properties.myInt is undefined, 55 will be used, if properties.myInt is 0 or another number, that number will be used. – user3742403 Nov 27 '14 at 20:03
  • @user3742403: oh of course, I hadn’t thought of that, very good point. I’ll amend my answer accordingly. – Paul D. Waite Nov 27 '14 at 23:25
  • @user3742403: It might be worth writing a function that loops through all the properties of an object, and assigns them as identically-named properties of another object (i.e. an object merge function). Lots of frameworks have such functions; e.g. in Underscore, it’s the “extend” function. – Paul D. Waite Nov 27 '14 at 23:33