0
\$\begingroup\$

I wasn't quite happy with the way localStorage handles non-string values, for example localStorage.setItem("foo",{test:5});localStorage.getItem("foo"); returns string literal '[object Object]', so i thought it would be a good idea to wrap it in json, came up with

betterLocalStorage = {
    get: function(key) {
        return JSON.parse(localStorage.getItem(key));
    },
    set: function(key, value) {
        localStorage.setItem(key, JSON.stringify(value));
    }
};

and betterLocalStorage.set("foo",{test:5});betterLocalStorage.get("foo"); returns object {test: 5}

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

Style

  • Don't use undeclared variables, eg betterLocalStorage should be const betterLocalStorage =

  • Use function property shorthand to define functions. Eg get: function(key) { can be get(key) {

  • Avoid using get and set as property names as these are tokens used to define setters and getters.

  • LocalStorage is an Object you can use bracket notation to set and get properties though there is nothing wrong using getItem and setItem. However do not mix access methods. Also not tha getItem will return null rather than undefined if a property does not exist.

Design

  • Local storage is a limited resource and is shared with all code on your domain (including extensions, user injected, and 3rd party code). There is no guarantee that data stored will be retrievable.

  • Local storage can be blocked and or modified by extensions/user code. JSON.parse will throw if the string is not a correctly formed JSON string. You do not guard against such events.

  • JSON.stringify will throw if the object being processed contains a cyclic reference. eg The following will throw an error. const a = {b: {}}; a.b = a; betterLocalStorage.set("foo", a). Many object contain cyclic references so care must be taken.

  • Your function pair get/set will convert undefined to null. Eg const a; console.log(betterLocalStorage.get(betterLocalStorage.set(a))); /* >> null should be undefined */

    This is counterintuitive if you are not aware, and becomes very problematic if you rely on default parameters in related code.

  • Your code converts an undefined value to null (via get set pair). You should guard against this behaviour.

  • If you use bracket notation (as in rewrite example) parsing a undefined property will throw an error. I do not use getItem and setItem due to its DOM centric behaviour. Which you use is up to you.

Rewrite

The rewrite addresses the style and design issues outlined above.

const storage = {
  getItem(key) {
    try {
      return localStorage[key] === undefined ? undefined : JSON.parse(localStorage[key]);
    } catch (e) {
      // TODO handle, report or pass on error
    }
    return; 
  },
  setItem(key, value) {
    if (value !== undefined) {
      try {
        localStorage[key] = JSON.stringify(value);
      } catch (e) {
        // TODO handle, report or pass on error
      }
    }
  }
};
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.