Tidak dapat menyetel nilai boolean di LocalStorage?

112

Saya perhatikan bahwa saya tidak dapat menyetel nilai boolean localStorage?

localStorage.setItem("item1", true);
alert(localStorage.getItem("item1") + " | " + (localStorage.getItem("item1") == true));

Selalu memberi peringatan true | falseketika saya mencoba untuk mengujinya localStorage.getItem("item1") == "true"memberi tanda benar ... Bagaimana saya bisa menyetel item localStoragemenjadi benar?

Meskipun itu adalah string, saya pikir hanya ===akan memeriksa jenisnya?

Begitu

alert("true" == true); // should be true? 
Jiew Meng
sumber

Jawaban:

69

Implementasi Penyimpanan Firefox hanya dapat menyimpan string, tetapi pada September 2009 , W3C memodifikasi draf untuk menerima data apa pun.Implementasinya (masih) belum selesai( lihat Edit di bawah ).

Jadi dalam kasus Anda, boolean diubah menjadi string.

Adapun alasannya "true" != true, seperti yang tertulis pada uraian Equal ( ==) di MDC *:

Jika kedua operan tidak berjenis sama, JavaScript mengonversi operan tersebut lalu menerapkan perbandingan yang ketat. Jika salah satu operan adalah bilangan atau boolean, operan akan diubah menjadi bilangan jika memungkinkan; else jika salah satu operan adalah string, operan lainnya akan diubah menjadi string jika memungkinkan.

Perhatikan bahwa string diubah menjadi Angka, bukan Boolean . Karena "true"diubah menjadi angka NaN, itu tidak akan sama dengan apa pun, jadi falsedikembalikan.

(*: Untuk standar aktual, lihat ECMA-262 §11.9.3 "Algoritma Perbandingan Kesetaraan Abstrak")


Edit: The setItemantarmuka itu dikembalikan untuk menerima string hanya pada 2011 September 1 rancangan untuk mencocokkan perilaku implementasi yang ada, karena tidak ada vendor yang tertarik dalam mendukung menyimpan non-string. Lihat https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 untuk detailnya.

kennytm
sumber
2
Jika salah satu operan adalah angka atau boolean, operan akan diubah menjadi angka jika memungkinkan - saya sama sekali tidak menyadarinya. Saya pikir jika yang satu adalah string, yang lainnya dilemparkan ke string. Cheers (+1).
Andy E
2
@Andy, periksa catatan berguna tentang subjek ini.
CMS
91

Untuk saat ini, semua implementasi Safari , WebKit, Chrome, Firefox dan IE , mengikuti versi lama standar WebStorage, di mana nilai item penyimpanan hanya berupa string.

Pilihannya adalah menggunakan JSON parsedan stringifymetode untuk membuat serial dan deserialisasi data, seperti yang saya sarankan beberapa waktu lalu di pertanyaan lain , misalnya:

var value = "true";
JSON.parse(value) === true; // true
CMS
sumber
4
Ini jelas akan rusak jika string yang diteruskan valuebukan JSON yang valid (misalnya JSON.parse("a random string"))
Adonis K. Kakoulidis
3
Benar @AdonisK. Tetapi jika dia menggunakan JSON.stringify saat menyetel semua nilai, maka dia dapat melepaskan tanggung jawab untuk mengeluarkan JSON yang valid ke pustaka. Dan itu adalah pustaka yang sangat stabil.
Colt McCormack
11

Solusi saya:

function tytPreGetBool(pre) {
    return localStorage.getItem(pre) === 'true';
}
tyttoot
sumber
2
@koppor Mungkin karena jika getItem akan mengembalikan boolean, maka metode ini akan menghasilkan hasil yang salah, karena true == 'true'itu false.
jox
8
..atau polos localStorage.getItem(pre)==='true'tanpa sisa
phil294
1
@koppor mengapa ini tidak disukai? karena penumpuk merasa benar sendiri meluap, secara harfiah :)
Ayyash
1
"? true: false" tidak diperlukan karena localStorage.getItem (pre) == 'true' sudah memberi Anda hasil boolean
FelipeDrumond
6

Ini terkait dengan jawaban CMS.

Berikut adalah fungsi kecil yang telah saya gunakan untuk menangani bagian penguraian dari masalah ini (fungsi tersebut akan terus melakukan Hal yang Benar setelah implementasi browser mengikuti spesifikasi, jadi tidak perlu ingat untuk mengganti kode nanti):

function parse(type) {
   return typeof type == 'string' ? JSON.parse(type) : type;
}
anak tertua
sumber
1
Bukankah ini tidak perlu dibandingkan dengan JSON.parse? JSON.parse ("true") dan JSON.parse (true) keduanya sudah mengembalikan true, jadi masih akan melakukan hal yang benar setelah browser mengimplementasikan boolean localstorage
bscan
3

Gunakan store.js :

localStorage.setItem('isUser', true)
localStorage.getItem('isUser') === "true" //true
npm i -D store

store.get('isUser')  //true
front-end-engnier
sumber
4
Tetapi apakah benar-benar perlu menyertakan seluruh pustaka hanya untuk tugas konversi string-ke-boolean sederhana ini?
jayqui
1

Saya tidak yakin apakah LocalStorage dapat menyimpan nilai boolean tetapi saya dapat memberi tahu Anda bahwa ketika Anda melakukannya, alert("true" == true);itu tidak akan pernah dievaluasi menjadi true karena Anda secara implisit membandingkan string dengan boolean. Itulah mengapa menyetel nilai boolean yang Anda gunakan, truebukan "true".

Roma
sumber
1
Bagaimana dengan peringatan ("1" == 1)? Javascript adalah sesuatu yang aneh (dan tidak konsisten).
pemboros
@ spender: itu karena operan yang tepat dimasukkan ke string untuk perbandingan. "1" === 1akan benar-benar mengembalikan false.
Andy E
@Kenny: whoops facepalm , terima kasih atas koreksinya :-) Saya bingung karena cara boolean cast ke string.
Andy E
1

evaljuga dapat digunakan dengan hati - hati dalam beberapa kasus.

console.log(eval("true") === true) //true
jalan buntu
sumber
Hindari evalkarena tidak aman. Lebih suka JSON.parse("true").
Fred
1

Apa yang biasanya saya lakukan hanyalah menyimpan nilai di LocalStore sebagai Boolean, dan kemudian mengambilnya dengan metode parsing, untuk memastikannya untuk semua browser. Metode saya di bawah ini disesuaikan untuk logika bisnis saya. Kadang-kadang saya mungkin menyimpan sesuatu sebagai 'tidak' dan masih perlu falsesebagai balasannya

function toBoolean(str) {
    if (typeof str === 'undefined' || str === null) {
        return false;
    } else if (typeof str === 'string') {           
        switch (str.toLowerCase()) {
        case 'false':
        case 'no':
        case '0':
        case "":
            return false;
        default:
            return true;
        }
    } else if (typeof str === 'number') {
        return str !== 0
    }
    else {return true;}
}
JohnPan
sumber