Jeg ønsker å lagre et JavaScript-objekt i HTML5 localStorage
, men objektet mitt blir tilsynelatende konvertert til en streng.
Jeg kan lagre og hente primitive JavaScript-typer og matriser ved hjelp av localStorage
, men objekter ser ikke ut til å fungere. Burde de gjøre det?
Her er koden min:
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);
Konsollutgangen er
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
Det ser ut til at setItem
-metoden konverterer inndata til en streng før den lagres.
Jeg ser denne oppførselen i Safari, Chrome og Firefox, så jeg antar at det er min misforståelse av HTML5 Web Storage spesifikasjonen, ikke en nettleser-spesifikk feil eller begrensning.
Jeg har prøvd å forstå structured clone-algoritmen som er beskrevet i http://www.w3.org/TR/html5/infrastructure.html. Jeg forstår ikke helt hva den sier, men kanskje problemet mitt har å gjøre med at objektets egenskaper ikke er oppregnede (???)
Finnes det en enkel løsning?
Oppdatering: W3C ombestemte seg til slutt om strukturert-klon-spesifikasjonen, og bestemte seg for å endre spesifikasjonen for å matche implementeringene. Se https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111. Så dette spørsmålet er ikke lenger 100 % gyldig, men svarene kan fortsatt være av interesse.
Hvis man ser på dokumentasjonen til Apple, Mozilla og Mozilla igjen, ser funksjonaliteten ut til å være begrenset til å håndtere bare strengnøkkel/verdi-par.
En løsning kan være å stringify objektet ditt før du lagrer det, og senere analysere det når du henter det:
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));
En mindre forbedring av en variant:
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);
}
På grunn av kortslutningsevaluering, vil getObject()
umiddelbart returnere null
hvis key
ikke er i Storage. Det vil heller ikke kaste et SyntaxError
unntak hvis value
er ""
(den tomme strengen; JSON.parse()
kan ikke håndtere det).
Det kan være nyttig å utvide lagringsobjektet med disse praktiske metodene:
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
}
Storage.prototype.getObject = function(key) {
return JSON.parse(this.getItem(key));
}
På denne måten får du den funksjonaliteten du virkelig ønsket, selv om API-et under bare støtter strenger.