Why localStorage only allows to store string values

localStorage allows data to be stored in browsers across sessions, the data will be there even though the session is expired. It is frequently used to store static data so that they can be loaded when needed. But as per spec, it says that t he keys and the values are  always strings  (note that, as with objects, integer keys will be automatically converted to strings). Why cannot store the object as it is?

Take a look at an example:

var str = "test";
localStorage.setItem("str", str);

var obj = {
    a: "hello",
    b: 10
localStorage.setItem("obj", obj);

The output is:

[object Object]

We can see that the obj is converted to a string. This normally shouldn't be like this as it is what users expect to get in most cases. 

Theoritically it's not an user friendly design to let user implement their own serialization/deserialization logic for the stored object in localStorage. It would make the application logic complicated in big projects. In addition, other storage mechanisms supported in HTML standard do support serialziation/deserialization such as IndexedDB and the obsolete Web SQL.

Indeed localStorage spec in the original HTML draft standard contains the part for serialization/deserialization, however it got removed in the final standard. The Vue.js project contributor 胖茶 di d some research on the change history of localStorage to understand the rationale behind the change. Below are his major findings.

  • In one git change dated back to 2006/04/16 , there were some changes to the signature of getItem() function and there were some mention about serialization/deserialization of E4X, XMLand Arrays in its original comment but there were no detailed explanantion on how to realize them. And the new commit removed those comments.
  • The StructuredSerialize/StructuredDeserialize algorithms implemented in IndexedDB and history.state came way later than the implementation of localStorage. 

So  胖茶 emailed the standar d editor  Ian Hickson about this question and mentioned his findings and guesses and got the response from Ian Hickson.

Yeah that's very plausible. Getting browser vendors on board is a big part of spec writing, so if they were expressing doubts I'd have been eager to simplify for them. There's certainly an argument to be made that having the serialization be done in JS is simpler than having the browser do it, and pretty much just as powerful.

Per what was discussed, the most plausible reason is that it was to reduce the implementation challenge as this localStorage support was added to the spec at a late stage and there was no conclusive decisions on how the serialization/decerialization can be achieved. To unblock the standard and implementation, the support for serialization/deserialization was removed.

Now some browsers like Chrome do support another function which can be used to achieve what we want. It is called localStorage.setObject()/localStorage.getObject().

var obj = {
    a: "hello",
    b: 10
localStorage.setObject("obj", obj);

// {a: "hello", b: 10}

However this is not supported in all major browsers(Firefox doesn't support this yet), hence use it with caution.

Reference: https://www.zhihu.com/question/366665675/answer/1127726009