Trong JavaScript, tại sao 1 0 0 bằng sai, nhưng khi được kiểm tra bởi 'if' thì nó không sai?


232

Sau đây cho thấy đó "0"là sai trong Javascript:

>>> "0" == false
true

>>> false == "0"
true

Vậy tại sao bản in sau đây "ha"?

>>> if ("0") console.log("ha")
ha

47
"0"là một chuỗi và vì nó không trống nên nó được đánh giá là đúng.
Máy bay kỹ thuật số

8
"0" === false [...] false

3
Kiểm tra sự thật bài viết của Angus Croll trong javascript. javascriptweblog.wordpress.com/2011/02/07/ từ
timrwood

8
'0'==falsenhưng '0' không phải là giá trị chim ưng (có Javascript có thể là lạ)
Linsey

5
@Linsey: Toàn bộ điều "giả dối" và "sự thật" chỉ có nghĩa là giải thích cách các giá trị được chuyển đổi thành booleans. Khi bạn so sánh hai giá trị với ==, chúng không bao giờ được chuyển đổi thành booleans, vì vậy nó không áp dụng. (Các quy tắc cho chuyển đổi dường như ủng hộ chuyển đổi thành số.)
millimoose

Câu trả lời:


251

Lý do là bởi vì khi bạn làm rõ ràng "0" == false, cả hai bên đang được chuyển đổi thành số và sau đó việc so sánh được thực hiện.

Khi bạn làm : if ("0") console.log("ha"), giá trị chuỗi đang được kiểm tra. Bất kỳ chuỗi không trống nào true, trong khi một chuỗi trống là false.

Bằng (==)

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 nghiêm ngặt. Nếu một 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 các số nếu có thể; khác nếu toán hạng là một chuỗi , toán hạng khác được chuyển đổi thành chuỗi nếu có thể. Nếu cả hai toán hạng là các đối tượng , thì JavaScript so sánh các tham chiếu bên trong bằng nhau khi các toán hạng tham chiếu đến cùng một đối tượng trong bộ nhớ.

(Từ Toán tử so sánh trong Mạng lưới nhà phát triển Mozilla)


348

Các bảng hiển thị vấn đề:

trung thực nếu tuyên bố

và == so sánh trung thực của tất cả các loại đối tượng trong javascript

Đạo đức của câu chuyện sử dụng === bình đẳng nghiêm ngặt hiển thị sự tỉnh táo

tín dụng tạo bảng: https://github.com/dorey/JavaScript-Equality-Table


2
Nó có ý nghĩa hơn nhiều với một thứ tự giá trị khác gist.github.com/kirilloid/8165660
kirilloid

3
Từ giờ trở đi, nếu ai đó nói rằng anh ta không bao giờ sử dụng các toán tử so sánh nghiêm ngặt, tôi sẽ đối mặt với anh ta với những cái bàn này và khiến anh ta khóc. Vẫn không chắc chắn nếu tôi nắm bắt được khái niệm NaNmặc dù. Ý tôi là, typeof NaN // numbernhưng NaN === NaN // false, hmm ...
Justus Romijn

4
Một người bạn của tôi đã tạo ra f.cl.ly/items/3b0q1n0o1m142P1P340P/javascript_equality.html - các biểu đồ tương tự như trên, nhưng dễ đọc hơn một chút.
Lucy Bain

@JustusRomijn có nhiều giá trị để biểu diễn NaN, vì vậy khi bạn so sánh 2 NaN, chúng có các giá trị khác nhau (tôi đoán vậy). Đọc trích dẫn đầu tiên ở đây .
cychoi

4
Những bảng này có một sai lầm. Cả ==cũng không ===điều hành cho [], {}, [[]], [0][1]giá trị này không đánh giá đúng sự thật. Ý tôi là [] == [][] === []cũng sai.
Herbertusz

38

Đó là theo thông số kỹ thuật.

12.5 Câu lệnh if 
.....

2. Nếu ToBoolean (GetValue (exprRef)) là đúng, thì 
a. Trả về kết quả đánh giá Tuyên bố đầu tiên.
3. Khác, 
....

ToBoolean, theo thông số kỹ thuật, là

Hoạt động trừu tượng ToBoolean chuyển đổi đối số của nó thành giá trị của kiểu Boolean theo Bảng 11:

Và bảng đó nói điều này về chuỗi:

nhập mô tả hình ảnh ở đây

Kết quả là sai nếu đối số là Chuỗi rỗng (độ dài của nó bằng 0); nếu không thì kết quả là đúng

Bây giờ, để giải thích lý do tại sao "0" == falsebạn nên đọc toán tử đẳng thức, trong đó nói rằng nó nhận giá trị của nó từ phép toán trừu tượng GetValue(lref)khớp với bên phải.

Mô tả phần có liên quan này là:

nếu IsPropertyReference (V), thì 
a. Nếu HasPrimitiveBase (V) là sai, thì hãy lấy phương thức bên trong [[Get]] của cơ sở, nếu không thì hãy lấy
là phương thức nội bộ [[Get]] đặc biệt được xác định bên dưới. 
b. Trả về kết quả của việc gọi phương thức get bằng cách sử dụng cơ sở làm giá trị này và truyền
GetReferencedName (V) cho đối số

Hay nói cách khác, một chuỗi có một cơ sở nguyên thủy, gọi lại phương thức get nội bộ và kết thúc là false.

