Nên sử dụng toán tử bằng nào (== vs ===) trong so sánh JavaScript?


5665

Tôi đang sử dụng JSLint để duyệt qua JavaScript và nó sẽ trả lại nhiều đề xuất để thay thế ==(hai dấu bằng) bằng ===(ba dấu bằng) khi thực hiện những việc như so sánh idSele_UNVEHtype.value.length == 0bên trong ifcâu lệnh.

Có một lợi ích hiệu suất để thay thế ==bằng ===?

Bất kỳ cải tiến hiệu suất sẽ được hoan nghênh khi có nhiều toán tử so sánh tồn tại.

Nếu không có chuyển đổi loại nào diễn ra, liệu có đạt được hiệu suất hơn ==không?


134
Người mà nó có thể quan tâm đến cùng một chủ đề === vs ==, nhưng trong PHP, có thể đọc tại đây: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/iêu
Marco Demaio

257
Chỉ trong trường hợp bất cứ ai đã tự hỏi vào năm 2012: ===cách nhanh hơn ==. jsperf.com/comparison-of-comparisons
Ry-

25
@minitech nên như vậy vì nó không thực hiện chuyển đổi loại
Umur Kontacı

19
@minitech, tôi nghi ngờ bất cứ ai sẽ làm cho ứng dụng của họ nhanh hơn đáng kể bằng cách sử dụng ===hơn ==. Trên thực tế, điểm chuẩn không cho thấy sự khác biệt lớn giữa cả hai trên các trình duyệt hiện đại. Cá nhân, tôi thường sử dụng ==ở mọi nơi trừ khi tôi thực sự cần sự bình đẳng nghiêm ngặt.
nguyệt quế

5
Đây là một phần trong bài nói chuyện về các bộ phận tốt của Crockford, nơi anh ấy thảo luận về các nhà khai thác =====nhà điều hành: youtube.com/, Nếu không chơi, đó là lúc 15:20
davidhiggins

Câu trả lời:


6485

Toán tử đẳng thức nghiêm ngặt ( ===) hành xử giống hệt với toán tử đẳng thức trừu tượng ( ==) ngoại trừ không có chuyển đổi loại nào được thực hiện và các loại phải giống nhau để được coi là bằng nhau.

Tham khảo: Hướng dẫn Javascript: Toán tử so sánh

Các ==nhà điều hành sẽ so sánh bình đẳng sau khi làm bất kỳ chuyển đổi loại cần thiết . Các ===nhà điều hành sẽ không làm việc chuyển đổi, vì vậy nếu hai giá trị không phải là cùng loại ===sẽ chỉ đơn giản là trở lại false. Cả hai đều nhanh chóng như nhau.

Để trích dẫn JavaScript tuyệt vời của Douglas Crockford : Các bộ phận tốt ,

JavaScript có hai bộ toán tử đẳng thức: ===!==, cặp song sinh xấu xa của chúng ==!=. Những người tốt làm việc theo cách bạn mong đợi. Nếu hai toán hạng cùng loại và có cùng giá trị, thì ===tạo true!==sản xuất false. Cặp song sinh độc ác làm điều đúng khi các toán hạng cùng loại, nhưng nếu chúng thuộc các loại khác nhau, chúng cố gắng ép buộc các giá trị. các quy tắc mà họ làm điều đó là phức tạp và không đáng nhớ. Đây là một số trường hợp thú vị:

'' == '0'           // false
0 == ''             // true
0 == '0'            // true

false == 'false'    // false
false == '0'        // true

false == undefined  // false
false == null       // false
null == undefined   // true

' \t\r\n ' == 0     // true

Bảng so sánh bình đẳng

Sự thiếu minh bạch là đáng báo động. Lời khuyên của tôi là đừng bao giờ sử dụng cặp song sinh độc ác. Thay vào đó, luôn luôn sử dụng ===!==. Tất cả các so sánh chỉ hiển thị sản xuất falsevới các ===nhà điều hành.


Cập nhật:

Một điểm tốt được nuôi dưỡng bởi @Casebash trong các ý kiến và trong @Phillipe Laybaert của câu trả lời đối tượng liên quan. Đối với các đối tượng =====hành động nhất quán với nhau (trừ trường hợp đặc biệt).

var a = [1,2,3];
var b = [1,2,3];

var c = { x: 1, y: 2 };
var d = { x: 1, y: 2 };

var e = "text";
var f = "te" + "xt";

a == b            // false
a === b           // false

c == d            // false
c === d           // false

e == f            // true
e === f           // true

Trường hợp đặc biệt là khi bạn so sánh một nguyên thủy với một đối tượng đánh giá cùng một nguyên thủy, do nó toStringhoặc valueOfphương thức của nó . Ví dụ, hãy xem xét việc so sánh một chuỗi nguyên thủy với một đối tượng chuỗi được tạo bằng cách sử dụng hàm Stringtạo.

"abc" == new String("abc")    // true
"abc" === new String("abc")   // false

Ở đây ==toán tử đang kiểm tra các giá trị của hai đối tượng và trả về true, nhưng người ===ta thấy rằng chúng không cùng loại và trả về false. Điều nào là đúng? Điều đó thực sự phụ thuộc vào những gì bạn đang cố gắng so sánh. Lời khuyên của tôi là bỏ qua câu hỏi hoàn toàn và chỉ không sử dụng hàm Stringtạo để tạo các đối tượng chuỗi từ chuỗi ký tự.

Tham khảo
http: //www.ecma-i Intl.org/ecma-262/5.1/#sec-11.9.3


236
=== không nhanh hơn nếu các loại giống nhau. Nếu các loại không giống nhau, === sẽ nhanh hơn vì nó sẽ không thực hiện chuyển đổi.
Xuất hóa đơn cho thằn lằn

