2

I've created two object prototypes in JavaScript. These are the object constructor functions. You can see that the Board object contains an array of PostIt objects:

function PostIt(id, msg, img, pos) {
  this.id = id;
  this.msg = msg;
  this.img = img;
  this.pos = pos.slice(); // copy of array
}

function Board() {
  this.postIts = [];   // Empty array of PostIt objects
} 

Every prototype has its methods (getters/setters) and also Board has methods to push and pop PostIt objects from the array.

I've also implemented a mechanism in Board to save & retrieve the array by means of localStorage:

Board.prototype.save = function () {
  // Clean localstorage first
  localStorage.clear();

  if (this.getNumPostIts() > 0) { // It array is not empty
    localStorage.setItem('myboard', JSON.stringify(this.postIts));
  }
};

// Retrieve array of postit objects from local storage
Board.prototype.load = function () {
  this.postIts = JSON.parse((localStorage.getItem('myboard')));
};

The PostIt objects are retrieved correctly, but I'm not sure about what happens when I assign them to the this.postIts array of the Board object:

this.postIts = JSON.parse((localStorage.getItem('myboard')));

Once I've done this on loading the site, when I try to call a method for any of the postit objects in the array, I get an exception. For example, the following code after loading the document

myBoard = new Board();

if (localStorage.myboard) { // Local Storage has data
  // Retrieve data from local storate and dump it to myBoard
  myBoard.load();

  // Display Id for every postit
  for (var i=0; i < myBoard.getNumPostIts(); i++) {
    var pId = myBoard.getPostItByArrayIndex(i).getId();
    console.log("PostIt #%d has id = %d", i, pId);
  }    
} 

Calling the getId() method of the PostIt object raises an exception: jQuery.Deferred exception: myBoard.getPostItByArrayIndex(...).getId is not a function TypeError: myBoard.getPostItByArrayIndex(...).getId is not a function

I don't understand why "getId" is not a function. Is there something wrong when I call this getter method? EDIT: .getId() is a getter method of the PostIt object prototype:

PostIt.prototype.getId = function() {
  return this.id;
};
rodrunner
  • 1,860
  • 4
  • 23
  • 34

1 Answers1

2

The JSON format does not store the prototypes of the objects you convert to JSON. So when you parse those JSON strings again, the objects will just be plain objects, not related in any way to the prototype, like PostIt. By consequence prototype methods like getId are not available to those objects any more.

Similarly you would also lose the the direct methods on objects, as JSON does not provision for the function format.

How to make it work

I would first change the PostIt constructor, so that it has defaults for all arguments. More specifically, it needs some adjustment for the pos property:

function PostIt(id, msg, img, pos) {
  this.id = id;
  this.msg = msg;
  this.img = img;
  this.pos = Array.isArray(pos) ? pos.slice() : []; // default is empty array
}

And now you can use Object.assign to convert the JSON parsed objects back to PostIt objects:

Board.prototype.load = function () {
  this.postIts = JSON.parse((localStorage.getItem('myboard')))
                     .map(x => Object.assign(new PostIt, x));
};
trincot
  • 317,000
  • 35
  • 244
  • 286