So I'm working on an application that takes in data from users & store it as objects in an array, I then created functionality to store that data in the localStorage. Here is the basic demo of what I'm trying to do:
// constructor function
function Book(title, author, pages, read = false) {
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
this.status = function() {
console.log(this.read);
}
}
// array to store objects
let mybooks = [];
// instances of the Book object
let book1 = new Book('Hello', 'John', 123, true);
let book2 = new Book('Hey', 'Jane', 13, false);
let book3 = new Book('Hi', 'Mary', 12, true);
let book4 = new Book('Holo', 'Peter', 10, false);
let book5 = new Book('Banda', 'Banda', 03, true);
// push the instances to the mybooks array
mybooks.push(book1);
mybooks.push(book2);
mybooks.push(book3);
mybooks.push(book4);
mybooks.push(book5);
// store mybooks to the localStorage
localStorage.mybooks = JSON.stringify(mybooks);
// retrieve data from the localStorage
let data = JSON.parse(localStorage.getItem('mybooks'));
// call the status() method on each object
data.forEach(book => {
book.status();
});
By calling the .status() method on each object, I expect to get the boolean ( true/false ) value on the console. But I get this error:
Uncaught TypeError: book.status is not a function
at app.js:36
at Array.forEach (<anonymous>)
at app.js:35
But if I run the same function on each object before storing it on the localStorage, I get the correct output.
Have a look at JSON.stringify
... any information about an object / instance which can not be transformed into a JSON conform key-value pair will be lost.
Thus, a Book
instance will be presented by a string as simple as e.g. this ...
'{"title":"Hello","author":"John","pages":123,"read":true}'
... and in case of parsing such a string via JSON.parse
one gets returned an object like ...
{ title: "Hello", author: "John", pages: 123, read: true }
... which still might be capable of representing a book through the data it carries, but it can not be used anymore like a real Book
instance that e.g. features an inherited status
method that at any time could be used for such an instance.
In order to solve the problem the OP has to map
the parsed array of raw book data items (the one from the local storage) into an array of real Book
instances ...
function Book(title, author, pages, read = false) {
// just a container of book specific data.
this.title = title;
this.author = author;
this.pages = pages;
this.read = read;
}
Book.prototype.status = function() {
// `status` preferably is implemented as prototype method.
console.log(this.read);
}
const mybooks = [
new Book('Hello', 'John', 123, true),
new Book('Hey', 'Jane', 13, false),
new Book('Hi', 'Mary', 12, true),
new Book('Holo', 'Peter', 10, false),
new Book('Banda', 'Banda', 03, true),
];
// const [book1, book2, book3, book4, book5] = mybooks;
mybooks.forEach(book => book.status());
// localStorage.setItem('mybooks', JSON.stringify(mybooks));
const storageValue = JSON.stringify(mybooks);
console.log('storageValue :', storageValue);
// const data = JSON.parse(localStorage.getItem('mybooks'));
const storageData = JSON.parse(storageValue);
console.log('storageData ... raw book data :', storageData);
// there is no status method at neither raw book data item ...
console.log('storageData[0].status :', storageData[0].status);
console.log('storageData[4].status :', storageData[4].status);
// ... but one nevertheless can work with each raw data item ...
console.log('raw book data item `status` delegation call ...');
storageData.forEach(rawBookDataItem =>
// explicit delegation via `call`.
Book.prototype.status.call(rawBookDataItem)
);
// map/transform raw book data items each into a `Book` instance ...
const listOfBookInstances = storageData.map(data =>
new Book(data.title, data.author, data.pages, data.read)
);
console.log('listOfBookInstances :', listOfBookInstances);
// call `status` method on each (new) book instance.
listOfBookInstances.forEach(book => book.status());
.as-console-wrapper { min-height: 100%!important; top: 0; }