520
=== sẽ không bao giờ chậm hơn ==. Cả hai đều thực hiện kiểm tra loại, vì vậy === không làm gì thêm so với ==, nhưng kiểm tra loại có thể cho phép === thoát sớm hơn khi các loại không giống nhau.
Bill the Lizard

246
Thay thế tất cả == /! = Bằng === /! == làm tăng kích thước của tệp js, sẽ mất nhiều thời gian hơn để tải. :)
Marco Demaio

92
"... Các quy tắc mà họ thực hiện rất phức tạp và không đáng nhớ ..." Bây giờ những tuyên bố như vậy khiến bạn cảm thấy an toàn khi lập trình ...
Johan

47
Từ Crockford: "Việc thiếu tính siêu việt là đáng báo động." Nếu bạn phát triển phần mềm và không thấy thiếu tính chuyển đổi trong cảnh báo của toán tử so sánh hoặc nếu so sánh tốc độ giữa == và === hoặc kích thước tệp / thời gian tải thì bạn nên ưu tiên cho tính xác định bắc cầu của hành vi của toán tử so sánh, bạn có thể cần phải quay lại và bắt đầu lại.
jinglểula

1144

Sử dụng ==toán tử ( Equality )

true == 1; //true, because 'true' is converted to 1 and then compared
"2" == 2;  //true, because "2" is converted to 2 and then compared

Sử dụng ===toán tử ( Danh tính )

true === 1; //false
"2" === 2;  //false

Điều này là do toán tử đẳng thức ==thực hiện kiểu ép buộc , nghĩa là trình thông dịch ngầm cố gắng chuyển đổi các giá trị trước khi so sánh.

Mặt khác, toán tử nhận dạng ===không thực hiện cưỡng chế kiểu và do đó không chuyển đổi các giá trị khi so sánh, và do đó nhanh hơn (như theo bài kiểm tra điểm chuẩn JS này ) khi nó bỏ qua một bước.


9
@Software Monkey: không dành cho các loại giá trị (số, boolean, ...)
Philippe Leybaert

34
Vì không ai đề cập đến Bảng bình đẳng Javascript, nên đây là: dorey.github.io/JavaScript-Equality-Table
blaze

6
Trong tuyên bố đầu tiên, bạn có chắc chắn rằng 'true' được chuyển đổi thành 1 chứ không phải 1 được chuyển đổi thành true?
Shadi Namrouti

2
Các thuật ngữ "bình đẳng" và "bản sắc" bắt nguồn từ đâu? Các tiêu chuẩn không sử dụng các điều khoản. Nó gọi là =="bình đẳng trừu tượng" và nó gọi là ==="bình đẳng nghiêm ngặt". Cấp cho gọi ==bất kỳ loại "bình đẳng" là IMHO khủng khiếp, vì nó không phải là bắc cầu, nhưng tại sao lại ngụy biện? Tôi có nhiều vấn đề hơn với "danh tính" mặc dù; Tôi nghĩ rằng thuật ngữ này là khá sai lệch, mặc dù nó "hoạt động." Nhưng nghiêm túc, ai đặt ra thuật ngữ "danh tính"? Tôi tìm kiếm tiêu chuẩn và không thể tìm thấy nó.
Ray Toal

1
"Danh tính" là rất nhiều từ sai. So sánh sắc trong tất cả các ngôn ngữ tôi đã sử dụng phương tiện một trong cùng một đối tượng , tức là hai biến tài liệu tham khảo đang trỏ không chỉ cho các tổ chức tương đương, nhưng các tổ chức tương tự.
Inigo

724

Một đại diện hình ảnh thú vị của so sánh bình đẳng giữa =====.

Nguồn: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

Khi sử dụng ===để kiểm tra tính bằng JavaScript, mọi thứ đều như vậy. Không có gì được chuyển đổi trước khi được đánh giá.

Đánh giá bình đẳng === trong JS


var1 == var2

Khi sử dụng ==để kiểm tra tính bằng JavaScript, một số chuyển đổi thú vị sẽ diễn ra.

Đánh giá bằng == trong JS

Đạo đức của câu chuyện:

Sử dụng ===trừ khi bạn hoàn toàn hiểu các chuyển đổi diễn ra với ==.


3
@mfeine là bạn có nghĩa là === hoặc! == thay vì == hoặc! =. Đừng muốn nhầm lẫn các lập trình viên mới;)
katalin_2003

2
từ kinh nghiệm của tôi bằng cách sử dụng ba bằng có thể gây ra vấn đề và nên tránh trừ khi hiểu đầy đủ. hai bằng nhau tạo ra kết quả tốt hơn nhiều vì 99% thời gian tôi thực sự không muốn các loại bằng nhau.
vsync

13
@vsync: Nếu bạn thực sự không muốn các loại bằng nhau , bạn nên sử dụng ba bằng !
SNag

7
Một ngoại lệ: bạn có thể sử dụng một cách an toàn x == nullđể kiểm tra xem xnullhay undefined.
Andy

1
@ user648026: Câu hỏi đặt ra là về bình đẳng so với ==vs ===. Các trường hợp trên và dưới là không bằng nhau, và sẽ trở lại falsevới cả hai ==và các ===nhà khai thác. Ngoài ra, từ khóa true, false, undefined, null, Infinitytồn tại trong JS chỉ trong một trường hợp, và không thể được sử dụng trong các trường hợp trên hoặc hỗn hợp.
SNag

609

