Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Recover methods from saved Javascript obect

If I have a class declaration in Javascript with a simple method as so:

class Foo {
    constructor(a, b) {
        this.a = a;
        this.b = b;
    }
    sum() {
        return this.a + this.b;
    }
}

I can then create an object and call its sum() method.

var bar = new Foo(2, 5); // {"a": 2, "b": 5}
var total = bar.sum(); // 7

I can also store this object (bar) in a database or local storage by first converting it to a string:

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

localStorage.savedBar = JSON.stringify(bar); // "{\"a\": 2, \"b\": 5}"

However, when I retrieve it, I can no longer access its methods.

var retrievedBar = JSON.parse(localStorage.savedBar); // {"a": 2, "b": 5}
var secondTotal = retrievedBar.sum(); // retrievedBar.sum is not a function!

This is really annoying, as it means that I would have to reconstruct any class objects. I have to say,

var goodRetrievedBar = new Foo(retrievedBar.a, retrievedBar.b);
var goodSecondTotal = goodRetrievedBar.sum(); // 7

which might seem fine for this scenario, but as soon as I even think about more deeply nested data structures, I very quickly enter the land of for loops and complex logic for a seemingly simple task. Also, if I wanted to make changes to my class in the future:

class Foo {
    constructor(a, b, c) {
        this.a = a;
        this.b = b;
        if (typeof c !== 'undefined') {
            this.c = c;
        }
    }
    sum() {
        if (this.c) {
            return this.a + this.b + this.c;
        }
        return this.a + this.b;
    }
}

I would also have to update my parsing code to support the additional property, c, when the changes I made to the class wouldn’t require me to make any other changes in my code.

Is there an easier way to force an object to assimilate itself into a class somehow? What is the standard way to deal with this in a simple and effective way?

>Solution :

Functions generally can’t be serialized and deserialized in all cases (due to closures), nor can objects with internal prototypes (other than Object.prototype) have those prototypes reflected after deserialization.

What you can do is serialize the own-properties of the instance, then when deserializing, use Object.create so that the internal prototype of the new instance is the class prototype.

class Foo {
    constructor(a, b, c) {
        this.a = a;
        this.b = b;
        if (typeof c !== 'undefined') {
            this.c = c;
        }
    }
    sum() {
        if (this.c) {
            return this.a + this.b + this.c;
        }
        return this.a + this.b;
    }
}
const f = new Foo(1, 2, 3);
const stringified = JSON.stringify(f);

const retrievedInstance = Object.create(Foo.prototype);
Object.assign(retrievedInstance, JSON.parse(stringified));
console.log(retrievedInstance.sum());

Note that this approach won’t work if you have anything stored in closures somewhere in the original object rather than in properties on the instance.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading