ควรใช้โอเปอเรเตอร์ตัวใด (== vs ===) ในการเปรียบเทียบ JavaScript


5665

ฉันกำลังใช้JSLintเพื่ออ่าน JavaScript และมันกลับคำแนะนำมากมายเพื่อแทนที่==(เครื่องหมายเท่ากับสอง) ด้วย===(เครื่องหมายเท่ากับสาม) เมื่อทำสิ่งต่าง ๆ เช่นการเปรียบเทียบidSele_UNVEHtype.value.length == 0ภายในของifคำสั่ง

มีประโยชน์ด้านประสิทธิภาพการแทนที่==ด้วย===หรือไม่

การปรับปรุงประสิทธิภาพใด ๆ จะได้รับการต้อนรับเนื่องจากมีตัวดำเนินการเปรียบเทียบหลายตัว

หากไม่มีการแปลงประเภทเกิดขึ้นจะมีประสิทธิภาพเพิ่มขึ้น==หรือไม่


134
ผู้ที่อาจสนใจในหัวข้อเดียวกัน=== vs ==แต่ใน PHP สามารถอ่านได้ที่นี่: stackoverflow.com/questions/2401478/why-is-faster-than-in-php/…
Marco Demaio

257
ในกรณีที่ทุกคนสงสัยว่าในปี 2012: ===เป็นวิธีที่==เร็วกว่า jsperf.com/comparison-of-comparisons
Ry-

25
@minitech มันควรจะเป็นอย่างที่มันไม่ได้ทำแปลงชนิด
Umur Kontacı

19
@minitech ผมสงสัยทุกคนเป็นไปเพื่อให้โปรแกรมของพวกเขาอย่างเห็นได้ชัดเร็วขึ้นโดยการใช้มากกว่า=== ==ในความเป็นจริงมาตรฐานไม่ได้แสดงความแตกต่างใหญ่ระหว่างเบราว์เซอร์สมัยใหม่ โดยส่วนตัวแล้วฉันมักจะใช้==ทุกที่ยกเว้นว่าฉันต้องการความเท่าเทียมกันอย่างเข้มงวดจริงๆ
เรนท์

5
นี่คือส่วนหนึ่งของJS The Good Partsของ Crockford ที่ซึ่งเขาพูดถึง===และ==โอเปอเรเตอร์: youtube.com/ถ้าไม่เล่นก็เป็นเวลา15:20
davidhiggins

คำตอบ:


6485

ตัวดำเนินการความเสมอภาคที่เข้มงวด ( ===) ทำงานเหมือนกันกับตัวดำเนินการความเท่าเทียมกันทางนามธรรม ( ==) ยกเว้นการแปลงชนิดไม่ถูกทำและประเภทต้องเป็นชนิดเดียวกัน

เอกสารอ้างอิง: Javascript Tutorial: ตัวดำเนินการเปรียบเทียบ

==ผู้ประกอบการจะเปรียบเทียบเพื่อความเท่าเทียมกันหลังจากทำแปลงชนิดใด ๆ ที่จำเป็น ===ผู้ประกอบการจะไม่ทำแปลงดังนั้นหากสองค่าไม่ประเภทเดียวกันก็จะกลับมา=== falseทั้งสองอย่างรวดเร็วเท่ากัน

เพื่ออ้างอิงจาวาสคริปต์ที่ยอดเยี่ยมของ Douglas Crockford : The Good Parts ,

JavaScript มีสองชุดของผู้ประกอบการเท่าเทียมกัน: ===และ!==และฝาแฝดที่ชั่วร้ายของพวกเขาและ== !=คนดีทำงานในแบบที่คุณคาดหวัง หากทั้งสองตัวถูกดำเนินการเป็นประเภทเดียวกันและมีค่าเหมือนกันแล้ว===ผลิตtrueและการผลิต!== falseฝาแฝดที่ชั่วร้ายทำสิ่งที่ถูกต้องเมื่อตัวถูกดำเนินการเป็นประเภทเดียวกัน แต่ถ้าพวกมันต่างประเภทกันพวกมันพยายามที่จะบีบบังคับค่า กฎที่พวกเขาทำมีความซับซ้อนและไม่น่าจดจำ นี่คือบางกรณีที่น่าสนใจ:

'' == '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

ตารางเปรียบเทียบความเสมอภาค

การขาดความไวแสงนั้นน่าตกใจ คำแนะนำของฉันคืออย่าใช้ฝาแฝดที่ชั่วร้าย แต่มักจะใช้และ=== !==การเปรียบเทียบทั้งหมดแสดงให้เห็นถึงการผลิตfalseกับ===ผู้ประกอบการ


ปรับปรุง:

จุดที่ดีถูกนำเสนอโดย@Casebashในความคิดเห็นและในคำตอบของ @Phillipe Laybaert เกี่ยวกับวัตถุ สำหรับวัตถุและดำเนินการอย่างสอดคล้องกับวัตถุอื่น (ยกเว้นในกรณีพิเศษ)=====

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

กรณีพิเศษคือเมื่อคุณเปรียบเทียบแบบดั้งเดิมกับวัตถุที่ประเมินเป็นแบบดั้งเดิมเดียวกันเนื่องจากวิธีการtoStringหรือ valueOfตัวอย่างเช่นพิจารณาการเปรียบเทียบสตริงดั้งเดิมกับวัตถุสตริงที่สร้างขึ้นโดยใช้ตัวStringสร้าง

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

ต่อไปนี้เป็น==ผู้ประกอบการคือการตรวจสอบค่าของวัตถุสองและกลับมาtrueแต่จะเห็นว่าพวกเขาไม่ได้ประเภทเดียวกันและกลับมา=== falseอันไหนที่ถูก? นั่นขึ้นอยู่กับสิ่งที่คุณพยายามเปรียบเทียบ คำแนะนำของฉันคือการข้ามคำถามทั้งหมดและไม่ใช้ตัวStringสร้างเพื่อสร้างวัตถุสตริงจากตัวอักษรสตริง

อ้างอิง
http://www.ecma-international.org/ecma-262/5.1/#sec-11.9.3


236
=== ไม่เร็วถ้าประเภทเหมือนกัน หากประเภทไม่เหมือนกัน === จะเร็วกว่าเพราะจะไม่พยายามแปลง
Bill the Lizard

520
=== จะไม่ช้ากว่า == พวกเขาทั้งสองทำการตรวจสอบประเภทดังนั้น === ไม่ได้ทำอะไรพิเศษเมื่อเทียบกับ == แต่การตรวจสอบประเภทอาจอนุญาตให้ === ออกเร็วกว่าเมื่อประเภทไม่เหมือนกัน
Bill the Lizard

