Saya ingin menyimpan objek JavaScript dalam HTML5 localStorage
, tetapi objek saya tampaknya sedang dikonversi ke string.
Saya dapat menyimpan dan mengambil jenis dan array JavaScript primitif menggunakan localStorage
, tetapi objek tampaknya tidak berfungsi. Haruskah mereka
Ini kode saya:
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);
Output konsol adalah
typeof testObject: object
testObject properties:
one: 1
two: 2
three: 3
typeof retrievedObject: string
Value of retrievedObject: [object Object]
Sepertinya saya seperti setItem
metode ini mengkonversi input ke string sebelum menyimpannya.
Saya melihat perilaku ini di Safari, Chrome, dan Firefox, jadi saya menganggap itu kesalahpahaman saya tentang spesifikasi Penyimpanan Web HTML5 , bukan bug atau batasan khusus browser.
Saya sudah mencoba memahami algoritma klon terstruktur yang dijelaskan dalam http://www.w3.org/TR/html5/infrastructure.html . Saya tidak sepenuhnya mengerti apa yang dikatakannya, tapi mungkin masalah saya ada hubungannya dengan properti objek saya yang tidak dapat dihitung (???)
Apakah ada solusi yang mudah?
Pembaruan: W3C akhirnya berubah pikiran tentang spesifikasi terstruktur-klon, dan memutuskan untuk mengubah spesifikasi agar sesuai dengan implementasi. Lihat https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 . Jadi pertanyaan ini tidak lagi 100% valid, tetapi jawabannya mungkin masih menarik.
sumber
Jawaban:
Melihat dokumentasi Apple , Mozilla dan Mozilla lagi , fungsi tampaknya terbatas untuk menangani pasangan kunci kunci / nilai saja.
Solusinya adalah dengan merapatkan objek Anda sebelum menyimpannya, dan kemudian menguraikannya saat Anda mengambilnya:
sumber
JSON.stringify()
memperluas objek yang direferensikan ke "konten" lengkapnya (tersurat tersirat) di objek yang kami rangkai. Lihat: stackoverflow.com/a/12659424/2044940Peningkatan minor pada varian :
Karena evaluasi hubung singkat ,
getObject()
akan segera kembalinull
jikakey
tidak ada di Storage. Hal ini juga tidak akan melemparSyntaxError
pengecualian jikavalue
adalah""
(string kosong;JSON.parse()
tidak bisa mengatasinya).sumber
var userObject = { userId: 24, name: 'Jack Bauer' };
Dan untuk mengaturnyalocalStorage.setObject('user', userObject);
Kemudian mendapatkannya kembali dari penyimpananuserObject = localStorage.getObject('user');
Anda bahkan dapat menyimpan berbagai objek jika Anda mau.key
tidak di Penyimpanan Lokal,window.localStorage.getItem(key)
mengembalikannull
- itu tidak membuang pengecualian "Akses ilegal" - danJSON.parse(null)
mengembalikannull
juga - itu tidak melempar pengecualian juga, baik di bagian Chromium 21 maupun per ES 5.1 15.12.2 , karenaString(null) === "null"
yang dapat diartikan sebagai JSON literal .""
(string kosong) sebelumnya. Karena itu ketik-convert kefalse
danJSON.parse("")
, yang akan membuangSyntaxError
pengecualian, tidak dipanggil.Anda mungkin perlu memperluas objek Penyimpanan dengan metode praktis berikut:
Dengan cara ini Anda mendapatkan fungsionalitas yang benar-benar Anda inginkan walaupun di bawah API hanya mendukung string.
sumber
localStorage.setObject
.getObject()
akan mengeluarkanSyntaxError
pengecualian jika nilai yang disimpan adalah""
, karenaJSON.parse()
tidak bisa mengatasinya. Lihat edit saya untuk jawaban Guria untuk detailnya.Memperluas objek Storage adalah solusi yang luar biasa. Untuk API saya, saya telah membuat fasad untuk localStorage dan kemudian memeriksa apakah itu objek atau tidak saat pengaturan dan dapatkan.
sumber
data.set('username': 'ifedi', 'fullname': { firstname: 'Ifedi', lastname: 'Okonkwo'});
:?Stringify tidak menyelesaikan semua masalah
Tampaknya jawaban di sini tidak mencakup semua jenis yang dimungkinkan dalam JavaScript, jadi berikut adalah beberapa contoh singkat tentang cara menghadapinya dengan benar:
Saya tidak merekomendasikan untuk menyimpan fungsi karena
eval()
kejahatan dapat menyebabkan masalah keamanan, pengoptimalan, dan debugging. Secara umum,eval()
jangan pernah digunakan dalam kode JavaScript.Anggota pribadi
Masalah dengan menggunakan
JSON.stringify()
untuk menyimpan objek adalah, bahwa fungsi ini tidak dapat membuat serial anggota pribadi. Masalah ini dapat diatasi dengan menimpa.toString()
metode (yang disebut secara implisit saat menyimpan data dalam penyimpanan web):Referensi melingkar
Masalah lain yang
stringify
tidak bisa ditangani adalah referensi sirkuler:Dalam contoh ini,
JSON.stringify()
akan membuangTypeError
"Konversi struktur melingkar ke JSON" . Jika menyimpan referensi melingkar harus didukung, parameter keduaJSON.stringify()
mungkin digunakan:Namun, menemukan solusi yang efisien untuk menyimpan referensi melingkar sangat tergantung pada tugas-tugas yang perlu diselesaikan, dan mengembalikan data tersebut juga tidak sepele.
Sudah ada beberapa pertanyaan tentang SO yang berurusan dengan masalah ini: Stringify (convert to JSON) objek JavaScript dengan referensi melingkar
sumber
Ada perpustakaan hebat yang membungkus banyak solusi sehingga bahkan mendukung browser lama yang disebut jStorage
Anda dapat mengatur objek
Dan mengambilnya dengan mudah
sumber
Secara teori, dimungkinkan untuk menyimpan objek dengan fungsi:
Namun, Serialisasi / deserialisasi fungsi tidak dapat diandalkan karena bergantung pada implementasi .
sumber
c.f[k] = escape(a[k]);
dengan Unicode-safec.f[k] = encodeURIComponent(a[k]);
daneval('b.' + k + ' = ' + unescape(data.f[k]));
withb[k] = eval("(" + decodeURIComponent(data.f[k]) + ")");
. Tanda kurung diperlukan karena fungsi Anda, jika diserialisasi dengan benar, kemungkinan akan anonim, yang bukan as-adalah valid / Pernyataan / (jadieval()
) akan memberikanSyntaxError
pengecualian jika tidak).typeof
merupakan operator , jangan menuliskannya seolah-olah itu sebuah fungsi. Gantitypeof(a[k])
dengantypeof a[k]
.for
-in
tidak difilter untuk properti sendiri. 3. Gaya kode, termasuk referensi, tidak konsisten.the use and placement of white space, line terminators, and semicolons within the representation String is implementation-dependent.
saya tidak melihat perbedaan fungsional.Note *in particular* that …
. Tetapi spesifikasi nilai kembali dimulai denganAn implementation-dependent representation of the function is returned. This representation has the syntax of a FunctionDeclaration.
Nilai kembali dapatfunction foo () {}
- dengan asumsi implementasi yang sesuai .Saya tiba di pos ini setelah mengenai pos lain yang telah ditutup sebagai duplikat dari ini - berjudul 'bagaimana cara menyimpan array di penyimpanan lokal?'. Yang baik-baik saja kecuali tidak ada utas yang benar-benar memberikan jawaban lengkap tentang bagaimana Anda dapat mempertahankan array di localStorage - namun saya telah berhasil membuat solusi berdasarkan informasi yang terkandung dalam kedua utas.
Jadi, jika ada orang lain yang ingin dapat mendorong / pop / menggeser item dalam sebuah array, dan mereka ingin array itu disimpan di localStorage atau memang sessionStorage, ini dia:
contoh penggunaan - menyimpan string sederhana dalam array localStorage:
contoh penggunaan - menyimpan objek dalam array sessionStorage:
metode umum untuk memanipulasi array:
sumber
Rekomendasikan penggunaan perpustakaan abstraksi untuk banyak fitur yang dibahas di sini serta kompatibilitas yang lebih baik. Banyak pilihan:
sumber
Anda dapat menggunakan localDataStorage untuk secara transparan menyimpan tipe data javascript (Array, Boolean, Date, Float, Integer, String dan Object). Ini juga memberikan kebingungan data yang ringan, secara otomatis memampatkan string, memfasilitasi kueri menurut kunci (nama) serta kueri menurut nilai (kunci), dan membantu untuk menegakkan penyimpanan bersama tersegmentasi dalam domain yang sama dengan kunci awalan.
[DISCLAIMER] Saya adalah penulis utilitas [/ DISCLAIMER]
Contoh:
Seperti yang Anda lihat, nilai-nilai primitif dihormati.
sumber
Opsi lain adalah menggunakan plugin yang ada.
Misalnya persisto adalah proyek sumber terbuka yang menyediakan antarmuka yang mudah untuk penyimpanan / sesi lokal dan mengotomatiskan kegigihan untuk bidang formulir (input, tombol radio, dan kotak centang).
(Penafian: Saya penulis.)
sumber
localStroage
; exp:var lsh = new localStorageHelper(); lsh.setItem('bob', 'bill');
Juga termasuk acara.Kamu bisa menggunakan ejson untuk menyimpan objek sebagai string.
Ini adalah pembungkus localStorage saya menggunakan ejson
https://github.com/UziTech/storage.js
Saya menambahkan beberapa jenis ke pembungkus saya termasuk ekspresi dan fungsi reguler
sumber
Saya membuat pembungkus minimalis lainnya dengan hanya 20 baris kode untuk memungkinkan menggunakannya seperti seharusnya:
https://github.com/zevero/simpleWebstorage
sumber
Untuk pengguna naskah yang bersedia menyetel dan mendapatkan properti yang diketik:
Contoh penggunaan :
sumber
https://github.com/adrianmay/rhaboo adalah lapisan gula penyimpanan lokal yang memungkinkan Anda menulis hal-hal seperti ini:
Itu tidak menggunakan JSON.stringify / parse karena itu akan tidak akurat dan lambat pada objek besar. Sebagai gantinya, setiap nilai terminal memiliki entri Penyimpanan lokal.
Anda mungkin bisa menebak bahwa saya mungkin ada hubungannya dengan rhaboo.
sumber
Berikut beberapa versi kode yang diposkan oleh @danott
Ini juga akan menerapkan nilai hapus dari penyimpanan lokal dan menunjukkan cara menambahkan lapisan Getter dan Setter jadi alih-alih
localstorage.setItem(preview, true)
kamu bisa menulis
config.preview = true
Baiklah, ini dia:
Anda juga dapat menghapus bagian alias dengan
.bind(...)
. Namun saya hanya memasukkannya karena sangat bagus untuk mengetahui hal ini. Saya menghabiskan waktu berjam-jam untuk mencari tahu mengapa cara sederhanaget = localStorage.getItem;
tidak berhasilsumber
Saya membuat sesuatu yang tidak merusak objek Storage yang ada, tetapi membuat pembungkus sehingga Anda dapat melakukan apa yang Anda inginkan. Hasilnya adalah objek normal, tidak ada metode, dengan akses seperti objek apa pun.
Benda yang saya buat.
Jika Anda ingin 1
localStorage
properti menjadi sihir:Jika Anda memerlukan beberapa:
Semua yang Anda lakukan
prop
, atau objek di dalamnyastorage
akan disimpan secara otomatislocalStorage
. Anda selalu bermain dengan objek nyata, sehingga Anda dapat melakukan hal-hal seperti ini:Dan setiap objek baru di dalam objek yang dilacak akan secara otomatis dilacak.
Kelemahan yang sangat besar: tergantung pada
Object.observe()
sehingga memiliki dukungan browser yang sangat terbatas. Dan sepertinya tidak akan datang untuk Firefox atau Edge dalam waktu dekat.sumber
Anda tidak dapat menyimpan nilai kunci tanpa Format String .
LocalStorage hanya mendukung format String untuk kunci / nilai.
Itu sebabnya Anda harus mengubah data Anda menjadi string apa pun itu Array atau Obyek .
Untuk Menyimpan data di localStorage, pertama-tama ikatlah menggunakan metode JSON.stringify () .
Kemudian ketika Anda ingin mengambil data, Anda perlu mengurai String ke Objek lagi.
Semoga ini bisa membantu.
sumber
Untuk menyimpan objek, Anda bisa membuat huruf yang bisa Anda gunakan untuk mendapatkan objek dari string ke objek (mungkin tidak masuk akal). Sebagai contoh
Teknik ini akan menyebabkan beberapa gangguan jika Anda menggunakan huruf yang Anda gunakan untuk membagi objek, dan itu juga sangat eksperimental.
sumber
Saya menemukan cara untuk membuatnya bekerja dengan objek yang memiliki referensi siklik.
Mari kita membuat objek dengan referensi siklik.
Kita tidak dapat melakukannya di
JSON.stringify
sini, karena referensi melingkar.LOCALSTORAGE.CYCLICJSON
memiliki.stringify
dan.parse
seperti biasaJSON
, tetapi bekerja dengan objek dengan referensi melingkar. ("Karya" yang berarti parse (stringify (obj)) dan obj sama dalam DAN memiliki set identik 'persamaan internal')Tapi kita bisa menggunakan pintasan:
Maka,
recovered
akan "sama" dengan keberatan, dalam arti berikut:Berikut ini adalah implementasi dari
LOCALSTORAGE
sumber
localStorage.setItem ('user', JSON.stringify (user));
Lalu untuk mengambilnya dari toko dan mengubahnya menjadi objek lagi:
var user = JSON.parse (localStorage.getItem ('user'));
Jika kita perlu menghapus semua entri toko, kita cukup melakukannya:
localStorage.clear ();
sumber