Chciałbym zapisać obiekt JavaScript w HTML5 localStorage, ale mój obiekt jest najwyraźniej konwertowany na ciąg.

Mogę przechowywać i pobierać prymitywne typy javascript i macierzy za pomocą localStorage, ale obiekty nie działają. Czy powinni?

Oto mój kod:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };
console.log('typeof testObject: ' + typeof testObject);
console.log('testObject properties:');
for (var prop in testObject) {
    console.log('  ' + prop + ': ' + testObject[prop]);
}

// Put the object into storage
localStorage.setItem('testObject', testObject);

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('typeof retrievedObject: ' + typeof retrievedObject);
console.log('Value of retrievedObject: ' + retrievedObject);

Wyjście konsoli jest

typeof testObject: object
testObject properties:
  one: 1
  two: 2
  three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]

Wygląda na mnie jak metoda setItem konwersja wejścia do ciągów przed przechowywaniem.

Widzę to zachowanie w Safari, Chrome i Firefox, więc zakładam, że to moje nieporozumienie HTML5 Web Storage Spec, nie specyficzny przegląd przed przeglądarką lub ograniczenie.

Próbowałem zrozumieć algorytm Clone Clone opisany w http://www.w3.org/tr/html5/infrasructure.html. Nie rozumiem w pełni, co to mówi, ale może mój problem musi zrobić z właściwościami mojego obiektu, które nie są wymienialne (???)

Czy jest łatwy obejście?


AKTUALIZACJA: W3C ostatecznie zmieniła swoje umysły o specyfikację strukturyzowanej klonowania i postanowił zmienić specyfikację, aby dopasować się do implementacji. Zobacz https://www.w3.org/bugs/public/show_Bug. CGI? Id = 12111. Więc to pytanie nie jest już w 100% ważne, ale odpowiedzi nadal mogą być interesujące.

2833
Kristopher Johnson 6 styczeń 2010, 07:05

16 odpowiedzi

Najlepsza odpowiedź

Patrząc na jabłko , Mozilla i Mozilla ponownie Dokumentacja, funkcjonalność wydaje się być ograniczona do obsługi tylko pary kluczy / wartości string.

Obejście może być do Smarfify Twój obiekt przed przechowywaniem, a później przeanalizuj, kiedy go odzyskasz:

var testObject = { 'one': 1, 'two': 2, 'three': 3 };

// Put the object into storage
localStorage.setItem('testObject', JSON.stringify(testObject));

// Retrieve the object from storage
var retrievedObject = localStorage.getItem('testObject');

console.log('retrievedObject: ', JSON.parse(retrievedObject));
3354
Cœur 15 czerwiec 2019, 04:06

Tutaj niektóre rozszerzone wersja kodu opublikowanego przez @danott

Zaimplementuje również Usuń Wartość z Localstorage i pokazuje, jak dodaje warstwę Gettera i Setter, więc zamiast

localstorage.setItem(preview, true)

Możesz pisać

config.preview = true

Dobra tutaj byli:

var PT=Storage.prototype

if (typeof PT._setItem >='u') PT._setItem = PT.setItem;
PT.setItem = function(key, value)
{
  if (typeof value >='u')//..ndefined
    this.removeItem(key)
  else
    this._setItem(key, JSON.stringify(value));
}

if (typeof PT._getItem >='u') PT._getItem = PT.getItem;
PT.getItem = function(key)
{  
  var ItemData = this._getItem(key)
  try
  {
    return JSON.parse(ItemData);
  }
  catch(e)
  {
    return ItemData;
  }
}

// Aliases for localStorage.set/getItem 
get =   localStorage.getItem.bind(localStorage)
set =   localStorage.setItem.bind(localStorage)

// Create ConfigWrapperObject
var config = {}

// Helper to create getter & setter
function configCreate(PropToAdd){
    Object.defineProperty( config, PropToAdd, {
      get: function ()      { return (  get(PropToAdd)      ) },
      set: function (val)   {           set(PropToAdd,  val ) }
    })
}
//------------------------------

// Usage Part
// Create properties
configCreate('preview')
configCreate('notification')
//...

// Config Data transfer
//set
config.preview = true

//get
config.preview

// delete
config.preview = undefined