246
การแทนที่ทั้งหมด == /! = ด้วย === /! == เพิ่มขนาดของไฟล์ js มันจะใช้เวลาในการโหลดนานขึ้น :)
Marco Demaio

92
"... กฎที่พวกเขาทำนั้นมีความซับซ้อนและไม่น่าจดจำ ... " ตอนนี้ข้อความดังกล่าวทำให้คุณรู้สึกปลอดภัยมากเมื่อตั้งโปรแกรม ...
Johan

47
จาก Crockford: "การขาดความไวเป็นเรื่องน่าตกใจ" หากคุณพัฒนาซอฟต์แวร์และไม่พบว่าการขาดความไวในการเตือนภัยของตัวดำเนินการเปรียบเทียบหรือถ้าการเปรียบเทียบความเร็วระหว่าง == และ === หรือขนาดไฟล์ / เวลาโหลดจะมีความสำคัญในใจของคุณมากกว่าการกำหนดพฤติกรรมของตัวดำเนินการเปรียบเทียบ อาจต้องย้อนกลับและเริ่มต้นใหม่
jinglesthula

1144

การใช้ตัว==ดำเนินการ ( ความเท่าเทียมกัน )

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

การใช้===โอเปอเรเตอร์ ( ข้อมูลประจำตัว )

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

นี่เป็นเพราะตัวดำเนินการความเสมอภาค==นั้นพิมพ์การข่มขู่หมายความว่าล่ามจะพยายามแปลงค่าโดยปริยายก่อนทำการเปรียบเทียบ

ในทางกลับกันตัวดำเนินการเอกลักษณ์===ไม่ได้ทำการข่มขู่และไม่แปลงค่าเมื่อทำการเปรียบเทียบและดังนั้นจึงเร็วกว่า (ตามการทดสอบเกณฑ์มาตรฐาน JS นี้ ) เนื่องจากข้ามขั้นตอนเดียว


9
@ ซอฟต์แวร์ Monkey: ไม่ใช่สำหรับประเภทค่า (ตัวเลข, บูลีน, ... )
Philippe Leybaert

34
เนื่องจากไม่มีใครได้พูดถึงตารางความเท่าเทียมกันของจาวาสคริปต์นี่คือ: dorey.github.io/JavaScript-Equality-Table
blaze

6
ในข้อความแรกคุณแน่ใจหรือไม่ว่า 'จริง' ถูกแปลงเป็น 1 และไม่ใช่ 1 แปลงเป็นจริง
Shadi Namrouti

2
คำว่า "ความเท่าเทียมกัน" และ "ตัวตน" มาจากที่ใด มาตรฐานไม่ได้ใช้ข้อกำหนดเหล่านั้น มันเรียกว่า=="ความเท่าเทียมกันทางนามธรรม" และเรียกว่า==="ความเท่าเทียมกันอย่างเข้มงวด" ได้รับการเรียก=="ความเท่าเทียมกัน" ชนิดใด IMHO น่ากลัวเพราะมันไม่ได้เป็นสกรรมกริยา แต่ทำไมการเล่นลิ้น? ฉันใช้ปัญหามากขึ้นกับ "ตัวตน" แม้ว่า; ฉันคิดว่าคำนี้เป็นคำที่ทำให้เข้าใจผิดแม้ว่ามันจะใช้งานได้ แต่อย่างจริงจังใครเป็นคนบัญญัติคำว่า "ตัวตน"? ฉันค้นหามาตรฐานและไม่พบ
Ray Toal

1
"ตัวตน" เป็นคำที่ผิดมาก การเปรียบเทียบเอกลักษณ์ในทุกภาษาที่ฉันใช้หมายถึงหนึ่งในวัตถุเดียวกันนั่นคือตัวแปรอ้างอิงสองตัวนั้นไม่เพียงชี้ไปที่เอนทิตีเทียบเท่า แต่เป็นเอนทิตีเดียวกัน
Inigo

724

การแสดงภาพที่น่าสนใจของการเปรียบเทียบความเท่าเทียมกันระหว่างและ =====

ที่มา: http://dorey.github.io/JavaScript-Equality-Table/


var1 === var2

เมื่อใช้===สำหรับการทดสอบความเท่าเทียมกันของ JavaScript ทุกอย่างเป็นไปตามที่เป็น ไม่มีการแปลงอะไรก่อนประเมิน

การประเมินความเท่าเทียมกันของ === ใน JS


var1 == var2

เมื่อใช้==สำหรับการทดสอบความเท่าเทียมกันของ JavaScript จะมีการแปลงแบบ Funky

การประเมินความเท่าเทียมกันของ == ใน JS

นิทานสอนใจ:

ใช้จนกว่าคุณจะเข้าใจการแปลงที่เกิดขึ้นกับ=====


3
@mfeineis คุณหมายถึง === หรือ! == แทนที่จะเป็น == หรือ! = ไม่ต้องการสับสนผู้เขียนโค้ดใหม่)
katalin_2003

2
จากประสบการณ์ของฉันโดยใช้สามเท่ากับสามารถทำให้เกิดปัญหาและควรหลีกเลี่ยงเว้นแต่เข้าใจอย่างสมบูรณ์ สองเท่ากับให้ผลลัพธ์ที่ดีกว่ามากเพราะ 99% ของเวลาที่ฉันไม่ต้องการให้ประเภทเท่ากัน
vsync

13
@vsync: หากคุณไม่ต้องการให้ประเภทเท่ากันคุณควรใช้สามเท่ากับ !
SNag

7
หนึ่งข้อยกเว้น: คุณสามารถใช้x == nullเพื่อตรวจสอบว่าxเป็นหรือnull undefined
Andy

1
@ user648026: คำถามที่เป็นเรื่องเกี่ยวกับความเท่าเทียมกันเมื่อเทียบกับเทียบกับ== ===ตอนบนและกรณีที่ต่ำกว่าที่มีอยู่แล้วไม่เท่ากันและจะกลับมาfalseมีทั้ง==และ===ผู้ประกอบการ นอกจากนี้คำหลักtrue, false, undefined, null, Infinityอยู่ใน JS เฉพาะในกรณีหนึ่งและไม่สามารถนำมาใช้ในกรณีส่วนบนหรือผสม
SNag

609

