0

I have a JSON object employees which I would like to populate with the data in my localstorage. I first saved my JSON object to local storage using stringify() .

    sessionStorage.setItem('Employee3', JSON.stringify({id: 3, firstName: 'Dwight', lastName: 'Schrute', title: 'Assistant Regional Manager', managerId: 2, managerName: 'Michael Scott', city: 'Scranton, PA', officePhone: '570-444-4444', cellPhone: '570-333-3333', email: '[email protected]', reportCount: 0}));

Now I want to populate my employees object:

employees: {},

populate: function() {
    var i = i;
    Object.keys(sessionStorage).forEach(function(key){
        if (/^Employee/.test(key)) {
            this.employees[i] = $.parseJSON(sessionStorage.getItem(key));
            i++;
        }
   });  
},

The function $.parseJSON(sessionStorage.getItem(key)) returns the JSON object correctly. Assigning it to the employees object fails:

Uncaught TypeError: Cannot set property 'undefined' of undefined

4
  • employees is an object whereas you are treating it as an array. How about declaring employees an array? Commented May 16, 2013 at 14:48
  • In the original snippet they didnt use localstorage, I am adding it now. They treated it as an array and it worked: this.employees[4] = {id: 4, firstName: 'Jim', lastName: 'Halpert', title: 'Assistant Regional Manager', managerId: 2, managerName: 'Michael Scott', city: 'Scranton, PA', officePhone: '570-222-2121', cellPhone: '570-999-1212', email: '[email protected]', reportCount: 1}; Commented May 16, 2013 at 14:49
  • @shahkalpesh: That's incorrect. In JavaScript you can access properties on objects using square brackets. It doesn't necesarily mean an access to an index of an array Commented May 16, 2013 at 14:51
  • @Kenneth: I am aware. Which property is being accessed here? What does i hold? Commented May 16, 2013 at 15:02

5 Answers 5

3

Array.forEach doesn't preserve this, so you'll have to preserve it yourself. Either of these will work (see mdn):

Object.keys(sessionStorage).forEach(function(key){
    if (/^Employee/.test(key)) {
        this.employees[i] = $.parseJSON(sessionStorage.getItem(key));
        i++;
    }
}, this);

var self = this;
Object.keys(sessionStorage).forEach(function(key){
    if (/^Employee/.test(key)) {
        self.employees[i] = $.parseJSON(sessionStorage.getItem(key));
        i++;
    }
});

Also, consider using the browser's JSON.parse() instead of jQuery's. Any browser that supports Array.forEach will support JSON.parse().

Sign up to request clarification or add additional context in comments.

8 Comments

Or use .bind(this) on the iterator function.
If you're using jQuery, there's no reason to use JSON.parse - jQuery tries that, then falls back to another method. I'd rather use that than not be sure
@MerynStol - That would only work if the OP only ever wanted to use one context for that array because this cannot be overridden. See mdn.
@Ian - But the OP is using Array.forEach, so there's already an assumption about browser support. I personally only like to use framework-specific functions if no reasonable native alternative exists, which is why I made the suggestion.
@tjameson how do you mean? If you do the bind each time forEach is called, you'll get the same effect as your first suggestion. Your suggestion is slightly shorter, easier to type, but not all methods support a second parameter for giving value for this. That's why I mentioned it.
|
2

Yet another way:

Object.keys(sessionStorage).forEach((function(key){
    if (/^Employee/.test(key)) {
        this.employees[i] = $.parseJSON(sessionStorage.getItem(key));
        i++;
    }
}).bind(this));

Calling .bind(this) on a function will return a new function bound to the value for this (in the current scope).

the advantage to this is that you don't need to remember which methods support the second "value for this" parameter. It always works. For example, this also works for when adding event listeners to DOM nodes.

tjameson's first suggestion is probably to be preferred in this specific case.

Comments

1

You have a problem with the scope of this. When you are inside the foreach-callback this is not referring to the correct instance.

You need to save a reference to this before and then access the object through that reference (self in the following example):

function something(){    
    var self = this;
    ** snip **
    employees: {},

    populate: function() {
        var i = i;
        Object.keys(sessionStorage).forEach(function(key){
            if (/^Employee/.test(key)) {
                self.employees[i] = $.parseJSON(sessionStorage.getItem(key));
                i++;
            }
       });  
    },
    ** snip ** 
}

Comments

1

You have a problem with the value of this inside the forEach callback. Also, And you don't need jQuery to parse JSON.

You can do this instead:

employees: {},

populate: function() {
    var that = this;
    var i = i;
    Object.keys(sessionStorage).forEach(function(key){
        if (/^Employee/.test(key)) {
            that.employees[i] = JSON.parse(sessionStorage.getItem(key));
            i++;
        }
   });  
},

2 Comments

Also, And you don't need jQuery to parse JSON. - then why does your answer still have $.parseJSON? :)
@Ian Thanks for pointing that out, I edited my answer in a hurry and cut out the wrong part.
0

There is no reason to parse JSON, two simple functions will do the job (hope that was the idea):

var employees = {};

function setEmployee( data ) {
    var id = data.id;
    sessionStorage.setItem('Employee' + id, JSON.stringify( data ));
};

function getEmployee( id ) {
    employees[id] = sessionStorage.getItem('Employee' + id);
};

var oneEmployee = {
    id: 3,
    firstName: 'Dwight',
    lastName: 'Schrute',
    title: 'Assistant Regional Manager',
    managerId: 2,
    managerName: 'Michael Scott',
    city: 'Scranton, PA',
    officePhone: '570-444-4444',
    cellPhone: '570-333-3333',
    email: '[email protected]',
    reportCount: 0
};

setEmployee( oneEmployee );

getEmployee( 3 );

Comments

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.