Cóż, możesz usunąć część aliasów z .bind(...). Jednak po prostu umieściłem to, ponieważ naprawdę dobrze się o tym wiedzieć. Uznałem mi godziny, aby dowiedzieć się, dlaczego proste {x1}} nie działa

1
Nadu 10 luty 2015, 20:25

Zrobiłem coś, co nie łamiło istniejących obiektów przechowywania, ale tworzy owijkę, dzięki czemu możesz robić to, co chcesz. Rezultatem jest normalny obiekt, brak metod, z dostępem jak każdy obiekt.

Rzecz, którą zrobiłem.

Jeśli chcesz 1 localStorage nieruchomość, aby być magią:

var prop = ObjectStorage(localStorage, 'prop');

Jeśli potrzebujesz kilku:

var storage = ObjectStorage(localStorage, ['prop', 'more', 'props']);

Wszystko, co robisz prop, lub obiekty wewnątrz storage zostaną automatycznie zapisane w localStorage. Zawsze bawisz się z prawdziwym obiektem, więc możesz zrobić takie rzeczy:

storage.data.list.push('more data');
storage.another.list.splice(1, 2, {another: 'object'});

A każdy nowy obiekt wewnątrz obiekt śledzony zostanie automatycznie śledzony.

Bardzo duży minus: To zależy od Object.observe(), więc ma bardzo ograniczoną obsługę przeglądarki. I już nie wygląda na Firefox lub Edge w dowolnym momencie.

1
Rudie 28 listopad 2015, 20:39

Znalazłem sposób, aby działał z obiektami, które mają cykliczne odniesienia.

Zróbmy obiekt z cyklicznych odniesień.

obj = {
    L: {
        L: { v: 'lorem' },
        R: { v: 'ipsum' }
    },
    R: {
        L: { v: 'dolor' },
        R: {
            L: { v: 'sit' },
            R: { v: 'amet' }
        }
    }
}
obj.R.L.uncle = obj.L;
obj.R.R.uncle = obj.L;
obj.R.R.L.uncle = obj.R.L;
obj.R.R.R.uncle = obj.R.L;
obj.L.L.uncle = obj.R;
obj.L.R.uncle = obj.R;

Nie możemy tutaj zrobić JSON.stringify, ze względu na okrągłe odniesienia.

circularUncle

