Impossible de définir des valeurs booléennes dans LocalStorage?


112

J'ai remarqué que je ne peux pas définir de valeurs booléennes dans localStorage?

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

Alerte toujours true | falselorsque j'essaie de le tester localStorage.getItem("item1") == "true"alerte vrai ... Comment puis-je définir un élément localStoragesur vrai?

Même si c'est une chaîne, je pensais seulement ===vérifier le type?

Alors

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

Réponses:


69

L'implémentation du stockage par Firefox ne peut stocker que des chaînes, mais en septembre 2009 , le W3C a modifié le brouillon pour accepter toutes les données.L'implémentation n'est (toujours) pas encore rattrapée( voir Modifier ci-dessous ).

Donc, dans votre cas, le booléen est converti en chaîne.

Quant à savoir pourquoi "true" != true, comme écrit dans la description de Equal ( ==) dans MDC *:

Si les deux opérandes ne sont pas du même type, JavaScript convertit les opérandes puis applique une comparaison stricte. Si l'un des opérandes est un nombre ou un booléen, les opérandes sont convertis en nombres si possible; sinon, si l'un des opérandes est une chaîne, l'autre opérande est converti en chaîne si possible.

Notez que la chaîne est convertie en un nombre au lieu d'un booléen . Puisque "true"converti en nombre est NaN, il ne sera égal à rien, il falseest donc retourné.

(*: Pour la norme actuelle, voir ECMA-262 §11.9.3 «L'algorithme de comparaison d'égalité abstraite»)


Edit: L' setIteminterface a été rétablie pour accepter les chaînes uniquement sur le brouillon du 1er septembre 2011 pour correspondre au comportement des implémentations existantes, car aucun des fournisseurs n'est intéressé par la prise en charge du stockage des non-chaînes. Voir https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 pour plus de détails.


2
Si l'un des opérandes est un nombre ou un booléen, les opérandes sont convertis en nombres si possible - je ne m'en suis pas rendu compte. Je pensais que si l'un était une corde, l'autre était jeté en corde. Bravo (+1).
Andy E

2
@Andy, consultez ces notes utiles sur le sujet.
CMS

91

Pour le moment, toutes les implémentations Safari , WebKit, Chrome, Firefox et IE , suivent une ancienne version du standard WebStorage, où la valeur des éléments de stockage ne peut être qu'une chaîne.

Une option serait d'utiliser JSON parseet une stringifyméthode pour sérialiser et désérialiser les données, comme je l'ai suggéré il y a quelque temps dans une autre question , par exemple:

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

4
Cela sera évidemment cassé si la chaîne passée valuen'est pas JSON valide (par exemple JSON.parse("a random string"))
Adonis K. Kakoulidis

3
Vrai @AdonisK. Mais s'il utilise JSON.stringify lors de la définition de toutes les valeurs, il est en mesure de se décharger de la responsabilité de générer un JSON valide dans la bibliothèque. Et c'est une bibliothèque très stable.
Colt McCormack

11

Mes solutions:

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

2
@koppor Peut-être parce que si getItem retournait un jour un booléen, alors cette méthode produira de faux résultats, puisque true == 'true'c'est le cas false.
jox

8
..ou plaine localStorage.getItem(pre)==='true'sans le reste
phil294

1
@koppor pourquoi est-ce voté à la baisse? parce que les empileurs bien-pensants débordent, littéralement :)
Ayyash

1
"? true: false" n'est pas nécessaire car localStorage.getItem (pre) == 'true' vous donne déjà un résultat booléen
FelipeDrumond

6

Ceci est lié à la réponse de CMS.

Voici une petite fonction que j'ai utilisée pour gérer la partie analyse de ce problème (la fonction continuera à faire la bonne chose après que les implémentations du navigateur aient rattrapé la spécification, donc pas besoin de se rappeler de changer le code plus tard):

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

1
N'est-ce pas inutile par rapport à JSON.parse? JSON.parse ("true") et JSON.parse (true) renvoient déjà tous les deux true, donc feront toujours la bonne chose après que les navigateurs aient implémenté le booléen localstorage
bscan

3

Utilisez store.js :

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

store.get('isUser')  //true

4
Mais est-il vraiment nécessaire d'inclure une bibliothèque entière juste pour cette simple tâche de conversion chaîne en booléen?
jayqui

1

Je ne sais pas si LocalStorage peut enregistrer des valeurs booléennes, mais je peux vous dire que lorsque vous le faites, alert("true" == true);il ne sera jamais évalué à vrai car vous comparez implicitement une chaîne à un booléen. C'est pourquoi vous devez définir des valeurs booléennes à la trueplace de "true".


1
Qu'en est-il de l'alerte ("1" == 1)? Javascript est une bête étrange (et incohérente).
dépensier

@spender: c'est parce que le bon opérande est converti en chaîne pour la comparaison. "1" === 1retournerait en fait false.
Andy E

@Kenny: whoops facepalm , merci pour la correction :-) J'étais mélangé à cause de la façon dont les booléens transforment les chaînes.
Andy E

1

evalpeut également être utilisé avec précaution dans certains cas.

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

Évitez evalcar cela peut être dangereux. Préférez JSON.parse("true").
Fred

1

Ce que je fais habituellement, c'est simplement enregistrer la valeur dans LocalStore en tant que booléen, puis la récupérer avec une méthode d'analyse, juste pour être sûr pour tous les navigateurs. Ma méthode ci-dessous est personnalisée pour ma logique métier. Parfois, je pourrais stocker smth comme `` non '' et avoir encore besoin falseen retour

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;}
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.