Não é possível definir valores booleanos em LocalStorage?

112

Percebi que não consigo definir valores booleanos em localStorage?

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

Sempre alerta true | falsequando tento testá- localStorage.getItem("item1") == "true"lo, alerta verdadeiro ... Como posso definir um item localStoragecomo verdadeiro?

Mesmo que seja uma string, pensei que só ===verificaria o tipo?

assim

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

Respostas:

69

A implementação de armazenamento do Firefox só pode armazenar strings, mas em setembro de 2009 , o W3C modificou o rascunho para aceitar quaisquer dados.A implementação (ainda) ainda não foi atualizada( veja Editar abaixo ).

Portanto, no seu caso, o booleano é convertido em uma string.

Quanto ao motivo "true" != true, conforme escrito na descrição de Equal ( ==) no MDC *:

Se os dois operandos não forem do mesmo tipo, o JavaScript converte os operandos e aplica a comparação estrita. Se o operando for um número ou booleano, os operandos serão convertidos em números, se possível; senão, se qualquer operando for uma string, o outro operando será convertido em uma string, se possível.

Observe que a string é convertida em um número em vez de um booleano . Como "true"convertido em um número é NaN, ele não será igual a nada, então falseé retornado.

(*: Para o padrão real, consulte ECMA-262 §11.9.3 "O algoritmo de comparação de igualdade abstrata")


Editar: A setIteminterface foi revertida para aceitar strings apenas no rascunho de 1º de setembro de 2011 para corresponder ao comportamento das implementações existentes, pois nenhum dos fornecedores está interessado em oferecer suporte ao armazenamento de não strings. Consulte https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 para obter detalhes.

Kennytm
fonte
2
Se algum dos operandos for um número ou booleano, os operandos serão convertidos em números, se possível - eu não sabia disso totalmente. Pensei que se um fosse uma corda, a outra fosse fundida em uma corda. Saúde (+1).
Andy E
2
@Andy, verifique estas notas úteis sobre o assunto.
CMS de
91

Por enquanto, todas as implementações Safari , WebKit, Chrome, Firefox e IE seguem uma versão antiga do padrão WebStorage, onde o valor dos itens de armazenamento pode ser apenas uma string.

Uma opção seria usar JSON parsee stringifymétodo para serializar e desserializar os dados, como sugeri há algum tempo em outra pergunta , por exemplo:

var value = "true";
JSON.parse(value) === true; // true
CMS
fonte
4
Isso obviamente será interrompido se a string transmitida valuenão for um JSON válido (por exemplo JSON.parse("a random string"))
Adonis K. Kakoulidis
3
True @AdonisK. Mas se ele estiver usando JSON.stringify ao definir todos os valores, ele poderá se livrar da responsabilidade de enviar JSON válido para a biblioteca. E essa é uma biblioteca muito estável.
Colt McCormack de
11

Minhas soluções:

function tytPreGetBool(pre) {
    return localStorage.getItem(pre) === 'true';
}
tyttoot
fonte
2
@koppor Talvez porque se getItem algum dia retornasse um booleano, esse método produziria resultados falsos, já que true == 'true'é false.
jox
8
..ou simples localStorage.getItem(pre)==='true'sem o resto
phil294
1
@koppor por que isso foi rejeitado? porque os stackers hipócritas estão transbordando, literalmente :)
Ayyash
1
"? true: false" é desnecessário, pois localStorage.getItem (pre) == 'true' já fornece um resultado booleano
FelipeDrumond
6

Isso está relacionado à resposta do CMS.

Aqui está uma pequena função que venho usando para lidar com a parte de análise desse problema (a função continuará fazendo a coisa certa depois que as implementações do navegador alcançarem as especificações, portanto, não há necessidade de se lembrar de alterar o código mais tarde):

function parse(type) {
   return typeof type == 'string' ? JSON.parse(type) : type;
}
menino mais velho
fonte
1
Isso não é desnecessário em comparação com JSON.parse? JSON.parse ("true") e JSON.parse (true) já retornam true, então ainda farão a coisa certa após os navegadores implementarem armazenamento local booleano
bscan
3

Use store.js :

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

store.get('isUser')  //true
engenheiro de ponta
fonte
4
Mas é realmente necessário incluir uma biblioteca inteira apenas para essa tarefa simples de conversão de string em booleano?
Jayqui
1

Não tenho certeza se LocalStorage pode salvar valores booleanos, mas posso dizer que, quando você fizer alert("true" == true);isso, nunca será avaliado como verdadeiro porque você está comparando implicitamente uma string com um booleano. É por isso que você deve usar valores booleanos em truevez de "true".

romano
fonte
1
E o alerta ("1" == 1)? Javascript é um animal estranho (e inconsistente).
spender
@spender: isso ocorre porque o operando correto é convertido em uma string para comparação. "1" === 1retornaria realmente falso.
Andy E
@Kenny: opa facepalm , obrigado pela correção :-) Eu estava confuso por causa de como booleanos convertidos em strings.
Andy E
1

evaltambém pode ser usado com cuidado em alguns casos.

console.log(eval("true") === true) //true
impasse
fonte
Evite, evalpois pode ser inseguro. Prefira JSON.parse("true").
Fred de
1

O que geralmente faço é apenas salvar o valor em LocalStore como um booleano e, em seguida, recuperar com um método de análise, apenas para ter certeza para todos os navegadores. Meu método abaixo é personalizado para minha lógica de negócios. Às vezes, posso armazenar smth como "não" e ainda precisar falseem troca

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
fonte