Ich möchte ein JavaScript-Objekt in HTML5 localStorage
speichern, aber mein Objekt wird offenbar in eine Zeichenfolge umgewandelt.
Ich kann primitive JavaScript-Typen und Arrays mit "localStorage" speichern und abrufen, aber Objekte scheinen nicht zu funktionieren. Sollten sie das?
Hier's mein Code:
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);
Die Konsolenausgabe lautet
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
Es sieht für mich so aus, als ob die Methode setItem
die Eingabe in eine Zeichenkette umwandelt, bevor sie gespeichert wird.
Ich sehe dieses Verhalten in Safari, Chrome und Firefox, so dass ich annehme, dass es mein Missverständnis der HTML5 Web Storage Spezifikation ist und nicht ein Browser-spezifischer Fehler oder eine Einschränkung.
Ich habe versucht, den in http://www.w3.org/TR/html5/infrastructure.html beschriebenen Algorithmus structured clone zu verstehen. Ich verstehe nicht ganz, was er aussagt, aber vielleicht hat mein Problem damit zu tun, dass die Eigenschaften meines Objekts nicht aufzählbar sind (???)
Gibt es einen einfachen Workaround?
Update: Das W3C hat seine Meinung über die Structured-Clone-Spezifikation geändert und beschlossen, die Spezifikation so zu ändern, dass sie mit den Implementierungen übereinstimmt. Siehe https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111. Die Frage ist also nicht mehr zu 100 % gültig, aber die Antworten könnten dennoch von Interesse sein.
Ein Blick in die Dokumentationen von Apple, Mozilla und Mozilla again zeigt, dass die Funktionalität auf die Verarbeitung von String-Schlüssel/Wert-Paaren beschränkt zu sein scheint.
Eine Abhilfe kann darin bestehen, Ihr Objekt vor dem Speichern stringifizieren und später beim Abrufen zu parsen:
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));
Eine geringfügige Verbesserung gegenüber einer Variante:
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);
}
Wegen der [Kurzschlussauswertung] (http://en.wikipedia.org/wiki/Short-circuit_evaluation) wird getObject()
sofort null
zurückgeben, wenn key
nicht in Storage ist. Es wird auch keine SyntaxError
-Ausnahme auslösen, wenn value
""
ist (die leere Zeichenkette; JSON.parse()
kann das nicht verarbeiten).
Es könnte sich als nützlich erweisen, das Storage-Objekt um diese praktischen Methoden zu erweitern:
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
}
Storage.prototype.getObject = function(key) {
return JSON.parse(this.getItem(key));
}
Auf diese Weise erhalten Sie die Funktionalität, die Sie wirklich wollten, obwohl die API nur Strings unterstützt.