Trong các câu trả lời ở đây, tôi đã không đọc bất cứ điều gì về ý nghĩa tương đương . Một số người sẽ nói điều đó ===có nghĩa là bằng nhau và cùng loại , nhưng điều đó không thực sự đúng. Nó thực sự có nghĩa là cả hai toán hạng tham chiếu cùng một đối tượng hoặc trong trường hợp các loại giá trị, có cùng giá trị .

Vì vậy, hãy lấy mã sau đây:

var a = [1,2,3];
var b = [1,2,3];
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Giống nhau ở đây:

var a = { x: 1, y: 2 };
var b = { x: 1, y: 2 };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Hoặc thậm chí:

var a = { };
var b = { };
var c = a;

var ab_eq = (a === b); // false (even though a and b are the same type)
var ac_eq = (a === c); // true

Hành vi này không phải lúc nào cũng rõ ràng. Có nhiều điều cho câu chuyện hơn là bình đẳng và cùng loại.

Quy tắc là:

Đối với loại giá trị (số):
a === b trả về true nếuabcó cùng giá trị và cùng loại

Đối với kiểu tham chiếu:
a === b trả về true nếuabtham chiếu chính xác cùng một đối tượng

Đối với chuỗi:
a === b trả về true nếuablà cả hai chuỗi và chứa cùng một ký tự


Chuỗi: trường hợp đặc biệt ...

Chuỗi không phải là loại giá trị, nhưng trong Javascript, chúng hoạt động giống như loại giá trị, vì vậy chúng sẽ "bằng nhau" khi các ký tự trong chuỗi giống nhau và khi chúng có cùng độ dài (như được giải thích trong quy tắc thứ ba)

Bây giờ nó trở nên thú vị:

var a = "12" + "3";
var b = "123";

alert(a === b); // returns true, because strings behave like value types

Nhưng làm thế nào về điều này?:

var a = new String("123");
var b = "123";

alert(a === b); // returns false !! (but they are equal and of the same type)

Tôi nghĩ chuỗi hành xử như các loại giá trị? Chà, nó phụ thuộc vào người bạn hỏi ... Trong trường hợp này a và b không cùng loại. alà loại Object, trong khi blà loại string. Chỉ cần nhớ rằng việc tạo một đối tượng chuỗi bằng cách sử dụng hàm Stringtạo sẽ tạo ra một cái gì đó có kiểu Objecthoạt động như một chuỗi hầu hết thời gian .


6
activa: Tôi sẽ làm rõ, rằng các chuỗi chỉ bằng nhau khi chúng là bằng chữ. Chuỗi mới ("abc") === "abc" là sai (theo nghiên cứu của tôi).
Lawrence Dol

3
new Number() == "0". Cũng trong Firefox:(function(){}) == "function () {\n}"
Thomas Eding

3
Cảm ơn bạn đã giải thích lý do tại sao new String("123") !== "123". Chúng là những loại khác nhau. Đơn giản, nhưng khó hiểu.
styfle

21
Stringcác đối tượng hành xử như các chuỗi như bất kỳ đối tượng khác . new Stringkhông bao giờ nên được sử dụng, vì điều đó không tạo ra chuỗi thực. Một chuỗi thực và có thể được tạo bằng chuỗi ký tự hoặc gọi Stringlà hàm mà không có new , ví dụ:String(0); //"0", Real string, not an object
Esailija

6
Nhưng trong các trường hợp bạn nêu chi tiết, toán tử "==" hoạt động giống hệt nhau.
Yaron Levi

270

Hãy để tôi thêm lời khuyên này:

Nếu nghi ngờ, hãy đọc thông số kỹ thuật !

ECMA-262 là đặc điểm kỹ thuật cho ngôn ngữ kịch bản mà JavaScript là phương ngữ. Tất nhiên trong thực tế, vấn đề quan trọng hơn là các trình duyệt quan trọng nhất hoạt động như thế nào so với định nghĩa bí truyền về cách xử lý một cái gì đó. Nhưng thật hữu ích để hiểu tại sao Chuỗi mới ("a")! == "a" .

Xin vui lòng để tôi giải thích làm thế nào để đọc các đặc điểm kỹ thuật để làm rõ câu hỏi này. Tôi thấy rằng trong chủ đề rất cũ này không ai có câu trả lời cho hiệu ứng rất lạ. Vì vậy, nếu bạn có thể đọc một đặc điểm kỹ thuật, điều này sẽ giúp bạn rất nhiều trong nghề nghiệp của bạn. Đó là một kỹ năng có được. Vì vậy, hãy tiếp tục.

Tìm kiếm tệp PDF cho === đưa tôi đến trang 56 của thông số kỹ thuật: 11.9.4. Toán tử tương đương nghiêm ngặt (===) và sau khi lội qua các đặc trưng tôi tìm thấy:

11.9.6 Thuật toán so sánh đẳng thức nghiêm ngặt So
sánh x === y, trong đó x và y là các giá trị, tạo ra đúng hoặc sai . Việc so sánh như vậy được thực hiện như sau:
  1. Nếu Loại (x) khác với Loại (y), hãy trả về false .
  2. Nếu Loại (x) không xác định, trả về true .
  3. Nếu Loại (x) là Null, trả về true .
  4. Nếu Loại (x) không phải là Số, hãy chuyển đến bước 11.
  5. Nếu x là NaN , hãy trả về false .
  6. Nếu y là NaN , trả về false .
  7. Nếu x là cùng một giá trị số với y, trả về true .
  8. Nếu x là +0 và y là −0, trả về true .
  9. Nếu x là −0 và y là +0, trả về true .
  10. Trả lại sai .
  11. Nếu Loại (x) là Chuỗi, thì trả về true nếu x và y chính xác là cùng một chuỗi ký tự (cùng độ dài và cùng ký tự ở các vị trí tương ứng); nếu không, trả lại sai .
  12. Nếu Loại (x) là Boolean, trả về true nếu x và y đều đúng hoặc cả sai ; nếu không, trả lại sai .
  13. Trả lại đúngnếu x và y đề cập đến cùng một đối tượng hoặc nếu chúng tham chiếu đến các đối tượng được nối với nhau (xem 13.1.2). Nếu không, trả lại sai .