ในคำตอบที่นี่ฉันไม่ได้อ่านอะไรเกี่ยวกับความหมายที่เท่ากัน บางคนจะพูดว่ามีความ===หมายเท่ากันและเป็นประเภทเดียวกันแต่นั่นไม่จริงเลย มันจริงหมายความว่าทั้งสองตัวถูกดำเนินการอ้างอิงวัตถุเดียวกันหรือในกรณีของประเภทค่ามีค่าเท่ากัน

ดังนั้นขอรหัสต่อไปนี้:

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

เหมือนกันที่นี่:

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

หรือแม้กระทั่ง:

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

พฤติกรรมนี้ไม่ชัดเจนเสมอไป เรื่องราวมีมากกว่าเรื่องความเสมอภาคและความเป็นคนประเภทเดียวกัน

กฎคือ:

สำหรับประเภทค่า (ตัวเลข):
a === bส่งคืนจริงถ้าaและbมีค่าเท่ากันและเป็นประเภทเดียวกัน

สำหรับประเภทการอ้างอิง:
a === bคืนค่าจริงถ้าaและbอ้างอิงวัตถุเดียวกันที่แน่นอน

สำหรับ strings:
a === bคืนค่าจริงถ้าaและbทั้งคู่เป็นสตริงและมีอักขระเหมือนกันทุกประการ


เงื่อนไข: กรณีพิเศษ ...

สตริงไม่ใช่ประเภทค่า แต่ใน Javascript จะทำงานเหมือนประเภทค่าดังนั้นจึงจะเป็น "เท่ากัน" เมื่ออักขระในสตริงเหมือนกันและเมื่อมีความยาวเท่ากัน (ดังอธิบายในกฎข้อที่สาม)

ตอนนี้มันกลายเป็นที่น่าสนใจ:

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

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

แต่เรื่องนี้ล่ะ:

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

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

ฉันคิดว่าสตริงทำงานเหมือนประเภทค่าหรือไม่ มันขึ้นอยู่กับคนที่คุณถาม ... ในกรณีนี้กและขไม่ใช่ประเภทเดียวกัน aเป็นประเภทObjectในขณะที่เป็นประเภทb stringเพียงจำไว้ว่าการสร้างวัตถุสตริงโดยใช้Stringคอนสตรัคสร้างบางสิ่งบางอย่างชนิดObjectที่จะทำงานเป็นสตริงมากที่สุดของเวลา


6
activa: ฉันจะชี้แจงว่าสตริงนั้นมีค่าเท่ากันเมื่อเป็นตัวอักษรเท่านั้น new String ("abc") === "abc" เป็นเท็จ (ตามการวิจัยของฉัน)
Lawrence Dol

3
new Number() == "0". นอกจากนี้ใน Firefox:(function(){}) == "function () {\n}"
Thomas Eding

3
new String("123") !== "123"ขอขอบคุณสำหรับการอธิบายว่าทำไม พวกมันแตกต่างกัน เรียบง่าย แต่สับสน
สไตล์

21
Stringวัตถุประพฤติเป็นสตริงเช่นเดียวกับวัตถุอื่นnew Stringไม่ควรใช้เนื่องจากไม่ได้สร้างสตริงจริง สตริงจริงและสามารถสร้างขึ้นด้วยตัวอักษรสตริงหรือการเรียกStringใช้เป็นฟังก์ชั่นโดยไม่ต้อง newตัวอย่างเช่น:String(0); //"0", Real string, not an object
Esailija

6
แต่ในกรณีที่คุณมีรายละเอียดตัวดำเนินการ "==" จะทำงานเหมือนกันทุกประการ
Yaron Levi

270

ให้ฉันเพิ่มคำแนะนำนี้:

หากมีข้อสงสัยอ่านข้อกำหนด !

ECMA-262 เป็นข้อกำหนดสำหรับภาษาสคริปต์ซึ่ง JavaScript เป็นภาษาถิ่น แน่นอนว่าในทางปฏิบัติมันมีความสำคัญมากกว่าวิธีการที่เบราว์เซอร์ที่สำคัญที่สุดประพฤติมากกว่าคำจำกัดความลึกลับของวิธีการจัดการบางสิ่งบางอย่าง แต่มันก็เป็นประโยชน์ที่จะเข้าใจว่าทำไมใหม่ String ( "เป็น")! == "A"

โปรดให้ฉันอธิบายวิธีอ่านข้อกำหนดเพื่อชี้แจงคำถามนี้ ฉันเห็นว่าในหัวข้อเก่าแก่นี้ไม่มีใครมีคำตอบสำหรับผลแปลก ๆ ดังนั้นหากคุณสามารถอ่านสเปคนี้จะช่วยให้คุณในอาชีพของคุณอย่างมาก มันเป็นทักษะที่ได้มา งั้นมาต่อกัน

การค้นหาไฟล์ PDF สำหรับ === จะพาฉันไปที่หน้า 56 ของข้อกำหนด: 11.9.4 ผู้ประกอบการที่เข้มงวดเท่ากับ (===)และหลังจากลุยผ่านกลุ่มเฉพาะฉันพบ:

11.9.6 เข้มงวดเท่าเทียมกันเปรียบเทียบขั้นตอนวิธี
การเปรียบเทียบ x === Y ที่ x และ y เป็นค่าผลิตจริงหรือเท็จ การเปรียบเทียบดังกล่าวจะดำเนินการดังนี้
  1. ถ้าประเภท (x) จะแตกต่างจากชนิด (y) ผลตอบแทนที่เป็นเท็จ
  2. หากประเภท (x) คือไม่ได้กำหนดกลับมาจริง
  3. หากประเภท (x) เป็นโมฆะกลับมาจริง
  4. หากประเภท (x) ไม่ได้เป็นจำนวนไปที่ขั้นตอน 11.
  5. หากเป็น x น่านกลับเท็จ
  6. หาก Y คือน่านกลับเท็จ
  7. ถ้า x เป็นค่าตัวเลขเดียวกับปีกลับมาจริง
  8. ถ้า x เป็น 0 และ Y เป็น -0 กลับมาจริง
  9. ถ้า x และ y -0 เป็น 0 กลับมาจริง
  10. กลับเท็จ
  11. ถ้า Type (x) เป็น String ให้ส่งคืนค่าจริงถ้า x และ y เป็นลำดับอักขระที่เหมือนกันทั้งหมด (ความยาวเท่ากันและอักขระเดียวกันในตำแหน่งที่สอดคล้องกัน); มิฉะนั้นผลตอบแทนที่เป็นเท็จ
  12. ถ้าประเภท (x) เป็นบูลีนกลับมาจริงถ้า x และ y มีทั้งจริงหรือทั้งจำทั้งเท็จ ; มิฉะนั้นผลตอบแทนที่เป็นเท็จ
  13. คืนความจริงถ้า x และ y อ้างถึงวัตถุเดียวกันหรือถ้าพวกเขาอ้างถึงวัตถุที่เข้าร่วมซึ่งกันและกัน (ดู 13.1.2) มิฉะนั้นผลตอบแทนที่เป็นเท็จ