LOCALSTORAGE.CYCLICJSON ma .stringify i .parse .parse {.parse jak normal JSON, ale działa z obiektami z odwołań okrągłych. ("Działa", co oznacza analiza (strumyk (obj)) i obj są głębokie równe i mają identyczne zestawy "wewnętrznych równości")

Ale możemy po prostu użyć skrótów:

LOCALSTORAGE.setObject('latinUncles', obj)
recovered = LOCALSTORAGE.getObject('latinUncles')

Następnie recovered będzie "taki sam" do OBJ, w następnym sensie:

[
obj.L.L.v === recovered.L.L.v,
obj.L.R.v === recovered.L.R.v,
obj.R.L.v === recovered.R.L.v,
obj.R.R.L.v === recovered.R.R.L.v,
obj.R.R.R.v === recovered.R.R.R.v,
obj.R.L.uncle === obj.L,
obj.R.R.uncle === obj.L,
obj.R.R.L.uncle === obj.R.L,
obj.R.R.R.uncle === obj.R.L,
obj.L.L.uncle === obj.R,
obj.L.R.uncle === obj.R,
recovered.R.L.uncle === recovered.L,
recovered.R.R.uncle === recovered.L,
recovered.R.R.L.uncle === recovered.R.L,
recovered.R.R.R.uncle === recovered.R.L,
recovered.L.L.uncle === recovered.R,
recovered.L.R.uncle === recovered.R
]

Oto implementacja LOCALSTORAGE

LOCALSTORAGE = (function(){
  "use strict";
  var ignore = [Boolean, Date, Number, RegExp, String];
  function primitive(item){
    if (typeof item === 'object'){
      if (item === null) { return true; }
      for (var i=0; i<ignore.length; i++){
        if (item instanceof ignore[i]) { return true; }
      }
      return false;
    } else {
      return true;
    }
  }
  function infant(value){
    return Array.isArray(value) ? [] : {};
  }
  function decycleIntoForest(object, replacer) {
    if (typeof replacer !== 'function'){
      replacer = function(x){ return x; }
    }
    object = replacer(object);
    if (primitive(object)) return object;
    var objects = [object];
    var forest  = [infant(object)];
    var bucket  = new WeakMap(); // bucket = inverse of objects 
    bucket.set(object, 0);    
    function addToBucket(obj){
      var result = objects.length;
      objects.push(obj);
      bucket.set(obj, result);
      return result;
    }
    function isInBucket(obj){ return bucket.has(obj); }
    function processNode(source, target){
      Object.keys(source).forEach(function(key){
        var value = replacer(source[key]);
        if (primitive(value)){
          target[key] = {value: value};
        } else {
          var ptr;
          if (isInBucket(value)){
            ptr = bucket.get(value);
          } else {
            ptr = addToBucket(value);
            var newTree = infant(value);
            forest.push(newTree);
            processNode(value, newTree);
          }
          target[key] = {pointer: ptr};
        }
      });
    }
    processNode(object, forest[0]);
    return forest;
  };
  function deForestIntoCycle(forest) {
    var objects = [];
    var objectRequested = [];
    var todo = [];
    function processTree(idx) {
      if (idx in objects) return objects[idx];
      if (objectRequested[idx]) return null;
      objectRequested[idx] = true;
      var tree = forest[idx];
      var node = Array.isArray(tree) ? [] : {};
      for (var key in tree) {
        var o = tree[key];
        if ('pointer' in o) {
          var ptr = o.pointer;
          var value = processTree(ptr);
          if (value === null) {
            todo.push({
              node: node,
              key: key,
              idx: ptr
            });
          } else {
            node[key] = value;
          }
        } else {
          if ('value' in o) {
            node[key] = o.value;
          } else {
            throw new Error('unexpected')
          }
        }
      }
      objects[idx] = node;
      return node;
    }
    var result = processTree(0);
    for (var i = 0; i < todo.length; i++) {
      var item = todo[i];
      item.node[item.key] = objects[item.idx];
    }
    return result;
  };
  var console = {
    log: function(x){
      var the = document.getElementById('the');
      the.textContent = the.textContent + '\n' + x;
	},
	delimiter: function(){
      var the = document.getElementById('the');
      the.textContent = the.textContent +
		'\n*******************************************';
	}
  }
  function logCyclicObjectToConsole(root) {
    var cycleFree = decycleIntoForest(root);
    var shown = cycleFree.map(function(tree, idx) {
      return false;
    });
    var indentIncrement = 4;
    function showItem(nodeSlot, indent, label) {
      var leadingSpaces = ' '.repeat(indent);
      var leadingSpacesPlus = ' '.repeat(indent + indentIncrement);
      if (shown[nodeSlot]) {
        console.log(leadingSpaces + label + ' ... see above (object #' + nodeSlot + ')');
      } else {
        console.log(leadingSpaces + label + ' object#' + nodeSlot);
        var tree = cycleFree[nodeSlot];
        shown[nodeSlot] = true;
        Object.keys(tree).forEach(function(key) {
          var entry = tree[key];
          if ('value' in entry) {
            console.log(leadingSpacesPlus + key + ": " + entry.value);
          } else {
            if ('pointer' in entry) {
              showItem(entry.pointer, indent + indentIncrement, key);
            }
          }
        });
      }
    }
	console.delimiter();
    showItem(0, 0, 'root');
  };
  function stringify(obj){
    return JSON.stringify(decycleIntoForest(obj));
  }
  function parse(str){
    return deForestIntoCycle(JSON.parse(str));
  }
  var CYCLICJSON = {
    decycleIntoForest: decycleIntoForest,
    deForestIntoCycle : deForestIntoCycle,
    logCyclicObjectToConsole: logCyclicObjectToConsole,
    stringify : stringify,
    parse : parse
  }
  function setObject(name, object){
    var str = stringify(object);
    localStorage.setItem(name, str);
  }
  function getObject(name){
    var str = localStorage.getItem(name);
    if (str===null) return null;
    return parse(str);
  }
  return {
    CYCLICJSON : CYCLICJSON,
    setObject  : setObject,
    getObject  : getObject
  }
})();
obj = {
	L: {
		L: { v: 'lorem' },
		R: { v: 'ipsum' }
	},
	R: {
		L: { v: 'dolor' },
		R: {
			L: { v: 'sit' },
			R: { v: 'amet' }
		}
	}
}
obj.R.L.uncle = obj.L;
obj.R.R.uncle = obj.L;
obj.R.R.L.uncle = obj.R.L;
obj.R.R.R.uncle = obj.R.L;
obj.L.L.uncle = obj.R;
obj.L.R.uncle = obj.R;

// LOCALSTORAGE.setObject('latinUncles', obj)
// recovered = LOCALSTORAGE.getObject('latinUncles')
// localStorage not available inside fiddle ):
LOCALSTORAGE.CYCLICJSON.logCyclicObjectToConsole(obj)
putIntoLS = LOCALSTORAGE.CYCLICJSON.stringify(obj);
recovered = LOCALSTORAGE.CYCLICJSON.parse(putIntoLS);
LOCALSTORAGE.CYCLICJSON.logCyclicObjectToConsole(recovered);

var the = document.getElementById('the');
the.textContent = the.textContent + '\n\n' +
JSON.stringify(
[
obj.L.L.v === recovered.L.L.v,
obj.L.R.v === recovered.L.R.v,
obj.R.L.v === recovered.R.L.v,
obj.R.R.L.v === recovered.R.R.L.v,
obj.R.R.R.v === recovered.R.R.R.v,
obj.R.L.uncle === obj.L,
obj.R.R.uncle === obj.L,
obj.R.R.L.uncle === obj.R.L,
obj.R.R.R.uncle === obj.R.L,
obj.L.L.uncle === obj.R,
obj.L.R.uncle === obj.R,
recovered.R.L.uncle === recovered.L,
recovered.R.R.uncle === recovered.L,
recovered.R.R.L.uncle === recovered.R.L,
recovered.R.R.R.uncle === recovered.R.L,
recovered.L.L.uncle === recovered.R,
recovered.L.R.uncle === recovered.R
]
)
<pre id='the'></pre>
1
mathheadinclouds 12 listopad 2019, 19:38

Aby zapisać obiekt, możesz wykonać litery, których możesz użyć, aby uzyskać obiekt z ciąg do obiektu (może nie mieć sensu). Na przykład

var obj = {a: "lol", b: "A", c: "hello world"};
function saveObj (key){
    var j = "";
    for(var i in obj){
        j += (i+"|"+obj[i]+"~");
    }
    localStorage.setItem(key, j);
} // Saving Method
function getObj (key){
    var j = {};
    var k = localStorage.getItem(key).split("~");
    for(var l in k){
        var m = k[l].split("|");
        j[m[0]] = m[1];
    }
    return j;
}
saveObj("obj"); // undefined
getObj("obj"); // {a: "lol", b: "A", c: "hello world"}

Ta technika spowoduje, że niektóre usterki, jeśli używasz listu, który został użył do dzielenia obiektu, a także jest bardzo eksperymentalny.

0
Seizefire 21 maj 2016, 16:48

Niewielka poprawa na Wariant:

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    var value = this.getItem(key);
    return value && JSON.parse(value);
}