Thú vị là bước 11. Có, chuỗi được coi là loại giá trị. Nhưng điều này không giải thích tại sao Chuỗi mới ("a")! == "a" . Chúng ta có một trình duyệt không phù hợp với ECMA-262 không?

Không quá nhanh!

Hãy kiểm tra các loại toán hạng. Hãy tự mình thử bằng cách gói chúng trong typeof () . Tôi thấy rằng Chuỗi mới ("a") là một đối tượng và bước 1 được sử dụng: trả về false nếu các loại khác nhau.

Nếu bạn tự hỏi tại sao Chuỗi mới ("a") không trả về một chuỗi, làm thế nào về một số bài tập đọc một đặc tả? Chúc vui vẻ!


Aidiakapi đã viết điều này trong một bình luận dưới đây:

Từ đặc điểm kỹ thuật

11.2.2 Toán tử mới :

Nếu Loại (hàm tạo) không phải là Đối tượng, hãy ném ngoại lệ TypeError.

Nói cách khác, nếu String không thuộc loại Object thì nó không thể được sử dụng với toán tử mới.

mới luôn trả về một Object, ngay cả đối với các hàm tạo String . Và than ôi! Các ngữ nghĩa giá trị cho các chuỗi (xem bước 11) bị mất.

Và điều này cuối cùng có nghĩa là: Chuỗi mới ("a")! == "a" .


Kết quả của Loại (x) được ngụ ý giống như loại?
Dfr

@nalply Tôi không hiểu chính xác sự lo lắng về hành vi new String('x'), bởi vì tôi chưa bao giờ thấy bất kỳ mã nào trong tự nhiên sử dụng các đối tượng trình bao bọc nguyên thủy và tôi không nghĩ có nhiều lý do chính đáng, đặc biệt là những ngày này. Bạn đã bao giờ gặp phải mã đó chưa?
Andy

@Andy vấn đề là độc hại hoặc chỉ là mã của bên thứ ba cẩu thả, sau đó bạn không thể cho rằng không ai sử dụng new String().
nalply

Nếu nó cẩu thả, === là cách bạn sẽ tìm ra. Nếu nó độc hại, tôi nghĩ new String()có lẽ là ít lo lắng nhất của bạn. Tôi hiểu mối quan tâm trong lý thuyết, nhưng một lần nữa, bạn có bất kỳ ví dụ thực tế nào không? Đối với tôi nó giống như nỗi lo lắng cũ mà ai đó có thể đặt undefinedsang một giá trị khác.
Andy

Tôi không biết bạn đã lấy cái này ở đâu, nhưng thuật toán so sánh của bạn bị sai ở bước 2. Phần "7.2.15 So sánh bình đẳng nghiêm ngặt" trước tiên kiểm tra xem các loại có giống nhau không, nếu có cho dù chúng là Số. Nếu không, thì phần "7.2.12 SameValueNonNumber (x, y)" được sử dụng.
Rusty Core

101

Trong PHP và JavaScript, nó là một toán tử bình đẳng nghiêm ngặt. Có nghĩa là, nó sẽ so sánh cả loại và giá trị.


10
@David: đúng. Đó là lý do tại sao câu trả lời này không chính xác (hoặc thậm chí sai)
Philippe Leybaert

7
@David var a = {}, b = {}; a == btrả về sai.
nyuszika7h

6
Có: Hai đối tượng khác nhau có cùng loại và giá trị so sánh sai, nghĩa là câu trả lời này chỉ sai. Tại sao nó có 50 upvote?
alexis

4
Tôi nhận ra điều này đã cũ, nhưng để làm rõ lý do tại sao câu trả lời này vẫn "đúng" là vì trong ví dụ var a = {}, b = {};Trong khi cả hai abthực sự là cả một đối tượng, nhưng chúng không cùng giá trị, nói về mặt kỹ thuật. Họ là những trường hợp khác nhau . Lưu ý rằng so sánh các trường hợp hành xử khác nhau so với so sánh nguyên thủy. Mà có lẽ thêm vào sự nhầm lẫn này. Bạn sẽ thấy hành vi so sánh tương tự nếu bạn sử dụng phiên bản thể hiện của các kiểu dữ liệu nguyên thủy. Ví dụ new String('asdf')hay new Number(5). Ví dụ: new Number(5) == new Number(5)là sai, mặc dù chúng giữ cùng một giá trị.
Norman Breau

1
Tất cả chúng ta đều quên rằng một tham chiếu đến một đối tượng thực sự là Loại giá trị, vì nó là một con trỏ tới một khe nhớ. So sánh đối tượng không so sánh "giá trị của đối tượng" nhưng liệu cả hai con trỏ có giống nhau hay không có nghĩa là chúng tham chiếu cùng một khe nhớ. Đó là một sự khác biệt rất tinh tế khi so sánh các Loại, vì toán tử "===" thực sự cần phải nói "nếu loại, giá trị và tham chiếu đến đối tượng trong bộ nhớ là như nhau".
Stokely

101

Tôi đã thử nghiệm điều này trong Firefox với Fireorms bằng mã như thế này:

console.time("testEquality");
var n = 0;
while(true) {
    n++;
    if(n==100000) 
        break;
}
console.timeEnd("testEquality");

