3

My final task is to fully recover object previously saved using JSON. For now JSON only allows to recover data, but not behaviour. A possilbe solution is to create a new object (lets call it obj) and copy data from JSON-recovered-object to obj. But it doesn't look nice for me. What I am asking, is there a way to dynamically change object prototype in JavaScript?

It's how I solve problem at the moment (using self-made copy method):

(this code on JSFiddle)

function Obj() {
    this.D = "D";
    this.E = "E";
    this.F = "F";

    this.toString = function () {
        return this.D + " * " + this.E + " * " + this.F;
    };

    this.copy = function (anotherObj) {
        for (var property in anotherObj) {
            if (isDef(anotherObj[property]) && isDef(this[property])) {
                this[property] = anotherObj[property];
            }
        }
    }
}
;

$(document).ready(function () {
    var str = $.toJSON(new Obj());
    $("#result").append("<p>JSON: " + str + "</p>");
    var obj = new Obj();
    obj.copy($.parseJSON(str));
    $("#result").append("<p>Recovered obj: " + obj.toString() + "</p>");
});

function isDef(variable)
{
    return typeof variable !== undefined;
}

1 Answer 1

4

There are easier methods provided by many popular JS libraries.

For example, if you are using jQuery, you might use the jQuery.extend() method instead of your copy function like so:

var obj = $.extend(new Obj(), $.parseJSON(str));

Forked jsFiddle here.

EDIT: Based on ideas from this question, I was able to get the restored object to have all the nested functionality as well, see the updated jsFiddle.

The core idea is to use prototypes instead of properties, and then make sure the object restored from JSON (which is just data) is the first parameter to $.extend():

function Obj2() {
    this.A = "A";
}
Obj2.prototype.toString = function() {
    return this.A;
};

function Obj() {
    this.A = new Obj2();
    this.D = "D";
    this.E = "E";
    this.F = "F";
}
Obj.prototype.toString = function() {
    return this.A.toString() + " * " + this.D + " * " + this.E + " * " + this.F;
};

var str = $.toJSON(new Obj());
$("#result").append("<p>JSON: " + str + "</p>");
var obj = jQuery.extend($.parseJSON(str), new Obj());
$("#result").append("<p>Recovered obj: " + obj.toString() + "</p>");
Sign up to request clarification or add additional context in comments.

6 Comments

Thanks. It's what I was looking for. It's a pity it doesn't work if there are object fields: jsfiddle.net/mr_goodcat/KfQrc/2
UPDATE: It seems "deep copy" should be a solution, but I can't make it work in the behaviour part (data is recovered): jsfiddle.net/mr_goodcat/KfQrc/3
Yeah, I couldn't get that to work, either. Copying nested prototypes is tricky and beyond me at the moment.
Yo! You did it! Thanks a lot. P.S. Seems it works the old way too: jsfiddle.net/mr_goodcat/KfQrc/6, so it only crucial to swap arguments to the extend method.
CRITICAL UPDATE: seems that your solution is not working after all. By swapping arguments we recover behaviour and erase all JSON-recovered data as well(( jsfiddle.net/mr_goodcat/KfQrc/9
|

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.