Ze względu na ocena zwarciowa, {x0}} Will Natychmiast RETURN null Jeśli key nie jest w magazynie. Nie będzie również rzucić wyjątku SyntaxError, jeśli value jest "" (pusty ciąg; JSON.parse() nie może sobie z tym poradzić).

638
Dave Jarvis 28 kwiecień 2018, 19:40

Możesz uznać za przydatne do rozszerzenia obiektu pamięci z tymi poradnymi metodami:

Storage.prototype.setObject = function(key, value) {
    this.setItem(key, JSON.stringify(value));
}

Storage.prototype.getObject = function(key) {
    return JSON.parse(this.getItem(key));
}

W ten sposób uzyskasz funkcjonalność, którą naprawdę chciałeś, choć pod adresem API obsługuje tylko łańcuchy.

225
Justin Voskuhl 6 styczeń 2010, 04:42

Rozszerzenie obiektu przechowywania jest niesamowite rozwiązanie. Dla mojego interfejsu API stworzyłem elewację dla Localstorage, a następnie sprawdź, czy jest obiektem, czy nie podczas ustawienia i zdobycia.

var data = {
  set: function(key, value) {
    if (!key || !value) {return;}

    if (typeof value === "object") {
      value = JSON.stringify(value);
    }
    localStorage.setItem(key, value);
  },
  get: function(key) {
    var value = localStorage.getItem(key);

    if (!value) {return;}

    // assume it is an object that has been stringified
    if (value[0] === "{") {
      value = JSON.parse(value);
    }

    return value;
  }
}
75
Alex Grande 25 październik 2013, 16:32

