1

I am trying to make a basic notes app using JS.

I am storing notes in localStorage, and I am trying to print those notes using for-in loop. It works mostly fine, but I don’t know why I am getting extra values like length, getItem, key, etc. Can anyone help?

My code:

for (const key in localStorage) {
    let notes = document.getElementById("notes");
    let value = localStorage.getItem(key);
    notes.innerHTML = notes.innerHTML + `${key}: ${value} <br>`;
}
user3840170
  • 26,597
  • 4
  • 30
  • 62

2 Answers2

1

localStorage (and likewise sessionStorage) is an object similar to Map, in that its own properties and methods don’t directly correspond to values actually kept in the storage. Enumerating its properties and accessing missing properties on it will fall back to returning items from the underlying storage, but that is actually a design flaw that is best not relied on.

To enumerate the contents of a storage object (localStorage or sessionStorage), you shouldn’t use for-in, Object.keys or Object.entries. Use key, length and getItem:

function* storageEntries(storage) {
    for (let i = 0; i < storage.length; ++i) {
        const key = storage.key(i); 
        yield [key, storage.getItem(key)];
    }
}

for (const [key, val] of storageEntries(localStorage)) {
    console.info(
        `localStorage ${JSON.stringify(key)} maps to ${JSON.stringify(val)}`);
}

Using the for-in loop and property accesses will return properties of the localStorage object itself, while using Object.entries or Object.keys will skip them even if there actually are storage items with the same keys. For example:

localStorage.clear();
localStorage.setItem('length', -69420);
localStorage.setItem('getItem', 'where is your god now?');

// returns wrong values
const result0 = [];
for (var key in localStorage) {
    result0.push(key, localStorage[key]);
}
console.log('WRONG:', result0);

// returns right values, but also spurious keys
const result1 = [];
for (var key in localStorage) {
    result1.push(key, localStorage.getItem(key));
}
console.log('WRONG:', result1);

// returns an empty array
console.log('WRONG:', Object.entries(localStorage));

// returns two key-value pairs
console.log('RIGHT:', Array.from(storageEntries(localStorage)));

As an aside though, keep in mind that each storage object provides a single namespace shared by all scripts that happen to be running on your page. If any other script you use decides to store items in localStorage as well, those may appear as ‘notes’ in your app, and modifying them may corrupt those other scripts’ data. You may be better off at the very least prefixing (or suffixing) storage keys you use with something specific to your app, to section them off and minimise the risk of clashes.

user3840170
  • 26,597
  • 4
  • 30
  • 62
-2

localStorage is an object with properties and methods. You're looping over all of these as well as the item items when you're performing the for of loop.

To ensure you only get the actual keys and values within localStorage then you can use Object.entries().

For example:

Object.entries(localStorage).forEach(([key, value]) => {
  let notes = document.getElementById("notes");
  notes.innerHTML = notes.innerHTML + `${key}: ${value} <br>`
});
Kristian Roebuck
  • 3,209
  • 2
  • 21
  • 29