console.time("testTypeEquality");
var n = 0;
while(true) {
    n++;
    if(n===100000) 
        break;
}
console.timeEnd("testTypeEquality");

Kết quả của tôi (được kiểm tra năm lần mỗi lần và tính trung bình):

==: 115.2
===: 114.4

Vì vậy, tôi muốn nói rằng sự khác biệt rất nhỏ (đây là hơn 100000 lần lặp, hãy nhớ) là không đáng kể. Hiệu suất không phải là một lý do để làm ===. Nhập an toàn (tốt, an toàn như bạn sẽ có trong JavaScript) và chất lượng mã là.


3
Hơn cả sự an toàn mà bạn muốn sự đúng đắn hợp lý - đôi khi bạn muốn mọi thứ trở nên trung thực khi ==không đồng ý.
rpjohnst

4
Bây giờ, làm thế nào để so sánh khi có một kiểu kết hợp thực tế cho ==toán tử? Hãy nhớ rằng, đó là khi có hiệu suất tăng.
Hubert OG

2
Sự khác biệt lớn khi được kiểm tra đúng cách vì các lý do đã nói ở trên nhanh hơn để chỉ kiểm tra bất bình đẳng loại. jsfiddle.net/4jhuxkb2
Doug Morrow

Bạn đo hiệu suất của một cái gì đó như thế này trong các hoạt động / giây, không phải là một thử nghiệm trong một trình duyệt duy nhất (một thị phần chiếm khoảng 5% thị phần) bằng cách sử dụng console.time () trong khi sử dụng thử nghiệm không thực hiện cưỡng chế kiểu (toàn bộ lý do nó chậm hơn) vào tài khoản. Đây là một thử nghiệm hoàn toàn vô nghĩa. Bạn là chính xác rằng hiệu suất không phải là lý do để sử dụng ===trên ==nhưng bạn là sai rằng hiệu suất của họ là về cơ bản bình đẳng và rằng bạn sẽ nghĩ thử nghiệm này chứng minh rằng, và nhiều người khác đồng ý, là hoàn toàn vô lý với tôi.
Stephen M Irving

97

Trong JavaScript, nó có nghĩa là cùng một giá trị và loại.

Ví dụ,

4 == "4" // will return true

nhưng

4 === "4" // will return false 

87

Các === điều hành được gọi là toán tử so sánh nghiêm ngặt, nó không khác với == nhà điều hành.

Cho phép lấy 2 bình a và b.

Để "a == b" đánh giá đúng a và b cần phải có cùng giá trị .

Trong trường hợp "a === b" a và b phải có cùng giá trị và cũng là cùng loại để đánh giá là đúng.

Lấy ví dụ sau

var a = 1;
var b = "1";

if (a == b) //evaluates to true as a and b are both 1
{
    alert("a == b");
}

if (a === b) //evaluates to false as a is not the same type as b
{
    alert("a === b");
}

Tóm lại ; sử dụng toán tử == có thể đánh giá là đúng trong các tình huống mà bạn không muốn nó sử dụng toán tử === sẽ an toàn hơn.

Trong kịch bản sử dụng 90%, sẽ không có vấn đề gì khi bạn sử dụng, nhưng thật hữu ích khi biết sự khác biệt khi bạn gặp một số hành vi không mong muốn một ngày nào đó.


82

Tại sao lại ==khó đoán như vậy?

Bạn nhận được gì khi so sánh một chuỗi rỗng ""với số 0 0?

true

Đúng, đó là đúng theo ==một chuỗi trống và số 0 là cùng một lúc.

Và nó không kết thúc ở đó, đây là một cái khác:

'0' == false // true

Mọi thứ trở nên thực sự kỳ lạ với mảng.

[1] == true // true
[] == false // true
[[]] == false // true
[0] == false // true

Sau đó, weirder với chuỗi

[1,2,3] == '1,2,3' // true - REALLY?!
'\r\n\t' == 0 // true - Come on!

Nó trở nên tồi tệ hơn:

Khi nào bằng nhau không bằng?

let A = ''  // empty string
let B = 0   // zero
let C = '0' // zero string

A == B // true - ok... 
B == C // true - so far so good...
A == C // **FALSE** - Plot twist!

Hãy để tôi nói rằng một lần nữa:

(A == B) && (B == C) // true
(A == C) // **FALSE**

Và đây chỉ là những thứ điên rồ mà bạn có được với người nguyên thủy.

Đó là một mức độ hoàn toàn mới khi bạn sử dụng ==với các đối tượng.

Tại thời điểm này có lẽ bạn đang tự hỏi ...

Lý do tại sao điều này xảy ra?

Vâng, bởi vì không giống như "ba bằng" ( ===) chỉ kiểm tra xem hai giá trị có giống nhau không.

==làm một loạt các công cụ khác .

Nó có xử lý đặc biệt cho các hàm, xử lý đặc biệt cho null, không xác định, chuỗi, bạn đặt tên cho nó.

Nó khá là lập dị.

Trong thực tế, nếu bạn đã cố gắng viết một hàm làm những gì ==nó sẽ trông giống như thế này:

function isEqual(x, y) { // if `==` were a function
    if(typeof y === typeof x) return y === x;
    // treat null and undefined the same
    var xIsNothing = (y === undefined) || (y === null);
    var yIsNothing = (x === undefined) || (x === null);

    if(xIsNothing || yIsNothing) return (xIsNothing && yIsNothing);

    if(typeof y === "function" || typeof x === "function") {
        // if either value is a string 
        // convert the function into a string and compare
        if(typeof x === "string") {
            return x === y.toString();
        } else if(typeof y === "string") {
            return x.toString() === y;
        } 
        return false;
    }

    if(typeof x === "object") x = toPrimitive(x);
    if(typeof y === "object") y = toPrimitive(y);
    if(typeof y === typeof x) return y === x;

    // convert x and y into numbers if they are not already use the "+" trick
    if(typeof x !== "number") x = +x;
    if(typeof y !== "number") y = +y;
    // actually the real `==` is even more complicated than this, especially in ES6
    return x === y;
}