สิ่งที่น่าสนใจคือขั้นตอนที่ 11 ใช่สตริงจะถือว่าเป็นประเภทของค่า แต่นี้ไม่ได้อธิบายว่าทำไมใหม่ String ( "เป็น")! == "A" เรามีเบราว์เซอร์ที่ไม่สอดคล้องกับ ECMA-262 หรือไม่?

ไม่เร็วมาก!

ตรวจสอบประเภทของตัวถูกดำเนินการ ลองด้วยตัวคุณเองโดยการตัดพวกเขาในtypeof () ฉันพบว่าString ใหม่ ("a")เป็นวัตถุและมีการใช้ขั้นตอนที่ 1: คืนค่าเท็จหากประเภทแตกต่างกัน

หากคุณสงสัยว่าเหตุใดString ใหม่ ("a")จึงไม่ส่งคืนสตริงคุณจะออกกำลังกายเพื่ออ่านข้อกำหนดได้อย่างไร มีความสุข!


Aidiakapi เขียนสิ่งนี้ในความคิดเห็นด้านล่าง:

จากสเปค

11.2.2 ผู้ประกอบการใหม่ :

ถ้า Type (ตัวสร้าง) ไม่ใช่วัตถุให้โยนข้อยกเว้น TypeError

ด้วยคำอื่น ๆ หาก String จะไม่เป็นประเภทวัตถุก็ไม่สามารถใช้กับผู้ประกอบการใหม่

ใหม่จะส่งคืนวัตถุเสมอแม้กระทั่งสำหรับตัวสร้างสตริงด้วยเช่นกัน และอนิจจา! ค่าซีแมนทิกส์ของสตริง (ดูขั้นตอนที่ 11) จะสูญหายไป

และนี้ในที่สุดก็หมายถึง: ใหม่ String ( "เป็น") == "เป็น"!


ผลลัพธ์ของ Type (x) มีความหมายเหมือนกันกับ typeof?
Dfr

@ เกือบฉันไม่เข้าใจความวิตกกังวลเกี่ยวกับพฤติกรรมอย่างnew String('x')แน่นอนเพราะฉันไม่เคยเห็นรหัสใด ๆ ในป่าที่ใช้วัตถุห่อหุ้มแบบดั้งเดิมและฉันไม่คิดว่าจะมีเหตุผลที่ดีมากโดยเฉพาะอย่างยิ่งไม่ใช่ทุกวันนี้ คุณเคยพบรหัสที่ทำหรือไม่?
แอนดี้

@Andy new String()ปัญหาคือรหัสของบุคคลที่สามที่เป็นอันตรายหรือเพียงแค่เลอะเทอะแล้วคุณจะไม่สามารถสรุปได้ว่าไม่มีใครใช้
nalply

ถ้ามันเลอะเทอะ === คุณจะรู้ได้อย่างไร หากเป็นอันตรายฉันคิดว่าnew String()น่าจะเป็นสิ่งที่คุณกังวลน้อยที่สุด ฉันเข้าใจถึงความกังวลในทางทฤษฎี แต่คุณมีอีกตัวอย่างจริงหรือไม่? สำหรับฉันมันเหมือนความวิตกกังวลแบบเก่าที่ใครบางคนสามารถตั้งค่าundefinedให้เป็นค่าอื่นได้
Andy

ฉันไม่ทราบว่าคุณได้รับที่ใด แต่อัลกอริทึมการเปรียบเทียบของคุณผิดในขั้นตอนที่ 2 ส่วน "7.2.15 การเปรียบเทียบความเท่าเทียมกันอย่างเข้มงวด" ก่อนอื่นตรวจสอบว่าประเภทเหมือนกันหรือไม่ถ้าใช่ไม่ว่าจะเป็นหมายเลข หากไม่มีให้ใช้ส่วน "7.2.12 SameValueNonNumber (x, y)"
แกนสนิม

101

ใน PHP และ JavaScript มันเป็นตัวดำเนินการความเท่าเทียมที่เข้มงวด ซึ่งหมายความว่ามันจะเปรียบเทียบทั้งประเภทและค่า


10
@ David: ถูกต้อง นั่นเป็นเหตุผลที่คำตอบนี้ไม่ถูกต้อง (หรือแม้กระทั่งที่ไม่ถูกต้อง)
ฟิลิปป์ Leybaert

7
@David var a = {}, b = {}; a == bคืนค่า false
nyuszika7h

6
ใช่: วัตถุสองชนิดที่แตกต่างกันซึ่งมีประเภทและค่าเหมือนกันเปรียบเทียบเป็นเท็จนั่นคือคำตอบนี้ผิด ทำไมมันมี 50 upvotes
alexis

4
ฉันรู้ว่านี่เก่า แต่ชี้แจงว่าทำไมคำตอบนี้ยังคง "ถูกต้อง" เป็นเพราะในตัวอย่างvar a = {}, b = {};ในขณะที่ทั้งสองaและbเป็นทั้งวัตถุ แต่พวกเขาไม่ได้ค่าเดียวกันพูดทางเทคนิค พวกเขามีความแตกต่างกันกรณี โปรดทราบว่าการเปรียบเทียบอินสแตนซ์ทำงานแตกต่างจากการเปรียบเทียบแบบดั้งเดิม ซึ่งอาจเพิ่มความสับสนนี้ คุณจะเห็นพฤติกรรมการเปรียบเทียบที่คล้ายกันหากคุณใช้ประเภทข้อมูลดั้งเดิมของอินสแตนซ์ เช่นหรือnew String('asdf') new Number(5)เช่นnew Number(5) == new Number(5)เท็จแม้ว่าพวกเขาจะถือค่าเดียวกัน
Norman Breau