Istnieje świetna biblioteka, która obejmuje wiele rozwiązań, dzięki czemu nawet obsługuje starszych przeglądarek o nazwie Jstorage

Możesz ustawić obiekt

$.jStorage.set(key, value)

I łatwo odzyskaj go

value = $.jStorage.get(key)
value = $.jStorage.get(key, "default value")
53
Matthew 27 marzec 2018, 03:14

Teoretycznie możliwe jest przechowywanie obiektów z funkcjami:

function store (a)
{
  var c = {f: {}, d: {}};
  for (var k in a)
  {
    if (a.hasOwnProperty(k) && typeof a[k] === 'function')
    {
      c.f[k] = encodeURIComponent(a[k]);
    }
  }

  c.d = a;
  var data = JSON.stringify(c);
  window.localStorage.setItem('CODE', data);
}

function restore ()
{
  var data = window.localStorage.getItem('CODE');
  data = JSON.parse(data);
  var b = data.d;

  for (var k in data.f)
  {
    if (data.f.hasOwnProperty(k))
    {
      b[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");
    }
  }

  return b;
}

Jednakże, funkcja serializacyjna / deserializacyjna jest niewiarygodna, ponieważ jest to zależne od implementacji.

28
PointedEars 8 październik 2012, 16:14

Przyjechałem do tego posta po uderzeniu w innym postie, który został zamknięty jako duplikat tego - zatytułowany "Jak przechowywać tablicę w Localstorage?". Co jest w porządku, z wyjątkiem, ani wątku faktycznie zapewnia pełną odpowiedź, w jaki sposób możesz utrzymać tablicę w LocalStorage - jednak udało mi się stworzyć rozwiązanie na podstawie informacji zawartych w obu niciach.

Więc jeśli ktoś chce móc push / pop / zmiany przedmiotów w tablicy i chcą, aby tablica przechowywała w LocalStorage lub rzeczywiście SessionStorage, tutaj idziesz:

Storage.prototype.getArray = function(arrayName) {
  var thisArray = [];
  var fetchArrayObject = this.getItem(arrayName);
  if (typeof fetchArrayObject !== 'undefined') {
    if (fetchArrayObject !== null) { thisArray = JSON.parse(fetchArrayObject); }
  }
  return thisArray;
}

Storage.prototype.pushArrayItem = function(arrayName,arrayItem) {
  var existingArray = this.getArray(arrayName);
  existingArray.push(arrayItem);
  this.setItem(arrayName,JSON.stringify(existingArray));
}

Storage.prototype.popArrayItem = function(arrayName) {
  var arrayItem = {};
  var existingArray = this.getArray(arrayName);
  if (existingArray.length > 0) {
    arrayItem = existingArray.pop();
    this.setItem(arrayName,JSON.stringify(existingArray));
  }
  return arrayItem;
}

Storage.prototype.shiftArrayItem = function(arrayName) {
  var arrayItem = {};
  var existingArray = this.getArray(arrayName);
  if (existingArray.length > 0) {
    arrayItem = existingArray.shift();
    this.setItem(arrayName,JSON.stringify(existingArray));
  }
  return arrayItem;
}

Storage.prototype.unshiftArrayItem = function(arrayName,arrayItem) {
  var existingArray = this.getArray(arrayName);
  existingArray.unshift(arrayItem);
  this.setItem(arrayName,JSON.stringify(existingArray));
}

Storage.prototype.deleteArray = function(arrayName) {
  this.removeItem(arrayName);
}

Przykładowe wykorzystanie - przechowywanie prostych strun w tablicy LocalStoRage:

localStorage.pushArrayItem('myArray','item one');
localStorage.pushArrayItem('myArray','item two');

Przykładowe wykorzystanie - przechowywanie obiektów w tablicy SessionStorage:

var item1 = {}; item1.name = 'fred'; item1.age = 48;
sessionStorage.pushArrayItem('myArray',item1);

var item2 = {}; item2.name = 'dave'; item2.age = 22;
sessionStorage.pushArrayItem('myArray',item2);

Wspólne metody manipulowania tablicami:

.pushArrayItem(arrayName,arrayItem); -> adds an element onto end of named array
.unshiftArrayItem(arrayName,arrayItem); -> adds an element onto front of named array
.popArrayItem(arrayName); -> removes & returns last array element
.shiftArrayItem(arrayName); -> removes & returns first array element
.getArray(arrayName); -> returns entire array
.deleteArray(arrayName); -> removes entire array from storage
26
Andy Lorenz 7 maj 2014, 14:07

Inną opcją byłoby użycie istniejącej wtyczki.

Na przykład Persisto jest projektem open source, który zapewnia łatwy interfejs do LocalStorage / SessionStorage i automatyzuje trwałość dla formularza Pola (wejście, przyciski radiowe i pola wyboru).

persisto features

(Zastrzeżenie: Jestem autorem.)

4
mar10 16 czerwiec 2016, 19:55

Możesz użyć Ejson do przechowywania obiektów jako ciągów.

Ejson jest rozszerzeniem JSON, aby wspierać więcej typów. Obsługuje wszystkie typy Bezpieczeństwa JSON, a także:

  • Data (javascript {x0}})
  • binarny (javascript Uint8Array lub wynik ajson.Newbinary )
  • typy zdefiniowane przez użytkownika (patrz ajson.addtype. Na przykład < href = "https://docs.metesor.com/api/ejson.html#mongo_object_id" Rel = "Nofollow"> Mongo.objectidd jest wdrażany w ten sposób.)