Nếu bạn muốn đánh giá mọi thứ bằng cách sử dụng thao tác GetValue ==, nếu bạn muốn đánh giá bằng cách sử dụng ToBoolean, hãy sử dụng ===(còn được gọi là toán tử đẳng thức "nghiêm ngặt")


"a string has a primitive base, which calls back the internal get method and ends up looking false"Điều này có đúng với tất cả các chuỗi không?
aziz trừng phạt

@Interstellar_Coder Section 8.12.3: [[Get]] (P)mô tả cách thức hoạt động của nó. Điều này chỉ đúng với các trường hợp chuỗi là 0, vì nó thực hiện một loạt các cuộc gọi nội bộ khác cuối cùng dẫn đến kết quả GetOwnPropertylà "bất cứ thứ gì" là thuộc tính dữ liệu, sau đó trả về giá trị đó. Đây là lý do tại sao "0" là sai và "blah" là đúng. Xem một số video của Douglas Crockford trên nhà hát của nhà phát triển Yahoo, anh mô tả "tính trung thực" trong JavaScript ít phức tạp hơn tôi. Nếu bạn hiểu "sự thật" và "giả dối" nghĩa là gì bạn sẽ hiểu câu trả lời của Bobince ngay lập tức.
Ẩn danh

1
Tôi có thể tìm thông số kỹ thuật ở đâu?
dùng985366

12

Đó là PHP trong đó chuỗi "0"là sai (false-when-used-in-boolean-bối cảnh). Trong JavaScript, tất cả các chuỗi không trống đều là sự thật.

Bí quyết là ==đối với một boolean không đánh giá trong ngữ cảnh boolean, nó chuyển đổi thành số và trong trường hợp các chuỗi được thực hiện bằng cách phân tích cú pháp dưới dạng thập phân. Vì vậy, bạn nhận được Số 0thay vì boolean trung thực true.

Đây là một phần rất kém của thiết kế ngôn ngữ và đó là một trong những lý do chúng tôi cố gắng không sử dụng ==toán tử không may . Sử dụng ===thay thế.


7
// I usually do this:

x = "0" ;

if (!!+x) console.log('I am true');
else      console.log('I am false');

// Essentially converting string to integer and then boolean.

4

Các trích dẫn của bạn xung quanh 0làm cho nó thành một chuỗi, được đánh giá là đúng.

Xóa các trích dẫn và nó sẽ làm việc.

if (0) console.log("ha") 

đúng, không phải về cách "làm cho nó hoạt động" mà là câu hỏi giống như "tại sao nó lại hành xử theo cách đó?"
phân cực

2

Tất cả là do thông số kỹ thuật của ECMA ... "0" == falsevì các quy tắc được chỉ định ở đây http://ecma262-5.com/ELS5 hài.htmlm#Section_11.9.3 ... Và if ('0')đánh giá là đúng vì các quy tắc được chỉ định ở đây http: / /ecma262-5.com/ELS5 hài.htmlm#Section_12.5


Tôi không biết ai đó đã chuyển thông số kỹ thuật đến một trang web ... thật tuyệt vời! Không có nhiều tệp PDF cho tôi.
Ẩn danh

1

Biểu thức "nếu" kiểm tra tính trung thực, trong khi các phép thử bằng hai lần cho tính tương đương độc lập với loại. Một chuỗi luôn luôn đúng, như những người khác ở đây đã chỉ ra. Nếu hai nhân bằng nhau đang kiểm tra cả hai toán hạng của nó về tính trung thực và sau đó so sánh kết quả, thì bạn sẽ nhận được kết quả mà bạn đang giả định bằng trực giác, tức là ("0" == true) === true. Như Doug Crockford đã nói trong JavaScript tuyệt vời của mình : Các bộ phận tốt , "các quy tắc [== ép buộc các loại toán hạng của nó] rất phức tạp và không đáng chú ý .... Việc thiếu tính chuyển đổi là đáng báo động." Nó đủ để nói rằng một trong các toán hạng được ép kiểu để khớp với cái kia và "0" cuối cùng được hiểu là một số 0,


1

== Toán tử đẳng thức đánh giá các đối số sau khi chuyển đổi chúng thành số. Vì vậy, chuỗi zero "0" được chuyển đổi thành kiểu dữ liệu Số và boolean false được chuyển đổi thành Số 0. Vì vậy,

"0" == false // true

Áp dụng tương tự cho `

false == "0" //true

=== Kiểm tra đẳng thức nghiêm ngặt đánh giá các đối số với kiểu dữ liệu gốc

"0" === false // false, because "0" is a string and false is boolean

Áp dụng tương tự cho

false === "0" // false

Trong

if("0") console.log("ha");

Chuỗi "0" không so sánh với bất kỳ đối số nào và chuỗi là giá trị thực cho đến khi hoặc trừ khi nó được so sánh với bất kỳ đối số nào. Nó chính xác như

if(true) console.log("ha");

Nhưng

if (0) console.log("ha"); // empty console line, because 0 is false

`


1

Điều này là do JavaScript sử dụng kiểu ép buộc trong bối cảnh Boolean và mã của bạn

if ("0") 

sẽ bị ép buộc thành đúng trong bối cảnh boolean.

Có các giá trị trung thực khác trong Javascript sẽ được ép buộc thành đúng trong bối cảnh boolean và do đó thực thi khối if là: -

if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)

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.