Неможливо встановити булеві значення в LocalStorage?


112

Я помітив, що я не можу встановлювати булеві значення в localStorage?

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

Завжди сповіщення, true | falseколи я намагаюся перевірити localStorage.getItem("item1") == "true"його, попереджає правду ... Як я можу встановити елемент localStorageна істинному?

Навіть якщо це рядок, я думав, що тільки ===перевірять тип?

Так

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

Відповіді:


69

Впровадження Firefox Storage може зберігати лише рядки, але на вересень 2009 року W3C змінив проект, щоб прийняти будь-які дані.Реалізація (досі) ще не наздогнала( див. Редагувати нижче ).

Тож у вашому випадку булевий перетворюється на рядок.

Щодо того "true" != true, як написано в описі рівняння ( ==) в MDC *:

Якщо два операнди не одного типу, JavaScript перетворює операнди, то застосовується суворе порівняння. Якщо будь-який операнд є числом або булевим, операнди перетворюються на числа, якщо це можливо; інакше, якщо будь-який операнд є рядком, інший операнд перетворюється на рядок, якщо це можливо.

Зауважте, що рядок перетворюється на число замість булевого . Оскільки "true"перетворене в число є NaN, воно не буде дорівнювати нічому, тому falseповертається.

(*: Для фактичного стандарту див. Пункт ECM-262 §11.9.3 "Алгоритм порівняння абстрактних рівностей")


Edit:setItem інтерфейс був повернувся приймати рядки тільки на вересень 1 - го проект 2011 року відповідно до поведінкою існуючих реалізацій, так як жоден з постачальників не зацікавлені в підтримці зберігаються не так-рядків. Детальніше дивіться на https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 .


2
Якщо будь-який операнд є числом або булевим, операнди перетворюються на числа, якщо це можливо - я абсолютно не усвідомлював цього. Я думав, що якщо одна струна, то інша кидається в струну. Ура (+1).
Енді Е

2
@Andy, перевірте ці корисні замітки з цього приводу.
CMS

91

Наразі всі реалізації Safari , WebKit, Chrome, Firefox та IE дотримуються старої версії стандарту WebStorage, де значення елементів зберігання може бути лише рядком.

Можливим буде використання JSON parseта stringifyметоду для серіалізації та десеріалізації даних, як я запропонував деякий час тому в іншому запитанні , наприклад:

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

4
Це, очевидно, порушиться, якщо передана рядок valueнедійсна JSON (наприклад JSON.parse("a random string"))
Адоніс К. Какулідіс

3
Правда @AdonisK. Але якщо він використовує JSON.stringify при встановленні всіх значень, він може зняти відповідальність за виведення дійсного JSON в бібліотеку. І це дуже стабільна бібліотека.
Кольт Маккормак

11

Мої рішення:

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

2
@koppor Можливо тому, що якщо getItem коли-небудь поверне булевий, то цей метод дасть помилкові результати, оскільки true == 'true'є false.
jox

8
.. або localStorage.getItem(pre)==='true'
рівна

1
@koppor Чому це знищено? тому що власні праведні
Айяш

1
"true: false" не потрібний, оскільки localStorage.getItem (pre) == "true" вже дає вам
бульовий

6

Це пов’язано з відповіддю CMS.

Ось невелика функція, яку я використовував для обробки розбору частини цієї проблеми (ця функція буде продовжувати виконувати правильну річ після того, як в браузері реалізація наздожене специфікацію, тому не потрібно пам’ятати про те, щоб змінити код пізніше):

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

1
Це не зайве порівняно з JSON.parse? JSON.parse ("true") та JSON.parse (true) вже обидва повертають істину, тому все одно робитимуть правильну справу після того, як браузери реалізують булеві локальні сховища
bscan

3

Використовуйте store.js :

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

store.get('isUser')  //true

4
Але чи дійсно потрібно включати цілу бібліотеку саме для цієї простої задачі перетворення рядка в бул?
jayqui

1

Я не впевнений, що LocalStorage може зберегти булеві значення, але я можу вам сказати, що коли ви alert("true" == true);це зробите, це ніколи не оцінюватиметься як true, оскільки ви неявно порівнюєте рядок із булевими. Ось чому для встановлення булевих значень ви використовуєте trueзамість "true".


1
Що щодо сповіщення ("1" == 1)? Javascript - дивна (і непослідовна) звірина.
витрачається

@spender: це тому, що правильний операнд приведений до рядка для порівняння. "1" === 1насправді повернеться помилковим.
Енді Е

@Kenny: whoops facepalm , дякую за виправлення :-) Мене змішало через те, як булеви кидають на струни.
Енді Е

1

evalтакож можна обережно використовувати в деяких випадках.

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

Уникайте, evalоскільки це може бути небезпечно. Віддавайте перевагу JSON.parse("true").
Фред

1

Що я зазвичай роблю, це просто зберегти значення в LocalStore як булеве, а потім отримати метод розбору, щоб бути впевненим у всіх браузерах. Мій метод нижче налаштований під мою бізнес-логіку. Іноді я можу зберігати smth як "ні" і все одно потребую falseвзамін

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;}
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.