¿No se pueden establecer valores booleanos en LocalStorage?

112

Me di cuenta de que no puedo establecer valores booleanos en localStorage?

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

Siempre alerta true | falsecuando intento probarlo localStorage.getItem("item1") == "true", alerta verdadero ... ¿Cómo puedo configurar un elemento en localStorageverdadero?

Incluso si es una cadena, pensé que solo ===comprobaría el tipo.

Entonces

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

Respuestas:

69

La implementación de Storage de Firefox solo puede almacenar cadenas, pero en septiembre de 2009 , W3C modificó el borrador para aceptar cualquier dato.La implementación (todavía) no se ha puesto al día todavía( ver Editar a continuación ).

Entonces, en su caso, el booleano se convierte en una cadena.

En cuanto a por qué "true" != true, como está escrito en la descripción de Equal ( ==) en MDC *:

Si los dos operandos no son del mismo tipo, JavaScript convierte los operandos y luego aplica una comparación estricta. Si alguno de los operandos es un número o un booleano, los operandos se convierten en números si es posible; de lo contrario, si alguno de los operandos es una cadena, el otro operando se convierte en una cadena si es posible.

Tenga en cuenta que la cadena se convierte en un número en lugar de un booleano . Dado que "true"convertido a un número es NaN, no será igual a nada, por lo que falsese devuelve.

(*: Para conocer el estándar actual, consulte ECMA-262 §11.9.3 “El algoritmo de comparación de igualdad abstracta”)


Editar: La setIteminterfaz se revirtió para aceptar cadenas solo en el borrador del 1 de septiembre de 2011 para que coincida con el comportamiento de las implementaciones existentes, ya que ninguno de los proveedores está interesado en admitir el almacenamiento de cadenas que no sean cadenas. Consulte https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 para obtener más detalles.

Kennytm
fuente
2
Si alguno de los operandos es un número o un booleano, los operandos se convierten en números si es posible ; no me di cuenta de eso. Pensé que si uno era una cuerda, el otro estaba convertido en una cuerda. Saludos (+1).
Andy E
2
@Andy, mira estas útiles notas sobre el tema.
CMS
91

Por el momento, todas las implementaciones de Safari , WebKit, Chrome, Firefox e IE , siguen una versión antigua del estándar WebStorage, donde el valor de los elementos de almacenamiento puede ser solo una cadena.

Una opción sería usar JSON parsey el stringifymétodo para serializar y deserializar los datos, como sugerí hace algún tiempo en otra pregunta , por ejemplo:

var value = "true";
JSON.parse(value) === true; // true
CMS
fuente
4
Esto obviamente se romperá si la cadena pasada valueno es JSON válido (por ejemplo JSON.parse("a random string"))
Adonis K. Kakoulidis
3
Verdadero @AdonisK. Pero si está usando JSON.stringify al establecer todos los valores, entonces puede descargar la responsabilidad de generar JSON válido en la biblioteca. Y esa es una biblioteca muy estable.
Colt McCormack
11

Mis soluciones:

function tytPreGetBool(pre) {
    return localStorage.getItem(pre) === 'true';
}
tyttoot
fuente
2
@koppor Tal vez porque si getItem alguna vez devuelve un valor booleano, este método producirá resultados falsos, ya que true == 'true'es false.
jox
8
..o llano localStorage.getItem(pre)==='true'sin el resto
phil294
1
@koppor ¿por qué se ha votado en contra? porque los apiladores santurrones están desbordados, literalmente :)
Ayyash
1
"? true: false" no es necesario ya que localStorage.getItem (pre) == 'true' ya le da un resultado booleano
FelipeDrumond
6

Esto está relacionado con la respuesta de CMS.

Aquí hay una pequeña función que he estado usando para manejar la parte de análisis de este problema (la función seguirá haciendo lo correcto después de que las implementaciones del navegador se pongan al día con la especificación, por lo que no es necesario recordar cambiar el código más adelante):

function parse(type) {
   return typeof type == 'string' ? JSON.parse(type) : type;
}
niño mayor
fuente
1
¿No es esto innecesario en comparación con JSON.parse? JSON.parse ("true") y JSON.parse (true) ya devuelven true, por lo que seguirán haciendo lo correcto después de que los navegadores implementen el almacenamiento local booleano
bscan
3

Utilice store.js :

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

store.get('isUser')  //true
engnier de front-end
fuente
4
Pero, ¿es realmente necesario incluir una biblioteca completa solo para esta simple tarea de conversión de cadena a booleana?
jayqui
1

No estoy seguro de si LocalStorage puede guardar valores booleanos, pero puedo decirle que cuando lo haga alert("true" == true);nunca se evaluará como verdadero porque está comparando implícitamente una cadena con un booleano. Es por eso que para establecer los valores booleanos que usa en truelugar de "true".

romano
fuente
1
¿Qué pasa con la alerta ("1" == 1)? Javascript es una bestia extraña (e inconsistente).
gastador
@spender: eso se debe a que el operando correcto se convierte en una cadena para la comparación. "1" === 1en realidad devolvería falso.
Andy E
@Kenny: whoops facepalm , gracias por la corrección :-) Estaba confundido por cómo los booleanos se lanzan a las cuerdas.
Andy E
1

evaltambién se puede utilizar con cuidado en algunos casos.

console.log(eval("true") === true) //true
punto muerto
fuente
Evítelo evalya que puede ser peligroso. Preferir JSON.parse("true").
Fred
1

Lo que suelo hacer es guardar el valor en LocalStore como booleano y luego recuperarlo con un método de análisis, solo para estar seguro para todos los navegadores. Mi método a continuación está personalizado para mi lógica empresarial. A veces puedo almacenar algo como 'no' y todavía necesito falsea 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;}
}
JohnPan
fuente