Vì vậy, nhiều câu trả lời làm một nửa công việc. Có, !!X
có thể được đọc là "tính trung thực của X [được biểu thị dưới dạng boolean]". Nhưng !!
thực tế không phải là như vậy, rất quan trọng để tìm ra liệu một biến duy nhất là (hoặc thậm chí nếu nhiều biến là) trung thực hoặc giả. !!myVar === true
cũng giống như chỉ myVar
. So sánh !!X
với một boolean "thực" không thực sự hữu ích.
Những gì bạn đạt được !!
là khả năng kiểm tra tính trung thực của nhiều biến số với nhau theo cách lặp lại, được chuẩn hóa (và thân thiện với JSLint).
Đơn giản chỉ cần đúc :(
Đó là...
0 === false
là false
.
!!0 === false
là true
.
Ở trên không hữu ích lắm. if (!0)
cho bạn kết quả tương tự như if (!!0 === false)
. Tôi không thể nghĩ ra một trường hợp tốt để chuyển một biến thành boolean và sau đó so sánh với một boolean "thật".
Xem "== và! =" Từ hướng dẫn của JSLint (lưu ý: Crockford đang di chuyển trang web của anh ấy một chút; liên kết đó có thể bị chết tại một số điểm) để biết một chút về lý do:
Các toán tử == và! = Thực hiện ép buộc trước khi so sánh. Điều này là xấu vì nó khiến '\ t \ r \ n' == 0 là đúng. Điều này có thể che dấu lỗi loại. JSLint không thể xác định một cách đáng tin cậy nếu == đang được sử dụng một cách chính xác, vì vậy tốt nhất là không nên sử dụng == và! = Và luôn luôn sử dụng các toán tử === và! == đáng tin cậy hơn.
Nếu bạn chỉ quan tâm rằng một giá trị là trung thực hoặc giả, thì hãy sử dụng mẫu ngắn. Thay vì
(foo != 0)
chỉ nói
(foo)
và thay vì
(foo == 0)
Nói
(!foo)
Lưu ý rằng có một số trường hợp không trực quan trong đó boolean sẽ được chuyển thành một số ( true
được truyền tới 1
và false
tới 0
) khi so sánh boolean với một số. Trong trường hợp này, !!
có thể hữu ích về mặt tinh thần. Mặc dù, một lần nữa, đây là những trường hợp bạn đang so sánh một người không phải là boolean với một boolean khó đánh máy, đó là, imo, một sai lầm nghiêm trọng. if (-1)
vẫn là con đường để đi đến đây
╔═══════════════════════════════════════╦═══════════════════╦═══════════╗
║ Original ║ Equivalent ║ Result ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (-1 == true) console.log("spam") ║ if (-1 == 1) ║ undefined ║
║ if (-1 == false) console.log("spam") ║ if (-1 == 0) ║ undefined ║
║ Order doesn't matter... ║ ║ ║
║ if (true == -1) console.log("spam") ║ if (1 == -1) ║ undefined ║
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (!!-1 == true) console.log("spam") ║ if (true == true) ║ spam ║ better
╠═══════════════════════════════════════╬═══════════════════╬═══════════╣
║ if (-1) console.log("spam") ║ if (truthy) ║ spam ║ still best
╚═══════════════════════════════════════╩═══════════════════╩═══════════╝
Và mọi thứ thậm chí còn điên rồ hơn tùy thuộc vào động cơ của bạn. WScript, ví dụ, giành giải thưởng.
function test()
{
return (1 === 1);
}
WScript.echo(test());
Do một số jive Windows lịch sử , nó sẽ xuất -1 trong một hộp thông báo! Hãy thử nó trong một dấu nhắc cmd.exe và xem! Nhưng WScript.echo(-1 == test())
vẫn cung cấp cho bạn 0 hoặc WScript false
. Nhìn đi chỗ khác Thật gớm ghiếc.
So sánh sự thật :)
Nhưng nếu tôi có hai giá trị tôi cần kiểm tra truthi / falsi-ness bằng nhau thì sao?
Giả vờ chúng ta có myVar1 = 0;
và myVar2 = undefined;
.
myVar1 === myVar2
là 0 === undefined
và rõ ràng là sai.
!!myVar1 === !!myVar2
là !!0 === !!undefined
và là sự thật! Sự thật giống nhau! (Trong trường hợp này, cả hai "có một sự thật giả dối".)
Vì vậy, nơi duy nhất bạn thực sự cần sử dụng "biến boolean-cast" sẽ là nếu bạn gặp tình huống kiểm tra xem cả hai biến có cùng độ trung thực không? Đó là, sử dụng !!
nếu bạn cần để xem nếu hai vars là cả truthy hoặc cả hai falsy (hay không), có nghĩa là, các bằng (hoặc không) truthiness .
Tôi không thể nghĩ ra một trường hợp sử dụng tuyệt vời, không giả tạo cho việc đó. Có lẽ bạn đã "liên kết" các trường trong một hình thức?
if (!!customerInput.spouseName !== !!customerInput.spouseAge ) {
errorObjects.spouse = "Please either enter a valid name AND age "
+ "for your spouse or leave all spouse fields blank.";
}
Vì vậy, bây giờ nếu bạn có một sự thật cho cả hai hoặc giả cho cả tên vợ và tuổi, bạn có thể tiếp tục. Nếu không, bạn chỉ có một lĩnh vực có giá trị (hoặc một cuộc hôn nhân được sắp xếp rất sớm) và cần tạo thêm một lỗi trên errorObjects
bộ sưu tập của bạn .
EDIT ngày 24 tháng 10 năm 2017, ngày 6 tháng 2 năm 19:
Thư viện bên thứ 3 mong đợi các giá trị Boolean rõ ràng
Đây là một trường hợp thú vị ... !!
có thể hữu ích khi các lib của bên thứ 3 mong đợi các giá trị Boolean rõ ràng.
Chẳng hạn, Sai trong JSX (React) có một ý nghĩa đặc biệt không được kích hoạt trên sự giả dối đơn giản. Nếu bạn đã cố gắng trả lại một cái gì đó như sau trong JSX của mình, hãy chờ đợi một int trong messageCount
...
{messageCount && <div>You have messages!</div>}
... Bạn có thể ngạc nhiên khi thấy React kết xuất 0
khi bạn không có tin nhắn. Bạn phải trả về false một cách rõ ràng để JSX không hiển thị. Câu lệnh trên trả về 0
, mà JSX vui vẻ biểu hiện, như nó nên. Nó không thể nói rằng bạn không có Count: {messageCount && <div>Get your count to zero!</div>}
(hoặc một cái gì đó ít giả tạo hơn).
Một sửa chữa liên quan đến việc bangbang, mà cưỡng ép 0
vào !!0
, đó là false
:
{!!messageCount && <div>You have messages!</div>}
Các tài liệu của JSX đề nghị bạn rõ ràng hơn, viết mã tự nhận xét và sử dụng phép so sánh để buộc Boolean.
{messageCount > 0 && <div>You have messages!</div>}
Tôi cảm thấy thoải mái hơn khi tự mình xử lý sự giả dối -
{messageCount ? <div>You have messages!</div> : false}
Thỏa thuận tương tự trong Bản mô tả: Nếu bạn có hàm trả về giá trị boolean (hoặc bạn đang gán giá trị cho biến boolean), bạn [thường] không thể trả về / gán giá trị boolean-y; nó phải là một boolean được gõ mạnh. Điều này có nghĩa, iff myObject
được gõ mạnh , return !myObject;
hoạt động cho một hàm trả về boolean, nhưng return myObject;
không. Bạn phải return !!myObject
phù hợp với mong đợi của Typecript.
Ngoại lệ cho Bản in? Nếu myObject
là một any
, bạn quay lại Wild West của JavaScript và có thể trả lại mà không cần !!
, ngay cả khi kiểu trả về của bạn là boolean.
Hãy nhớ rằng đây là các quy ước về JSX & Typecript , không phải là các quy ước vốn có của JavaScript .
Nhưng nếu bạn thấy 0
s lạ trong JSX được kết xuất của bạn, hãy nghĩ rằng quản lý giả mạo lỏng lẻo.