Wszystkie serializacje Ejson są również ważne JSON. Na przykład obiekt z datą i buforem binarnym byłby serializowany w Ejson jako:

{
  "d": {"$date": 1358205756553},
  "b": {"$binary": "c3VyZS4="}
}

Oto mój owijarka Localstorage za pomocą EJSON

https://github.com/uzitech/storage.js.

Dodałem kilka typów do mojego opakowania, w tym wyrażenia regularne i funkcje

4
Tony Brix 28 lipiec 2016, 15:41

Zrobiłem kolejny minimalistyczny owijek z tylko 20 wierszami kodu, aby umożliwić używanie go tak, jak powinno:

localStorage.set('myKey',{a:[1,2,5], b: 'ok'});
localStorage.has('myKey');   // --> true
localStorage.get('myKey');   // --> {a:[1,2,5], b: 'ok'}
localStorage.keys();         // --> ['myKey']
localStorage.remove('myKey');

https://github.com/zevero/simpleWebstorage.

2
zevero 28 wrzesień 2016, 10:30

Dla użytkowników maszynopisów chce ustawić i uzyskać wpisane właściwości:

/**
 * Silly wrapper to be able to type the storage keys
 */
export class TypedStorage<T> {

    public removeItem(key: keyof T): void {
        localStorage.removeItem(key);
    }

    public getItem<K extends keyof T>(key: K): T[K] | null {
        const data: string | null =  localStorage.getItem(key);
        return JSON.parse(data);
    }

    public setItem<K extends keyof T>(key: K, value: T[K]): void {
        const data: string = JSON.stringify(value);
        localStorage.setItem(key, data);
    }
}

Przykład wykorzystania:

// write an interface for the storage
interface MyStore {
   age: number,
   name: string,
   address: {city:string}
}

const storage: TypedStorage<MyStore> = new TypedStorage<MyStore>();

storage.setItem("wrong key", ""); // error unknown key
storage.setItem("age", "hello"); // error, age should be number
storage.setItem("address", {city:"Here"}); // ok

const address: {city:string} = storage.getItem("address");
2
Flavien Volken 30 maj 2018, 11:06

http://rhaboo.org jest warstwą lokalizacyjnej cukru, która pozwala napisać takie rzeczy:

var store = Rhaboo.persistent('Some name');
store.write('count', store.count ? store.count+1 : 1);
store.write('somethingfancy', {
  one: ['man', 'went'],
  2: 'mow',
  went: [  2, { mow: ['a', 'meadow' ] }, {}  ]
});
store.somethingfancy.went[1].mow.write(1, 'lawn');

Nie używa JSON.Stringify / Parse, ponieważ byłoby niedokładne i wolno na dużych obiektach. Zamiast tego każda wartość terminala ma swój własny wpis Localstorage.

Prawdopodobnie możesz odgadnąć, że mogę mieć coś wspólnego z Rhaboo ;-)

Adrian.

2
maja 8 maj 2020, 07:59