Boolesche Werte in LocalStorage können nicht festgelegt werden?

112

Ich habe festgestellt, dass ich keine booleschen Werte festlegen kann localStorage.

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

Immer Warnungen, true | falsewenn ich versuche, localStorage.getItem("item1") == "true"sie zu testen. Warnungen true ... Wie kann ich ein Element localStorageauf true setzen?

Selbst wenn es eine Zeichenfolge ist, dachte ich, ===würde nur den Typ überprüfen?

So

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

Antworten:

69

In der Firefox-Implementierung von Storage können nur Zeichenfolgen gespeichert werden. Im September 2009 hat W3C den Entwurf so geändert, dass alle Daten akzeptiert werden.Die Implementierung (noch) ist noch nicht aufgeholt( siehe Bearbeiten unten ).

In Ihrem Fall wird der Boolesche Wert also in einen String konvertiert.

Wie "true" != true, wie in der Beschreibung von Equal ( ==) in MDC * geschrieben:

Wenn die beiden Operanden nicht vom gleichen Typ sind, konvertiert JavaScript die Operanden und wendet dann einen strengen Vergleich an. Wenn einer der Operanden eine Zahl oder ein Boolescher Wert ist, werden die Operanden nach Möglichkeit in Zahlen konvertiert . Wenn einer der Operanden eine Zeichenfolge ist, wird der andere Operand nach Möglichkeit in eine Zeichenfolge konvertiert.

Beachten Sie, dass die Zeichenfolge anstelle eines Booleschen Werts in eine Zahl konvertiert wird . Da in eine Zahl konvertiert ist , wird es nicht gleich irgendetwas sein, also wird zurückgegeben."true"NaNfalse

(*: Für den aktuellen Standard siehe ECMA-262 §11.9.3 „Der abstrakte Gleichheitsvergleichsalgorithmus“)


Bearbeiten: Die setItemBenutzeroberfläche wurde zurückgesetzt, um Zeichenfolgen nur im Entwurf vom 1. September 2011 zu akzeptieren , um dem Verhalten vorhandener Implementierungen zu entsprechen, da keiner der Anbieter daran interessiert ist, das Speichern von Nicht-Zeichenfolgen zu unterstützen. Weitere Informationen finden Sie unter https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 .

kennytm
quelle
2
Wenn einer der Operanden eine Zahl oder ein Boolescher Wert ist, werden die Operanden nach Möglichkeit in Zahlen konvertiert - das habe ich überhaupt nicht bemerkt. Ich dachte, wenn einer eine Saite wäre, würde der andere zu einer Saite gegossen. Prost (+1).
Andy E
2
@Andy, überprüfen Sie diese nützlichen Hinweise zu diesem Thema.
CMS
91

Derzeit folgen alle Implementierungen von Safari , WebKit, Chrome, Firefox und IE einer alten Version des WebStorage-Standards, bei der der Wert der Speicherelemente nur eine Zeichenfolge sein kann.

Eine Option wäre die Verwendung von JSON parseund einer stringifyMethode zum Serialisieren und Deserialisieren der Daten, wie ich vor einiger Zeit in einer anderen Frage vorgeschlagen habe , zum Beispiel:

var value = "true";
JSON.parse(value) === true; // true
CMS
quelle
4
Dies wird offensichtlich brechen, wenn die übergebene Zeichenfolge valuenicht gültig ist JSON (zum Beispiel JSON.parse("a random string"))
Adonis K. Kakoulidis
3
True @AdonisK. Wenn er jedoch JSON.stringify verwendet, um alle Werte festzulegen, kann er die Verantwortung für die Ausgabe von gültigem JSON an die Bibliothek übertragen. Und das ist eine sehr stabile Bibliothek.
Colt McCormack
11

Meine Lösungen:

function tytPreGetBool(pre) {
    return localStorage.getItem(pre) === 'true';
}
tyttoot
quelle
2
@koppor Vielleicht , weil wenn getItem würde jemals einen boolean zurück, dann wird diese Methode falsche Ergebnisse liefern, da true == 'true'heißt false.
Jox
8
..oder Ebene localStorage.getItem(pre)==='true'ohne den Rest
phil294
1
@koppor warum wird das herabgestimmt? weil die selbstgerechten Stapler buchstäblich überlaufen :)
Ayyash
1
"? true: false" ist nicht erforderlich, da localStorage.getItem (pre) == 'true' bereits ein boolesches Ergebnis
liefert
6

Dies hängt mit der Antwort von CMS zusammen.

Hier ist eine kleine Funktion, die ich verwendet habe, um den Parsing-Teil dieses Problems zu behandeln (die Funktion wird weiterhin das Richtige tun, nachdem die Browser-Implementierungen die Spezifikation eingeholt haben, sodass Sie nicht daran denken müssen, den Code später zu ändern):

function parse(type) {
   return typeof type == 'string' ? JSON.parse(type) : type;
}
ältester lebender Junge
quelle
1
Ist das im Vergleich zu JSON.parse nicht unnötig? JSON.parse ("true") und JSON.parse (true) geben bereits beide true zurück und werden daher immer noch das Richtige tun, nachdem Browser boolean
localstorage
3

Verwenden Sie store.js :

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

store.get('isUser')  //true
Front-End-Engnier
quelle
4
Aber ist es wirklich notwendig, eine ganze Bibliothek nur für diese einfache Konvertierungsaufgabe von String zu Boolesch einzuschließen?
Jayqui
1

Ich bin nicht sicher, ob LocalStorage boolesche Werte speichern kann, aber ich kann Ihnen sagen, dass dies alert("true" == true);niemals als wahr ausgewertet wird, da Sie implizit eine Zeichenfolge mit einem booleschen Wert vergleichen. Aus diesem Grund sollten Sie truestattdessen boolesche Werte festlegen "true".

römisch
quelle
1
Was ist mit Alarm ("1" == 1)? Javascript ist eine seltsame (und inkonsistente) Bestie.
Spender
@spender: Das liegt daran, dass der richtige Operand für den Vergleich in eine Zeichenfolge umgewandelt wird. "1" === 1würde tatsächlich falsch zurückgeben.
Andy E.
@Kenny: hoppla facepalm , danke für die Korrektur :-) Ich wurde wegen gemischt , wie booleans in Strings gegossen.
Andy E.
1

evalkann in einigen Fällen auch vorsichtig verwendet werden.

console.log(eval("true") === true) //true
Sackgasse
quelle
Vermeiden Sie dies, evalda es unsicher sein kann. Lieber JSON.parse("true").
Fred
1

Normalerweise speichere ich den Wert in LocalStore nur als Booleschen Wert und rufe ihn dann mit einer Analysemethode ab, um sicherzugehen, dass alle Browser dies tun. Meine Methode unten ist für meine Geschäftslogik angepasst. Manchmal speichere ich etw als "Nein" und brauche es immer noch falseals Gegenleistung

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
quelle