Không thể đặt giá trị boolean trong LocalStorage?


112

Tôi nhận thấy rằng tôi không thể đặt giá trị boolean trong localStorage?

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

Luôn cảnh báo true | falsekhi tôi cố gắng kiểm tra localStorage.getItem("item1") == "true"thông báo đó là true ... Làm cách nào để đặt một mục localStoragethành true?

Ngay cả khi đó là một chuỗi, tôi nghĩ chỉ ===sẽ kiểm tra loại?

Vì thế

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

Câu trả lời:


69

Việc triển khai Storage của Firefox chỉ có thể lưu trữ các chuỗi, nhưng vào tháng 9 năm 2009 , W3C đã sửa đổi bản nháp để chấp nhận bất kỳ dữ liệu nào.Việc triển khai (vẫn) chưa được bắt kịp( xem Chỉnh sửa bên dưới ).

Vì vậy, trong trường hợp của bạn, boolean được chuyển đổi thành một chuỗi.

Đối với lý do tại sao "true" != true, như được viết trong mô tả của Equal ( ==) trong MDC *:

Nếu hai toán hạng không cùng loại, JavaScript sẽ chuyển đổi các toán hạng sau đó áp dụng so sánh chặt chẽ. Nếu một trong hai toán hạng là một số hoặc một boolean, các toán hạng được chuyển đổi thành số nếu có thể; khác nếu một trong hai toán hạng là một chuỗi, toán hạng kia được chuyển đổi thành một chuỗi nếu có thể.

Lưu ý rằng chuỗi được chuyển đổi thành Số thay vì Boolean . Vì được "true"chuyển đổi thành một số NaN, nó sẽ không bằng bất kỳ thứ gì, vì vậy falseđược trả về.

(*: Đối với tiêu chuẩn thực tế, xem ECMA-262 §11.9.3 “Thuật toán so sánh bình đẳng trừu tượng”)


Chỉnh sửa: Các setItemgiao diện đã được trở lại là chấp nhận chuỗi chỉ trên 2011 Tháng Chín dự thảo 1st để phù hợp với hành vi của hiện thực đang tồn tại, như không ai trong số các nhà cung cấp được quan tâm trong việc hỗ trợ lưu trữ không dây. Xem https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 để biết chi tiết.


2
Nếu một trong hai toán hạng là một số hoặc một boolean, các toán hạng sẽ được chuyển đổi thành số nếu có thể - tôi hoàn toàn không nhận ra điều đó. Tôi nghĩ nếu một cái là một chuỗi thì cái kia sẽ được chuyển thành một chuỗi. Chúc mừng (+1).
Andy E,

2
@Andy, kiểm tra ghi chú hữu ích về chủ đề này.
CMS

91

Hiện tại, tất cả các triển khai Safari , WebKit, Chrome, FirefoxIE đều tuân theo phiên bản cũ của tiêu chuẩn WebStorage, trong đó giá trị của các mục lưu trữ có thể chỉ là một chuỗi.

Một lựa chọn sẽ được sử dụng JSON parsestringifyphương pháp để serializedeserialize dữ liệu, như tôi đã đề xuất một số thời gian trước đây trong một câu hỏi khác , ví dụ:

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

4
Điều này rõ ràng sẽ phá vỡ nếu chuỗi được thông qua năm valuekhông phải là JSON hợp lệ (ví dụ JSON.parse("a random string"))
Adonis K. Kakoulidis

3
Đúng @AdonisK. Nhưng nếu anh ấy đang sử dụng JSON.stringify khi đặt tất cả các giá trị thì anh ấy có thể giảm tải trách nhiệm xuất JSON hợp lệ vào thư viện. Và đó là một thư viện rất ổn định.
Colt McCormack

11

Giải pháp của tôi:

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

2
@koppor Có lẽ bởi vì nếu GetItem sẽ bao giờ trả về một boolean, sau đó phương pháp này sẽ mang lại kết quả sai, vì true == 'true'false.
jox

8
..or đồng bằng localStorage.getItem(pre)==='true'mà không có sự nghỉ ngơi
phil294

1
@koppor tại sao điều này bị bỏ phiếu thấp? vì stackers tự mãn đang tràn, theo nghĩa đen :)
Ayyash

1
"? true: false" là không cần thiết vì localStorage.getItem (pre) == 'true' đã cung cấp cho bạn kết quả boolean
FelipeDrumond

6

Điều này liên quan đến câu trả lời của CMS.

Đây là một chức năng nhỏ mà tôi đã sử dụng để xử lý phần phân tích cú pháp của vấn đề này (chức năng này sẽ tiếp tục thực hiện Điều đúng đắn sau khi triển khai trình duyệt bắt kịp với thông số kỹ thuật, vì vậy không cần nhớ thay đổi mã sau này):

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

1
Điều này không cần thiết so với JSON.parse? JSON.parse ("true") và JSON.parse (true) đều đã trả về true, vì vậy sẽ vẫn hoạt động đúng sau khi trình duyệt triển khai boolean localstorage
bscan

3

Sử dụng store.js :

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

store.get('isUser')  //true

4
Nhưng có thực sự cần thiết phải bao gồm toàn bộ thư viện chỉ cho nhiệm vụ chuyển đổi chuỗi thành boolean đơn giản này không?
jayqui

1

Tôi không chắc liệu LocalStorage có thể lưu các giá trị boolean hay không nhưng tôi có thể nói với bạn rằng khi bạn làm điều alert("true" == true);đó sẽ không bao giờ đánh giá thành true vì bạn đang ngầm so sánh một chuỗi với một boolean. Đó là lý do tại sao phải đặt các giá trị boolean mà bạn sử dụng truethay thế "true".


1
Còn cảnh báo ("1" == 1) thì sao? Javascript là một thú dữ kỳ lạ (và không nhất quán).
tiêu

@spender: đó là vì toán hạng bên phải được chuyển thành một chuỗi để so sánh. "1" === 1thực sự sẽ trả về false.
Andy E,

@Kenny: rất tiếc facepalm , cảm ơn vì sự sửa chữa :-) Tôi đã nhầm lẫn vì cách booleans truyền thành chuỗi.
Andy E,

1

evalcũng có thể được sử dụng cẩn thận trong một số trường hợp.

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

Tránh evalvì nó có thể không an toàn. Thích hơn JSON.parse("true").
Fred

1

Những gì tôi thường làm chỉ là lưu giá trị trong LocalStore dưới dạng Boolean, sau đó truy xuất bằng phương pháp phân tích cú pháp, chỉ để đảm bảo cho tất cả các trình duyệt. Phương pháp của tôi dưới đây được tùy chỉnh cho logic kinh doanh của tôi. Đôi khi tôi có thể lưu trữ smth là "không" và vẫn cần đổi falselại

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;}
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.