📜 ⬆️ ⬇️

Work with local storage as with an object? Easy!

When localStorage appeared, I was happy, like an elephant, but a little later, after a detailed study of the issue, I was somewhat disappointed: only lines could be stored there, and objects could be forgotten. I had to turn them into strings for storage, I had to convert the string back into an object to work with it, then convert it again into a string in order to save it. I do not argue, there are wonderful libraries that allow you to manipulate the storage as simply as possible, but somehow you don’t really want to call functions.

localStorage = { a: { b: 1 }, c: { d: 2 } } localStorage.ab = 3; 

It would be cool, right?

A relatively long time ago, about half a year ago, I asked myself a question: how the hell could I do so that I could work with localStorage without functions at all, purely as with an object. Challenge accepted!
')
As the well-known Gesha says: “ Everything, I dozelal .”

Further reading is not necessary. A more reasonable solution is here: habrahabr.ru/post/144998


The main subtask was the invention of the method to hang the setter not only on the object itself, but also on the sub-objects, and the keys are not known in advance. This is solved very simply: put the getter on the object:

 Object.defineProperty( window, 'objectLocalStorage', { //  -  get: function() { return {}; } }); 

Now, when we assign any of the keys,

 window.objectLocalStorage.a = 1; 

Called getter.

So, everything to the disgrace is simple.

 (function() { // ,    ,      //       json    var _objectLocalStorage = JSON.parse( localStorage.getItem( 'objectStorage' ) ) || {}, timer = null; //     objectLocalStorage  window       //   ,    localStorage,   ,   Object.defineProperty( window, 'objectLocalStorage', { get: function() { // timer   ,         //   ,    localStorage    , //     // setTimeout    >< ,    if( timer === null ) { timer = setTimeout( function(){ var stringified = JSON.stringify( _objectLocalStorage ); //   :      , //     ,    if( stringified !== localStorage.getItem( 'objectStorage' ) ) { //  localStorage.setItem( 'objectStorage', stringified ); } timer = null; }, 0); } return _objectLocalStorage; }, //  ,  objectLocalStorage    set: function( v ) { _objectLocalStorage = v; localStorage.setItem( 'objectStorage', JSON.stringify( _objectLocalStorage ) ); } } ); })(); 

(Please note that the timer is called only to store the results in localStorage. Otherwise, the assignment result is predictable, as in a regular object, since _objectLocalStorage is returned immediately. It is inspired by this comment.)

How to use?

Paste the code above into your js file, and use:

 objectLocalStorage = { a: 4, b: {c: 2} }; objectLocalStorage.bc = {d: 5} 

Reloading page

 console.log( objectLocalStorage ); // { a: 4, b: {c: {d: 5}} } 


How it works?

When you get objectLocalStorage, the local _objectLocalStorage object is returned. So, when we assign something to one of the keys of a sub-object in objectLocalStorage, _objectLocalStorage is returned and the assignment goes into it. I.e
 objectLocalStorage.ab = 5; 
similarly
 _objectLocalStorage.ab = 5; 

But, in the first case, after assignment, the object is saved to be stored in localStorage. If you do not put this part into a timeout, the storage in the repository will be prior to assignment. I agree, this method is fraught with bugs, but I did not find another way to save after.

That's all. Ideally, of course, it would be nice to have:

But this later, I just wanted to share the joy :)

Rays beaver you.

UPD
I would like to separately highlight the alternative, simple and ingenious solution expressed by Scalar in the comments .

It seems to me easier to read and write to a regular object, which is serialized to LS (by timeout and onbeforeunload), and deserialized when the application starts.

Source: https://habr.com/ru/post/143597/


All Articles