1
เราทุกคนลืมว่าการอ้างอิงไปยังวัตถุจริงๆแล้วเป็นประเภทค่าเนื่องจากเป็นตัวชี้ไปยังสล็อตหน่วยความจำ การเปรียบเทียบออบเจ็กต์ไม่ได้เปรียบเทียบ "คุณค่าของออบเจ็กต์" แต่ไม่ว่าพอยน์เตอร์ทั้งสองจะเหมือนกันหรือไม่ซึ่งหมายความว่าพวกเขาอ้างถึงสล็อตหน่วยความจำเดียวกัน นั่นคือความแตกต่างที่ละเอียดมากในการเปรียบเทียบประเภทเนื่องจากตัวดำเนินการ "===" จำเป็นต้องพูดว่า "ถ้าประเภทค่าและการอ้างอิงไปยังวัตถุในหน่วยความจำเหมือนกัน"
Stokely

101

ฉันทดสอบสิ่งนี้ใน Firefox ด้วยFirebugโดยใช้รหัสเช่นนี้:

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");

ผลลัพธ์ของฉัน (ผ่านการทดสอบห้าครั้งและโดยเฉลี่ย):

==: 115.2
===: 114.4

ดังนั้นฉันจะบอกว่าความแตกต่างขั้นต่ำ (นี่คือการทำซ้ำมากกว่า 100,000 ครั้งโปรดจำไว้) นั้นเล็กน้อย ผลการดำเนินงานไม่ได้เป็น===เหตุผลที่จะทำ พิมพ์ความปลอดภัย (ดีเท่ากับที่คุณจะได้รับใน JavaScript) และคุณภาพของรหัสคือ


3
มากกว่าความปลอดภัยประเภทที่คุณต้องการความถูกต้องตรรกะ - บางครั้งคุณต้องการสิ่งที่เป็นจริงเมื่อ==ไม่เห็นด้วย
rpjohnst

4
ทีนี้สิ่งเหล่านี้จะเปรียบเทียบได้อย่างไรเมื่อมีการพิมพ์ตัวจริงสำหรับ==โอเปอเรเตอร์? โปรดจำไว้ว่านั่นคือเมื่อมีการเพิ่มประสิทธิภาพ
Hubert OG

2
ความแตกต่างที่สำคัญเมื่อทดสอบอย่างถูกต้องด้วยเหตุผลดังกล่าวข้างต้นของการตรวจสอบความไม่เท่าเทียมกันของประเภทที่รวดเร็วกว่าเท่านั้น jsfiddle.net/4jhuxkb2
Doug Morrow

คุณวัดประสิทธิภาพของบางอย่างเช่นนี้ในการปฏิบัติงาน / วินาทีไม่ใช่การทดสอบเดี่ยวในเบราว์เซอร์เดียว (อันที่มีส่วนแบ่งการตลาดประมาณ 5%) โดยใช้ console.time () ในขณะที่ใช้การทดสอบที่ไม่ใช้การข่มขู่ประเภท (เหตุผลทั้งหมด มันช้าลง) เข้าบัญชี นี่คือการทดสอบที่ไม่มีความหมายอย่างสมบูรณ์ คุณถูกต้องว่าการแสดงไม่ใช่เหตุผลที่จะใช้===มากกว่า==แต่คุณผิดที่การแสดงของพวกเขานั้นเท่ากันและคุณคิดว่าการทดสอบนี้พิสูจน์ให้เห็นว่าและคนอื่น ๆ เห็นด้วยเป็นเรื่องไร้สาระสำหรับฉัน
Stephen M Irving


87

===ประกอบการจะเรียกว่าเป็นตัวดำเนินการเปรียบเทียบที่เข้มงวดก็ไม่แตกต่างจาก==ผู้ประกอบการ

ให้ใช้ 2 vars a และ b

สำหรับ"a == ข"ในการประเมินให้เป็นจริงและขจำเป็นที่จะต้องเป็นค่าเดียวกัน

ในกรณีของ"a === b" a และ b ต้องเป็นค่าเดียวกันและเป็นชนิดเดียวกันเพื่อให้การประเมินเป็นจริง

นำตัวอย่างต่อไปนี้

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");
}

ในการสรุป ; การใช้ตัวดำเนินการ==อาจประเมินเป็นจริงในสถานการณ์ที่คุณไม่ต้องการให้ใช้ตัวดำเนินการ===จะปลอดภัยกว่า

ในสถานการณ์การใช้งาน 90% มันจะไม่สำคัญว่าคุณจะใช้อันไหน แต่จะมีประโยชน์ในการทราบความแตกต่างเมื่อคุณได้รับพฤติกรรมที่ไม่คาดคิดในหนึ่งวัน


82

ทำไมถึง==เดาไม่ได้?

คุณได้อะไรเมื่อคุณเปรียบเทียบสตริงที่ว่างเปล่า""กับศูนย์จำนวน0?

true

ใช่นั่นถูกต้องตาม==สตริงว่างเปล่าและเลขศูนย์เป็นเวลาเดียวกัน

และยังไม่จบตรงนี้อีกอัน:

'0' == false // true

สิ่งต่าง ๆ แปลก ๆ กับอาร์เรย์

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

จากนั้นก็แปลกด้วยเชือก

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

มันแย่ลง:

เมื่อเท่ากับไม่เท่ากัน

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!

ให้ฉันพูดอีกครั้ง:

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

และนี่เป็นเพียงสิ่งที่บ้าคลั่งที่คุณได้รับจากสิ่งดั้งเดิม

มันเป็นระดับใหม่ของความบ้าคลั่งเมื่อคุณใช้==กับวัตถุ

ณ จุดนี้คุณอาจสงสัยว่า ...

ทำไมสิ่งนี้ถึงเกิดขึ้น

ก็เพราะต่างจาก "สามเท่า" ( ===) ซึ่งเพิ่งตรวจสอบว่าสองค่าเหมือนกันหรือไม่

==ทำสิ่งอื่นทั้งหมด

มันมีการจัดการพิเศษสำหรับฟังก์ชั่นการจัดการพิเศษสำหรับโมฆะไม่ได้กำหนดสตริงคุณชื่อมัน

มันค่อนข้างแปลกประหลาด

ในความเป็นจริงถ้าคุณพยายามที่จะเขียนฟังก์ชั่นที่ทำในสิ่งที่==มันจะมีลักษณะเช่นนี้:

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();
}

ดังนั้นสิ่งนี้หมายความว่าอย่างไร

มันหมายถึง==ซับซ้อน

เพราะมันซับซ้อนมันยากที่จะรู้ว่าจะเกิดอะไรขึ้นเมื่อคุณใช้งาน

ซึ่งหมายความว่าคุณสามารถจบลงด้วยข้อบกพร่อง