function toPrimitive(obj) {
    var value = obj.valueOf();
    if(obj !== value) return value;
    return obj.toString();
}

Vì vậy, điều này có nghĩa là gì?

Nó có nghĩa ==là phức tạp.

Bởi vì nó phức tạp, thật khó để biết điều gì sẽ xảy ra khi bạn sử dụng nó.

Điều đó có nghĩa là bạn có thể kết thúc với lỗi.

Vì vậy, đạo đức của câu chuyện là ...

Làm cho cuộc sống của bạn bớt phức tạp.

Sử dụng ===thay vì ==.

Kết thúc.


Bạn looseEqualsai rồi Function == Function.toString()là đúng, nhưng looseEqual(Function, Function.toString())là sai Không chắc chắn tại sao bạn lọc ra các chức năng lúc đầu.
Oriol

@Oriol bạn đã đúng, tôi đã cập nhật mã để giải thích cho điều đó, FYI dựa trên các thử nghiệm của tôi, nó không đủ để loại bỏ bộ lọc cho "các chức năng", thay vào đó "các chức năng" phải được xử lý hoàn toàn khác nhau.
Luis Perez

Hãy lưu ý rằng thông số kỹ thuật không xử lý các chức năng khác nhau, chúng chỉ là các đối tượng. Vấn đề dường như là bạn dựa vào typeof x === "object"để kiểm tra xem đó có phải là một đối tượng không, nhưng `typeof chỉ hoạt động đối với các nguyên hàm không null. Bạn có thể quan tâm đến danh sách các cách thích hợp
Oriol

Tôi đã thử xử lý các chức năng và đối tượng như nhau nhưng thấy kết quả của anh ta không chính xác. Ví dụ: nếu các hàm được xử lý như các đối tượng thì so sánh một hàm với một đối tượng thực hiện hàm valueOf () hoặc toString () phù hợp với hàm sẽ vượt qua nhưng thực tế thì không. Ví dụ: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- kiểm tra Fiddle JS này chạy tất cả các bài kiểm tra: jsfiddle.net/luisperezphd/7k6gcn6g (có 1.225 hoán vị kiểm tra)
Luis Perez

1
Bạn nói đúng, những quan sát tuyệt vời, điều này nhấn mạnh điểm chính ==làm rất nhiều điều khiến cho việc dự đoán kết quả rất khó khăn trong khi ===lại đơn giản và dễ đoán hơn nhiều, đó là một trong những lý do chính ===là sự lựa chọn được đề xuất. (Tôi sẽ thêm một ghi chú vào câu trả lời đề cập đến quan điểm của bạn)
Luis Perez

81

===kiểm tra cùng một bên là bằng nhau về loại cũng như giá trị .


Thí dụ:

'1' === 1 // will return "false" because `string` is not a `number`

Ví dụ phổ biến:

0 == ''  // will be "true", but it's very common to want this check to be "false"

Một ví dụ phổ biến khác:

null == undefined // returns "true", but in most cases a distinction is necessary

Nhiều lần một untyped kiểm tra sẽ được thuận tiện vì bạn không quan tâm nếu giá trị là một trong hai undefined, null, 0 hoặc""


7
Ngoài ra,'string' !== 'number'
Homer

71

Sơ đồ luồng thực thi Javascript cho sự bình đẳng / So sánh nghiêm ngặt '==='

Javascript bình đẳng nghiêm ngặt

Sơ đồ luồng thực thi Javascript cho bình đẳng / so sánh không nghiêm ngặt '=='

Javascript không bình đẳng


Tôi không hiểu tại sao stringmũi tên lại chỉ vào hộp lớn màu xám, điều đó có nghĩa là bộ ngắt đang truyền chuỗi thành một số?
vsync

@vsync Nó trỏ đến tùy chọn chuỗi trong hộp màu xám tức là chuỗi -> # || NaN. Javascript không phải là một ngôn ngữ kịch bản loại, tức là về cơ bản nó có thể có bất kỳ loại biến nào. Vì vậy, nó được chỉ vào hộp màu xám đó.
Gấu trúc Samar

Tôi chỉ đơn giản hỏi nếu nó là dành cho mục đích truyền vì stringnó được so sánh với một loại number, vì vậy, bộ ngắt xem xét chuỗi nào nên được so sánh và đúc chuỗi phù hợp?
vsync

1
Hộp lớn màu xám là những gì ToNumbersẽ trả về khi được cung cấp các loại khác nhau, vì vậy nếu nó được cung cấp một chuỗi, nó sẽ chỉ chọn tùy chọn cuối cùng (và chuyển đổi nó thành một số). chỉ ==sử dụng ToNumbertrong các trường hợp string == numbertrở boolean == anythinglên (và chỉ trên string/ boolean). Điều này có nghĩa là ==sẽ không bao giờ chuyển đổi undefinedhoặc nullmặc dù chúng nằm trong hộp màu xám. (Đối với bất kỳ sự kết hợp của một trong hai undefinedhoặc nullhoặc cả hai, ==sẽ luôn luôn trả trueNgoài ra, cho dù giá trị là ở phía bên trái hoặc phải không quan trọng,. ==(Và ===) sẽ trả lại kết quả tương tự.)
user2033427

55

JavaScript === so với == .

0==false   // true
0===false  // false, because they are of a different type
1=="1"     // true, auto type coercion
1==="1"    // false, because they are of a different type

54

Điều đó có nghĩa là bình đẳng mà không có kiểu ép buộc kiểu có nghĩa là JavaScript không tự động chuyển đổi bất kỳ loại dữ liệu nào khác thành kiểu dữ liệu chuỗi

0==false   // true,although they are different types

0===false  // false,as they are different types

2=='2'    //true,different types,one is string and another is integer but 
            javaScript convert 2 to string by using == operator 

2==='2'  //false because by using === operator ,javaScript do not convert 
           integer to string 

2===2   //true because both have same value and same types 

48

Trong một kịch bản điển hình sẽ không có sự khác biệt hiệu suất. Quan trọng hơn có thể là thực tế rằng nghìn "===" nặng hơn 1 KB so với nghìn "==" :) Trình biên dịch JavaScript có thể cho bạn biết nếu có sự khác biệt về hiệu suất trong trường hợp của bạn.

Nhưng cá nhân tôi sẽ làm những gì mà JSLint gợi ý. Khuyến nghị này không phải vì vấn đề hiệu suất, mà vì phương tiện cưỡng chế kiểu ('\t\r\n' == 0)là đúng.


4
Không phải lúc nào cũng đúng. Với nén gzip, sự khác biệt sẽ gần như không đáng kể.
Daniel X Moore

1
Đồng ý, nhưng nghìn "===" cũng có nghĩa là 10 nghìn dòng mã khác, do đó, 1kb ít nhiều ...;)
Jonny

Nếu bạn quan tâm đến kích thước thì chỉ cần trao đổi tất cả == với ===, sau đó sử dụng biểu thức chính quy trong av eval để chuyển đổi lại

46

Toán tử so sánh bằng nhau == gây nhầm lẫn và nên tránh.

Nếu bạn CÓ PHẢI sống với nó, sau đó nhớ 3 điều sau đây:

  1. Nó không mang tính bắc cầu: (a == b)(b == c) không dẫn đến (a == c)
  2. Nó loại trừ lẫn nhau cho phủ định của nó: (a == b)(a! = B) luôn giữ các giá trị Boolean đối diện, với tất cả a và b.
  3. Trong trường hợp nghi ngờ, hãy học thuộc lòng bảng chân lý sau:

BẢNG HOẠT ĐỘNG THIẾT BỊ BẮT ĐẦU TRONG JAVASCRIPT

  • Mỗi hàng trong bảng là một bộ gồm 3 giá trị "bằng nhau", nghĩa là bất kỳ 2 giá trị nào trong số chúng đều bằng nhau bằng cách sử dụng dấu == *

** CHIẾN LƯỢC: lưu ý rằng bất kỳ hai giá trị nào trên cột đầu tiên không bằng nhau theo nghĩa đó. **

''       == 0 == false   // Any two values among these 3 ones are equal with the == operator
'0'      == 0 == false   // Also a set of 3 equal values, note that only 0 and false are repeated
'\t'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\r'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\n'     == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
'\t\r\n' == 0 == false   // -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --

null == undefined  // These two "default" values are not-equal to any of the listed values above
NaN                // NaN is not equal to any thing, even to itself.

39

Không thể có bất kỳ sự khác biệt hiệu suất giữa hai hoạt động trong việc sử dụng của bạn. Không có chuyển đổi loại nào được thực hiện vì cả hai tham số đã cùng loại. Cả hai hoạt động sẽ có một so sánh loại theo sau là so sánh giá trị.


38

Đúng! Nó không thành vấn đề.

===toán tử trong javascript kiểm tra giá trị cũng như kiểu trong đó ==toán tử chỉ kiểm tra giá trị (không chuyển đổi loại nếu được yêu cầu) .

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

Bạn có thể dễ dàng kiểm tra nó. Dán mã sau vào tệp HTML và mở mã trong trình duyệt

<script>

function onPageLoad()
{
    var x = "5";
    var y = 5;
    alert(x === 5);
};

</script>

</head>

<body onload='onPageLoad();'>

Bạn sẽ nhận được ' sai ' trong cảnh báo. Bây giờ sửa đổi onPageLoad()phương pháp để alert(x == 5);bạn sẽ nhận được đúng .


33

=== toán tử kiểm tra các giá trị cũng như các loại biến cho sự bằng nhau.

== toán tử chỉ kiểm tra giá trị của các biến cho đẳng thức.


32

Đây là một bài kiểm tra nghiêm ngặt.

Đó là một điều tốt đặc biệt là nếu bạn đang kiểm tra giữa 0 và sai và null.

Ví dụ: nếu bạn có:

$a = 0;

Sau đó:

$a==0; 
$a==NULL;
$a==false;

Tất cả trả về đúng và bạn có thể không muốn điều này. Giả sử bạn có một hàm có thể trả về chỉ số 0 của một mảng hoặc sai khi thất bại. Nếu bạn kiểm tra bằng "==" sai, bạn có thể nhận được kết quả khó hiểu.

Vì vậy, với điều tương tự như trên, nhưng một bài kiểm tra nghiêm ngặt:

$a = 0;

$a===0; // returns true
$a===NULL; // returns false
$a===false; // returns false

3
Trong JavaScript, điều này là hoàn toàn sai và không đầy đủ sai. 0 != null. -1
Ry-

31

Đôi khi, JSLint cung cấp cho bạn những lý do không thực tế để sửa đổi công cụ. ===có hiệu suất chính xác như ==thể các loại đã giống nhau.

Nó chỉ nhanh hơn khi các loại không giống nhau, trong trường hợp đó, nó không cố gắng chuyển đổi các loại mà trực tiếp trả về một sai.

Vì vậy, IMHO, JSLint có thể được sử dụng để viết mã mới, nhưng tối ưu hóa quá mức vô ích nên được tránh bằng mọi giá.

Có nghĩa là, không có lý do gì để thay đổi ==thành ===kiểm tra như if (a == 'test')khi bạn biết điều đó vì thực tế chỉ có thể là Chuỗi.

Sửa đổi nhiều mã theo cách đó làm lãng phí thời gian của nhà phát triển và người đánh giá và không đạt được gì.


30

Đơn giản

==có nghĩa là so sánh giữa các toán hạng với type conversion

&

===có nghĩa là so sánh giữa các toán hạng mà không có type conversion

Chuyển đổi loại trong javaScript có nghĩa là javaScript tự động chuyển đổi bất kỳ loại dữ liệu nào khác thành các loại dữ liệu chuỗi.

Ví dụ:

123=='123'   //will return true, because JS convert integer 123 to string '123'
             //as we used '==' operator 

123==='123' //will return false, because JS do not convert integer 123 to string 
            //'123' as we used '===' operator 

26

Một ví dụ đơn giản là

2 == '2'  -> true, values are SAME because of type conversion.

2 === '2'  -> false, values are NOT SAME because of no type conversion.

25

Cả 2 câu trả lời hàng đầu được đề cập == có nghĩa là bình đẳng và === có nghĩa là danh tính. Thật không may, tuyên bố này là không chính xác.

Nếu cả hai toán hạng của == là các đối tượng, thì chúng được so sánh để xem chúng có phải là cùng một đối tượng không. Nếu cả hai toán hạng đều trỏ đến cùng một đối tượng, thì toán tử bằng nhau trả về true. Nếu không, hai không bằng nhau.

var a = [1, 2, 3];  
var b = [1, 2, 3];  
console.log(a == b)  // false  
console.log(a === b) // false  

Trong đoạn mã trên, cả == và === đều sai vì a và b không phải là cùng một đối tượng.

Điều đó có nghĩa là: nếu cả hai toán hạng của == là các đối tượng, == hoạt động giống như ===, cũng có nghĩa là danh tính. Sự khác biệt cơ bản của hai toán tử này là về chuyển đổi loại. == có chuyển đổi trước khi kiểm tra sự bằng nhau, nhưng === thì không.


24

Theo nguyên tắc thông thường, tôi thường sử dụng ===thay vì ==(và !==thay vì !=).

Lý do được giải thích trong các câu trả lời ở trên và Douglas Crockford cũng khá rõ ràng về nó ( JavaScript: The Good Parts ).

Tuy nhiên, có một ngoại lệ duy nhất : == nulllà một cách hiệu quả để kiểm tra 'là null hoặc không xác định':

if( value == null ){
    // value is either null or undefined
}

Ví dụ jQuery 1.9.1 sử dụng mẫu này 43 lần và trình kiểm tra cú pháp JSHint thậm chí còn cung cấp eqnulltùy chọn thư giãn cho lý do này.

Từ hướng dẫn kiểu jQuery :

Kiểm tra bình đẳng nghiêm ngặt (===) nên được sử dụng có lợi cho ==. Ngoại lệ duy nhất là khi kiểm tra không xác định và null bằng cách null.

// Check for both undefined and null values, for some important reason. 
undefOrNull == null;

22

Vấn đề là bạn có thể dễ dàng gặp rắc rối vì JavaScript có rất nhiều chuyển đổi ngầm có nghĩa là ...

var x = 0;
var isTrue = x == null;
var isFalse = x === null;

Mà khá sớm trở thành một vấn đề. Mẫu tốt nhất về lý do tại sao chuyển đổi ngầm là "ác" có thể được lấy từ mã này trong MFC / C ++, thứ thực sự sẽ biên dịch do chuyển đổi ngầm định từ CString sang HANDLE, một loại con trỏ typedef ...

CString x;
delete x;

Mà rõ ràng trong thời gian chạy không làm những điều rất không xác định ...

Google cho các chuyển đổi ngầm định trong C ++ và STL để có được một số đối số chống lại nó ...


2
0 == nulllà sai.
Garrett


21

So sánh bình đẳng:

Nhà điều hành ==

Trả về true, khi cả hai toán hạng đều bằng nhau. Các toán hạng được chuyển đổi sang cùng loại trước khi được so sánh.

>>> 1 == 1
true
>>> 1 == 2
false
>>> 1 == '1'
true

So sánh bằng và loại:

Nhà điều hành ===

Trả về true nếu cả hai toán hạng đều bằng nhau và cùng loại. Nói chung sẽ tốt hơn và an toàn hơn nếu bạn so sánh theo cách này, vì không có chuyển đổi loại hậu trường.

>>> 1 === '1'
false
>>> 1 === 1
true


20

null và không xác định là hư vô, nghĩa là

var a;
var b = null;

Ở đây abkhông có giá trị. Trong khi đó, 0, false và '' đều là các giá trị. Một điều phổ biến bao gồm tất cả những điều này là tất cả chúng đều là giá trị giả, có nghĩa là tất cả chúng đều thỏa mãn điều kiện giả.

Vì vậy, 0, false và '' cùng nhau tạo thành một nhóm phụ. Và mặt khác, null & không xác định tạo thành nhóm phụ thứ hai. Kiểm tra các so sánh trong hình dưới đây. null và không xác định sẽ bằng nhau. Ba người kia sẽ bằng nhau. Nhưng, tất cả chúng đều được coi là điều kiện giả trong JavaScript.

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

Điều này giống như bất kỳ đối tượng nào (như {}, mảng, v.v.), chuỗi không trống & Boolean true đều là các điều kiện trung thực. Nhưng, tất cả đều không bằng nhau.

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.