Non è possibile impostare valori booleani in LocalStorage?


112

Ho notato che non posso impostare valori booleani in localStorage?

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

Avvisa sempre true | falsequando provo a testarlo localStorage.getItem("item1") == "true"avvisa vero ... Come posso impostare un elemento localStoragesu vero?

Anche se è una stringa, ho pensato di ===controllare solo il tipo?

Così

alert("true" == true); // should be true? 

Risposte:


69

L'implementazione di Storage di Firefox può memorizzare solo stringhe, ma nel settembre 2009 , il W3C ha modificato la bozza per accettare tutti i dati.L'implementazione (ancora) non è stata ancora raggiunta( vedi Modifica sotto ).

Quindi nel tuo caso il valore booleano viene convertito in una stringa.

Quanto al perché "true" != true, come scritto nella descrizione di Equal ( ==) in MDC *:

Se i due operandi non sono dello stesso tipo, JavaScript converte gli operandi quindi applica un confronto rigoroso. Se uno degli operandi è un numero o un booleano, gli operandi vengono convertiti in numeri, se possibile; altrimenti se uno degli operandi è una stringa, l'altro operando viene convertito in una stringa, se possibile.

Notare che la stringa viene convertita in un numero invece che in un booleano . Poiché "true"convertito in un numero è NaN, non sarà uguale a nulla, quindi falseviene restituito.

(*: Per lo standard attuale, vedere ECMA-262 §11.9.3 "The Abstract Equality Comparison Algorithm")


Modifica: l' setIteminterfaccia è stata ripristinata per accettare le stringhe solo nella bozza del 1 ° settembre 2011 per adattarsi al comportamento delle implementazioni esistenti, poiché nessuno dei fornitori è interessato a supportare l'archiviazione di non stringhe. Vedi https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 per i dettagli.


2
Se uno degli operandi è un numero o un booleano, gli operandi vengono convertiti in numeri se possibile - non me ne rendevo assolutamente conto. Ho pensato che se uno fosse una stringa, l'altro fosse fuso su una stringa. Saluti (+1).
Andy E

2
@ Andy, controlla queste note utili sull'argomento.
CMS

91

Per il momento, tutte le implementazioni Safari , WebKit, Chrome, Firefox e IE , seguono una vecchia versione dello standard WebStorage, dove il valore degli elementi di archiviazione può essere solo una stringa.

Un'opzione potrebbe essere quella di utilizzare JSON parsee il stringifymetodo per serializzare e deserializzare i dati, come ho suggerito qualche tempo fa in un'altra domanda , ad esempio:

var value = "true";
JSON.parse(value) === true; // true

4
Questo ovviamente si interromperà se la stringa passata valuenon è JSON valido (ad esempio JSON.parse("a random string"))
Adonis K. Kakoulidis

3
Vero @AdonisK. Ma se utilizza JSON.stringify quando imposta tutti i valori, è in grado di scaricare la responsabilità di inviare un JSON valido alla libreria. E questa è una libreria molto stabile.
Colt McCormack

11

Le mie soluzioni:

function tytPreGetBool(pre) {
    return localStorage.getItem(pre) === 'true';
}

2
@koppor Forse perché se getItem restituisse un valore booleano, questo metodo produrrà risultati falsi, poiché true == 'true'è false.
jox

8
..o semplice localStorage.getItem(pre)==='true'senza il resto
phil294

1
@koppor perché questo è stato votato contro? perché gli impilatori ipocriti stanno traboccando, letteralmente :)
Ayyash

1
"? true: false" non è necessario poiché localStorage.getItem (pre) == 'true' fornisce già un risultato booleano
FelipeDrumond

6

Questo è legato alla risposta di CMS.

Ecco una piccola funzione che ho utilizzato per gestire la parte di analisi di questo problema (la funzione continuerà a fare la cosa giusta dopo che le implementazioni del browser avranno raggiunto le specifiche, quindi non è necessario ricordarsi di modificare il codice in seguito):

function parse(type) {
   return typeof type == 'string' ? JSON.parse(type) : type;
}

1
Non è questo inutile rispetto a JSON.parse? JSON.parse ("true") e JSON.parse (true) restituiscono già entrambi true, quindi continueranno a funzionare correttamente dopo che i browser implementeranno boolean localstorage
bscan

3

Usa store.js :

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

store.get('isUser')  //true

4
Ma è davvero necessario includere un'intera libreria solo per questa semplice operazione di conversione da stringa a booleana?
jayqui

1

Non sono sicuro che LocalStorage possa salvare valori booleani, ma posso dirti che quando lo fai alert("true" == true);non restituirà mai true perché stai confrontando implicitamente una stringa con un booleano. Questo è il motivo per cui impostare i valori booleani che usi al trueposto di "true".


1
E l'avviso ("1" == 1)? Javascript è una bestia strana (e inconsistente).
spender

@spender: questo perché viene eseguito il cast dell'operando giusto su una stringa per il confronto. "1" === 1restituirebbe effettivamente falso.
Andy E

@ Kenny: whoops facepalm , grazie per la correzione :-) Sono stato confuso a causa di come i booleani vengono trasmessi alle corde.
Andy E

1

evalpuò anche essere usato con attenzione in alcuni casi.

console.log(eval("true") === true) //true

Evita evalperché può essere pericoloso. Prefer JSON.parse("true").
Fred,

1

Quello che di solito faccio è salvare il valore in LocalStore come booleano, quindi recuperarlo con un metodo di analisi, giusto per essere sicuro per tutti i browser. Il mio metodo di seguito è personalizzato per la mia logica aziendale. A volte potrei memorizzare smth come "no" e ancora bisogno falsein cambio

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;}
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.