ดังนั้นคุณธรรมของเรื่องราวคือ ...

ทำให้ชีวิตของคุณซับซ้อนน้อยลง

ใช้แทน=====

ตอนจบ.


คุณlooseEqualผิด Function == Function.toString()เป็นจริง แต่looseEqual(Function, Function.toString())เป็นเท็จ ไม่แน่ใจว่าทำไมคุณกรองฟังก์ชั่นตั้งแต่ต้น
Oriol

@Oriol คุณถูกต้องฉันอัปเดตรหัสเป็นบัญชีสำหรับนั้น FYI จากการทดสอบของฉันมันไม่เพียงพอที่จะลบตัวกรองสำหรับ "ฟังก์ชั่น" แทนที่จะเป็น "ฟังก์ชั่น" แทนที่จะต้องจัดการแตกต่างกันโดยสิ้นเชิง
Luis Perez

ระวังสเป็คที่ไม่ได้ปฏิบัติหน้าที่แตกต่างกันพวกเขาเป็นเพียงวัตถุ ปัญหาดูเหมือนว่าคุณพึ่งพาtypeof x === "object"เพื่อตรวจสอบว่ามันเป็นวัตถุ แต่ `typeof ใช้งานได้เฉพาะสำหรับดั้งเดิมที่ไม่เป็นโมฆะ คุณอาจจะสนใจในของฉันรายการของวิธีที่เหมาะสมในการตรวจสอบถ้ามีค่าเป็นวัตถุ
Oriol

ฉันพยายามรักษาฟังก์ชั่นและวัตถุเดียวกัน แต่พบว่าผลลัพธ์ของเขาไม่ถูกต้อง ตัวอย่างเช่นถ้าฟังก์ชั่นได้รับการปฏิบัติเหมือนวัตถุแล้วเปรียบเทียบฟังก์ชั่นกับวัตถุที่ใช้ฟังก์ชั่น valueOf () หรือ toString () ที่ตรงกับฟังก์ชั่นจะผ่าน แต่ในความเป็นจริงมันไม่ได้ ตัวอย่าง: (function blah() { console.log("test"); }) != {valueOf:function(){return "function blah() { console.log(\"test\"); }";}}- เช็คเอาท์นี้ JS ซอซึ่งวิ่งทดสอบทั้งหมด: jsfiddle.net/luisperezphd/7k6gcn6g (มี 1,225 พีชคณิตทดสอบ)
หลุยส์เปเรซ

1
คุณถูกต้องและการสังเกตที่ดีนี้เน้นประเด็นหลักที่==ทำให้หลายสิ่งหลายอย่างทำให้เป็นเรื่องยากมากที่จะคาดการณ์ผลลัพธ์ในขณะที่===ตรงไปตรงมาและคาดการณ์ได้มากขึ้นซึ่งเป็นหนึ่งในเหตุผลหลัก===คือทางเลือกที่แนะนำ (ฉันจะเพิ่มข้อความในคำตอบที่กล่าวขวัญจุดของคุณ)
หลุยส์เปเรซ

81

===การตรวจสอบด้านเดียวมีค่าเท่ากันในประเภทเช่นเดียวกับค่า


ตัวอย่าง:

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

ตัวอย่างทั่วไป:

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

อีกตัวอย่างทั่วไป:

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

หลายครั้งที่untypedการตรวจสอบจะเป็นประโยชน์เพราะคุณไม่ดูแลถ้ามีค่าเป็นอย่างใดอย่างหนึ่งundefined, null, 0 หรือ""


7
ด้วย'string' !== 'number'
โฮเมอร์

71

แผนภาพการไหลของการเรียกใช้ Javascript สำหรับความเท่าเทียม / การเปรียบเทียบที่เข้มงวด '==='

จาวาสคริปต์ที่เท่าเทียมกันอย่างเข้มงวด

แผนภาพการไหลของการเรียกใช้ Javascript สำหรับความไม่เท่าเทียม / การเปรียบเทียบที่เข้มงวด '=='

Javascript ไม่เท่าเทียมกัน


ฉันไม่เข้าใจว่าทำไมstringลูกศรชี้ไปที่กล่องสีเทาขนาดใหญ่มันควรจะหมายความว่าผู้ขัดขวางกำลังส่งสตริงไปที่ตัวเลขหรือไม่
vsync

@vsync มันชี้ไปที่ตัวเลือกสตริงภายในกล่องสีเทาเช่นสตริง -> # || น่าน Javascript ไม่ใช่ภาษาสคริปต์ประเภทเช่นโดยทั่วไปจะมีตัวแปรชนิดใดก็ได้ ดังนั้นมันจึงชี้ไปที่กล่องสีเทานั้น
Samar Panda

ฉันเพียงแค่ถามว่ามันมีวัตถุประสงค์เพื่อการหล่อหรือไม่เนื่องจากstringควรจะเปรียบเทียบกับประเภทnumberดังนั้นผู้ขัดจังหวะจะดูว่าควรเปรียบเทียบสตริงอะไรและใช้สตริงนั้นหรือไม่
vsync

1
กล่องสีเทาขนาดใหญ่คือสิ่งที่ToNumberจะกลับมาเมื่อได้รับประเภทที่แตกต่างกันดังนั้นหากได้รับสตริงมันจะเลือกตัวเลือกสุดท้ายเท่านั้น (และแปลงเป็นตัวเลข) ==ใช้ToNumberเฉพาะในกรณีstring == numberหรือboolean == anythingสูงกว่า (และเฉพาะในstring/ boolean) วิธีนี้==จะไม่แปลงundefinedหรือnullแม้ว่าจะอยู่ในกล่องสีเทา (สำหรับการรวมกันของใด ๆundefinedหรือทั้งสองอย่างใดอย่างหนึ่งnull) ==จะกลับเสมอtrueนอกจากนี้ไม่ว่าค่าจะอยู่ทางด้านซ้ายหรือด้านขวาไม่สำคัญ==(และ===) จะส่งคืนผลลัพธ์เดียวกัน)
user2033427

55

JavaScript VS=== ==

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

มันหมายถึงความเท่าเทียมกันโดยไม่มีประเภทการข่มขู่การ ข่มขู่หมายความว่าจาวาสคริปต์จะไม่แปลงประเภทข้อมูลอื่น ๆ ให้เป็นประเภทข้อมูลสตริงโดยอัตโนมัติ

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

ในสคริปต์ทั่วไปจะไม่มีความแตกต่างด้านประสิทธิภาพ สำคัญกว่านั้นคือข้อเท็จจริงที่ว่าพัน "===" คือ 1 KB ที่หนักกว่าหนึ่งพัน "==" :) โปรไฟล์ของ JavaScriptสามารถบอกคุณได้ว่ามีความแตกต่างด้านประสิทธิภาพในกรณีของคุณหรือไม่

แต่โดยส่วนตัวฉันจะทำในสิ่งที่ JSLint แนะนำ คำแนะนำนี้ไม่ได้เกิดจากปัญหาประสิทธิภาพการทำงาน แต่เนื่องมาจากวิธีการข่มขู่ประเภท('\t\r\n' == 0)นั้นเป็นความจริง


4
ไม่จริงเสมอไป ด้วยการบีบอัด gzip ความแตกต่างจะเล็กน้อยมาก
Daniel X Moore

1
เห็นด้วย แต่พัน "===" หมายความว่ายังมีอีก 10 หมื่นบรรทัดโค้ดดังนั้น 1kb ไม่มากก็น้อย ... ;)
Jonny

f ที่เกี่ยวข้องกับขนาดของคุณจากนั้นเพียงแค่แลกเปลี่ยน == ทั้งหมดของคุณด้วย === จากนั้นใช้ regexp ที่ห่อหุ้มด้วย

46

ตัวดำเนินการเปรียบเทียบที่เท่ากัน == นั้นสับสนและควรหลีกเลี่ยง

หากคุณต้องอยู่กับมันให้จำสิ่งต่าง ๆ ดังต่อไปนี้:

  1. มันไม่ได้เป็นสกรรมกริยา: (a == b)และ(b == c)ไม่ได้นำไปสู่(a == c)
  2. มันไม่ได้เกิดจากการปฏิเสธ: (a == b)และ(a! = b)มักจะมีค่าบูลีนที่ตรงข้ามเสมอโดยมี a และ b ทั้งหมด
  3. ในกรณีที่มีข้อสงสัยให้เรียนรู้ด้วยใจตารางความจริงต่อไปนี้:

ตารางความจริงของผู้ดำเนินการเท่าใน JAVASCRIPT

  • แต่ละแถวในตารางเป็นชุดของค่า "เท่าเทียมกัน" 3 ค่าซึ่งหมายความว่า 2 ค่าใด ๆ ในหมู่พวกเขาจะเท่ากันโดยใช้เครื่องหมาย == เท่ากัน *

** STRANGE: โปรดทราบว่าค่าสองค่าใด ๆ ในคอลัมน์แรกนั้นไม่เท่ากัน **

''       == 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

ไม่น่าจะมีความแตกต่างด้านประสิทธิภาพระหว่างสองการดำเนินงานในการใช้งานของคุณ ไม่มีการแปลงประเภทที่ต้องทำเพราะพารามิเตอร์ทั้งคู่เป็นประเภทเดียวกันอยู่แล้ว การดำเนินการทั้งสองจะมีการเปรียบเทียบชนิดตามด้วยการเปรียบเทียบค่า


38

ใช่ มันสำคัญ.

===ผู้ประกอบการใน JavaScript มูลค่าการตรวจสอบรวมทั้งชนิดที่เป็น==ผู้ประกอบการเพียงแค่ตรวจสอบค่า (ไม่แปลงชนิดถ้าจำเป็น)

ป้อนคำอธิบายรูปภาพที่นี่

คุณสามารถทดสอบได้อย่างง่ายดาย วางรหัสต่อไปนี้ในไฟล์ HTML และเปิดในเบราว์เซอร์

<script>

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

</script>

</head>

<body onload='onPageLoad();'>

คุณจะได้รับ ' เท็จ ' ในการแจ้งเตือน ตอนนี้ปรับเปลี่ยนonPageLoad()วิธีการในการalert(x == 5);ที่คุณจะได้รับจริง


33

=== ผู้ประกอบการตรวจสอบค่าเช่นเดียวกับประเภทของตัวแปรเพื่อความเท่าเทียมกัน

== ผู้ประกอบการเพียงตรวจสอบค่าของตัวแปรเพื่อความเท่าเทียมกัน


32

เป็นการตรวจสอบที่เข้มงวด

มันเป็นสิ่งที่ดีโดยเฉพาะถ้าคุณตรวจสอบระหว่าง 0 กับเท็จและ null

ตัวอย่างเช่นถ้าคุณมี:

$a = 0;

แล้ว:

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

ผลตอบแทนทั้งหมดเป็นจริงและคุณอาจไม่ต้องการสิ่งนี้ สมมติว่าคุณมีฟังก์ชั่นที่สามารถส่งคืนดัชนี 0 ของอาเรย์หรือเท็จเมื่อล้มเหลว หากคุณตรวจสอบด้วย "==" false คุณสามารถรับผลลัพธ์ที่สับสนได้

ดังนั้นด้วยสิ่งเดียวกันข้างต้น แต่เป็นการทดสอบที่เข้มงวด:

$a = 0;

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

3
ใน JavaScript สิ่งนี้ผิดอย่างสมบูรณ์และไม่สมบูรณ์อย่างผิดพลาด 0 != null. -1
Ry-

31

บางครั้ง JSLint ให้เหตุผลที่ไม่สมจริงแก่คุณในการแก้ไขสิ่งต่างๆ ===มีประสิทธิภาพเหมือนกันทุกประการ==เหมือนกันทุกประการเหมือนกับประเภทเดียวกัน

จะเร็วกว่าก็ต่อเมื่อชนิดไม่เหมือนกันซึ่งในกรณีนี้จะไม่พยายามแปลงชนิด แต่คืนค่าเท็จโดยตรง

ดังนั้นIMHO JSLint อาจใช้เพื่อเขียนรหัสใหม่ แต่การหลีกเลี่ยงการเพิ่มประสิทธิภาพที่ไร้ประโยชน์ควรหลีกเลี่ยงค่าใช้จ่ายทั้งหมด

ความหมายมีเหตุผลที่จะไม่มีการเปลี่ยนแปลง==ไป===ในการตรวจสอบเช่นif (a == 'test')เมื่อคุณรู้ว่ามันเป็นความจริงที่ว่าสามารถเป็นสตริง

การแก้ไขโค้ดจำนวนมากทำให้เสียเวลาของนักพัฒนาและผู้ตรวจสอบและไม่ประสบความสำเร็จ


30

ง่ายดาย

==หมายถึงการเปรียบเทียบระหว่างตัวถูกดำเนินการกับ type conversion

&

===หมายถึงการเปรียบเทียบระหว่างตัวถูกดำเนินการโดยไม่ type conversion

การแปลงประเภทในจาวาสคริปต์หมายความว่าจาวาสคริปต์แปลงชนิดข้อมูลอื่น ๆ เป็นชนิดข้อมูลสตริงโดยอัตโนมัติ

ตัวอย่างเช่น:

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

ตัวอย่างง่ายๆคือ

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

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

25

คำตอบ 2 อันดับแรกทั้งที่กล่าวถึง == หมายถึงความเท่าเทียมกันและ === หมายถึงตัวตน น่าเสียดายที่ข้อความนี้ไม่ถูกต้อง

หากทั้งสองตัวถูกดำเนินการ == เป็นวัตถุแล้วพวกเขาจะถูกเปรียบเทียบเพื่อดูว่าพวกเขาเป็นวัตถุเดียวกัน หากตัวถูกดำเนินการทั้งสองชี้ไปที่วัตถุเดียวกันตัวดำเนินการที่เท่ากันจะคืนค่าเป็นจริง มิฉะนั้นทั้งสองจะไม่เท่ากัน

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

ในรหัสข้างต้นทั้ง == และ === ได้รับเท็จเพราะ a และ b ไม่ใช่วัตถุเดียวกัน

กล่าวคือถ้าตัวถูกดำเนินการทั้งสองของ == เป็นวัตถุ == จะทำงานเหมือนกับ === ซึ่งก็หมายถึงตัวตน ความแตกต่างที่สำคัญของผู้ให้บริการสองรายนี้คือการแปลงประเภท == มีการแปลงก่อนที่จะตรวจสอบความเท่าเทียมกัน แต่ === ไม่มี


24

ตามกฎของหัวแม่มือฉันมักจะใช้===แทน==(และ!==แทนที่จะเป็น!= )

เหตุผลอธิบายไว้ในคำตอบข้างต้นและ Douglas Crockford ค่อนข้างชัดเจนเกี่ยวกับเรื่องนี้ ( JavaScript: The Good Parts )

อย่างไรก็ตามมีข้อยกเว้นเดียวข้อเดียว : == nullเป็นวิธีที่มีประสิทธิภาพในการตรวจสอบ 'เป็นโมฆะหรือไม่ได้กำหนด':

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

ตัวอย่างเช่น jQuery 1.9.1 ใช้รูปแบบนี้ 43 ครั้งและตัวตรวจสอบไวยากรณ์ JSHintยังมีeqnullตัวเลือกที่ผ่อนคลายสำหรับเหตุผลนี้

จากคู่มือสไตล์ jQuery :

ควรใช้การตรวจสอบความเท่าเทียมกันอย่างเข้มงวด (===) == ข้อยกเว้นเพียงอย่างเดียวคือเมื่อตรวจสอบ undefined และ null โดยวิธี null

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

22

ปัญหาคือคุณอาจเจอปัญหาได้ง่ายเนื่องจาก JavaScript มีการแปลงโดยนัยมากมายหมายถึง ...

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

ซึ่งในไม่ช้าก็กลายเป็นปัญหา ตัวอย่างที่ดีที่สุดว่าทำไมการแปลงโดยนัยคือ "ความชั่วร้าย" สามารถนำมาจากรหัสนี้ในMFC / C ++ ซึ่งจริง ๆ แล้วจะรวบรวมเนื่องจากการแปลงโดยนัยจาก CString เป็น HANDLE ซึ่งเป็นประเภท typedef ตัวชี้ ...

CString x;
delete x;

ซึ่งเห็นได้ชัดในช่วง Runtime ไม่มากไม่ได้กำหนดสิ่งที่ ...

Google สำหรับการแปลงโดยนัยใน C ++ และSTLเพื่อให้ได้ข้อโต้แย้งบางส่วน ...


2
0 == nullเป็นเท็จ
Garrett


21

การเปรียบเทียบความเท่าเทียมกัน:

ผู้ประกอบการ ==

ผลตอบแทนจริงเมื่อตัวถูกดำเนินการทั้งสองเท่ากัน ตัวถูกดำเนินการจะถูกแปลงเป็นประเภทเดียวกันก่อนที่จะถูกเปรียบเทียบ

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

ความเท่าเทียมกันและการเปรียบเทียบประเภท:

ผู้ประกอบการ ===

ผลตอบแทนจริงถ้าตัวถูกดำเนินการทั้งสองเท่ากันและประเภทเดียวกัน โดยทั่วไปแล้วจะดีกว่าและปลอดภัยกว่าถ้าคุณเปรียบเทียบวิธีนี้เนื่องจากไม่มีการแปลงประเภทเบื้องหลัง

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

20

นี่คือตารางเปรียบเทียบประโยชน์ที่แสดงให้เห็นว่าการแปลงที่เกิดขึ้นและความแตกต่างระหว่างและ=====

ในขณะที่ข้อสรุปฯ :

"ใช้สามเท่ากับถ้าคุณไม่เข้าใจการแปลงที่เกิดขึ้นสำหรับสองเท่ากับ"

http://dorey.github.io/JavaScript-Equality-Table/


20

โมฆะและไม่ได้กำหนดคือความว่างเปล่านั่นคือ

var a;
var b = null;

ที่นี่aและbไม่มีค่า โดยที่ 0, false และ '' เป็นค่าทั้งหมด สิ่งหนึ่งที่พบเห็นได้ทั่วไปคือสิ่งเหล่านี้ล้วนเป็นคุณค่าที่ไม่แน่นอนซึ่งหมายความว่าพวกเขาพึงพอใจเงื่อนไข falsy

ดังนั้น 0, false และ '' รวมกันเป็นกลุ่มย่อย ในทางกลับกัน null & ไม่ได้กำหนดในกลุ่มย่อยที่สอง ตรวจสอบการเปรียบเทียบในภาพด้านล่าง null และ undefined จะเท่ากัน อีกสามคนจะเท่ากับซึ่งกันและกัน แต่พวกเขาทั้งหมดจะถือว่าเป็นเงื่อนไขที่ผิดพลาดใน JavaScript

ป้อนคำอธิบายภาพที่นี่

สิ่งนี้เหมือนกับวัตถุใด ๆ (เช่น {}, อาร์เรย์, ฯลฯ ), สตริงที่ไม่ว่าง & บูลีนจริงเป็นเงื่อนไขจริงทั้งหมด แต่พวกเขาทั้งหมดไม่เท่ากัน

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.