HTML5 localStorage
içinde bir JavaScript nesnesi depolamak istiyorum, ancak nesnem görünüşe göre bir dizeye dönüştürülüyor.
İlkel JavaScript türlerini ve dizilerini localStorage
kullanarak depolayabiliyor ve alabiliyorum, ancak nesneler çalışmıyor gibi görünüyor. Çalışmalılar mı?
İşte kodum:
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);
Konsol çıktısı şöyledir
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
Bana öyle geliyor ki setItem
yöntemi girdiyi saklamadan önce bir dizeye dönüştürüyor.
Bu davranışı Safari, Chrome ve Firefox'ta görüyorum, bu nedenle tarayıcıya özgü bir hata veya sınırlama değil, HTML5 Web Storage spesifikasyonunu yanlış anladığımı varsayıyorum.
http://www.w3.org/TR/html5/infrastructure.html adresinde açıklanan yapılandırılmış klon algoritmasını anlamaya çalıştım. Ne dediğini tam olarak anlamadım, ama belki de sorunum nesnemin özelliklerinin sayılabilir olmamasıyla ilgilidir (???)
Kolay bir çözüm var mı?
Güncelleme: W3C sonunda structured-clone spesifikasyonu hakkındaki fikirlerini değiştirdi ve spesifikasyonu uygulamalara uyacak şekilde değiştirmeye karar verdi. Bkz. https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111. Yani bu soru artık %100 geçerli değil, ancak cevaplar hala ilgi çekici olabilir.
Apple]1, Mozilla ve Mozilla again belgelerine bakıldığında, işlevselliğin yalnızca dize anahtar/değer çiftlerini işlemekle sınırlı olduğu görülmektedir.
Geçici bir çözüm, nesnenizi depolamadan önce stringify yapmak ve daha sonra geri aldığınızda ayrıştırmak olabilir:
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));
Bir varyant üzerinde küçük bir iyileştirme:
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);
}
Kısa devre değerlendirmesi](http://en.wikipedia.org/wiki/Short-circuit_evaluation) nedeniyle, getObject()
, key
Storage içinde değilse hemen null
döndürür. Ayrıca value
""
(boş dize; JSON.parse()
bunu işleyemez) ise bir SyntaxError
istisnası atmaz.
Storage nesnesini bu kullanışlı yöntemlerle genişletmek işinize yarayabilir:
Storage.prototype.setObject = function(key, value) {
this.setItem(key, JSON.stringify(value));
}
Storage.prototype.getObject = function(key) {
return JSON.parse(this.getItem(key));
}
Bu şekilde, API'nin altında yalnızca dizeleri desteklese bile gerçekten istediğiniz işlevselliği elde edersiniz.