การใช้ == ใน JavaScript นั้นสมเหตุสมผลหรือไม่?


276

ในJavaScript ส่วนที่ดี Douglas Crockford เขียนว่า:

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กับ===ผู้ประกอบการ

จากการสังเกตอย่างแจ่มแจ้งนี้จะมีเวลาเมื่อใช้งาน==จริงหรือไม่


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

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

4
ฉันไม่คิดว่า JavaScript ไปไกลพอกับการข่มขู่ประเภท ควรมีตัวเลือกประเภทการข่มขู่เพิ่มเติมเช่นเดียวกับภาษาBS
มาร์คมาร์บูธ

5
ที่เดียวที่ฉันใช้ == คือเมื่อเปรียบเทียบ id แบบดรอปดาวน์ (ซึ่งเป็นถ่านเสมอ) กับ id ของรุ่น (ซึ่งเป็น int ทั่วไป)
Scottie

12
การพัฒนาเว็บ @DevSolar เหมาะสมเมื่อคุณไม่ต้องการที่จะจัดการกับการผลิตแอพแบบดั้งเดิมสำหรับแต่ละแพลตฟอร์ม 15 แพลตฟอร์มรวมถึงการรับรอง App Store ที่ผูกขาดของแต่ละแพลตฟอร์มที่มี
Damian Yerrick

คำตอบ:


232

ฉันจะโต้แย้ง ==

Douglas Crockford ที่คุณอ้างถึงมีชื่อเสียงในเรื่องความคิดเห็นมากมายและเป็นประโยชน์อย่างมากของเขา ในขณะที่ฉันอยู่กับ Crockford ในกรณีนี้มันคุ้มค่าที่จะกล่าวถึงไม่ใช่ความคิดเห็นเดียว มีคนอื่น ๆ เช่นภาษาเบรนแดนผู้สร้าง Eich ==ที่ไม่เห็นปัญหาใหญ่ที่มีอยู่ อาร์กิวเมนต์มีลักษณะดังนี้:

JavaScript เป็นภาษาที่พิมพ์ตามพฤติกรรม ทุกสิ่งได้รับการปฏิบัติตามสิ่งที่พวกเขาสามารถทำได้และไม่ใช่ประเภทที่แท้จริง นี่คือเหตุผลที่คุณสามารถเรียกใช้.mapเมธอดของอาร์เรย์บน NodeList หรือในชุดการเลือก jQuery นอกจากนี้ยังเป็นสาเหตุที่คุณสามารถทำได้3 - "5"และรับสิ่งที่มีความหมายกลับมาเพราะ "5" สามารถทำตัวเหมือนตัวเลขได้

เมื่อคุณทำการ==เท่าเทียมกันคุณกำลังเปรียบเทียบเนื้อหาของตัวแปรมากกว่าของประเภท นี่คือบางกรณีที่มีประโยชน์:

  • อ่านตัวเลขจากผู้ใช้ - อ่าน.valueองค์ประกอบอินพุตใน DOM หรือไม่ ไม่มีปัญหา! คุณไม่จำเป็นต้องเริ่มต้นแคสติ้งหรือกังวลเกี่ยวกับประเภทของมันคุณสามารถทำได้==ทันทีกับตัวเลข
  • ต้องการตรวจสอบ "การมีอยู่" ของตัวแปรที่ประกาศหรือไม่? - คุณทำได้== nullตั้งแต่nullแสดงพฤติกรรมไม่มีอะไรที่นั่นและไม่ได้กำหนดไม่ได้มีอะไรทั้ง
  • ต้องการตรวจสอบว่าคุณได้รับข้อมูลที่มีความหมายจากผู้ใช้หรือไม่? - ตรวจสอบว่าอินพุตเป็นเท็จด้วยการ==โต้แย้งมันจะรักษากรณีที่ผู้ใช้ไม่ได้ป้อนอะไรหรือเพียงแค่พื้นที่สีขาวสำหรับคุณซึ่งอาจเป็นสิ่งที่คุณต้องการ

ลองดูตัวอย่างของ Crockford และอธิบายพฤติกรรม:

'' == '0'           // got input from user vs. didn't get input - so false
0 == ''             // number representing empty and string representing empty - so true
0 == '0'            // these both behave as the number 0 when added to numbers - so true    
false == 'false'    // false vs got input from user which is truthy - so false
false == '0'        // both can substitute for 0 as numbers - so again true

false == undefined  // having nothing is not the same as having a false value - so false
false == null       // having empty is not the same as having a false value - so false
null == undefined   // both don't represent a value - so true

' \t\r\n ' == 0     // didn't get meaningful input from user vs falsey number - true 

โดยทั่วไป==ถูกออกแบบมาเพื่อการทำงานขึ้นอยู่กับวิธีวิทยาการประพฤติใน JavaScript ไม่ขึ้นอยู่กับสิ่งที่พวกเขามี แม้ว่าฉันจะไม่เห็นด้วยกับมุมมองนี้ แต่ก็มีข้อดีในการทำเช่นนี้ - โดยเฉพาะอย่างยิ่งถ้าคุณใช้กระบวนทัศน์ประเภทนี้ในการรักษาตามพฤติกรรมของภาษา

* บางคนอาจชอบพิมพ์ชื่อโครงสร้างซึ่งเป็นเรื่องธรรมดา แต่มีความแตกต่าง - ไม่สนใจพูดถึงความแตกต่างที่นี่จริงๆ


8
นี่เป็นคำตอบที่ดีมากและฉันใช้ทั้งสามกรณีของคุณสำหรับ == 'กรณีการใช้งาน # 1 & # 3 มีประโยชน์อย่างยิ่ง
Chris Cirefice

224
ปัญหาที่เกิดขึ้น==ไม่ใช่ว่าไม่มีการเปรียบเทียบใด ๆ ที่เป็นประโยชน์มันเป็นไปไม่ได้ที่จะจำกฎดังนั้นคุณเกือบจะรับประกันว่าจะทำผิดพลาด ตัวอย่างเช่น: "ต้องการตรวจสอบว่าคุณได้รับข้อมูลที่มีความหมายจากผู้ใช้หรือไม่" แต่ '0' เป็นข้อมูลที่มีความหมายและ'0'==falseเป็นจริง หากคุณเคยใช้===คุณจะต้องคิดอย่างชัดเจนและคุณจะไม่ทำผิด
Timmmm

44
"กฎเป็นไปไม่ได้ที่จะจำ" <== นี่เป็นสิ่งหนึ่งที่ทำให้ฉันกลัวที่จะไม่ทำอะไร "มีความหมาย" ใน Javascript (และลอยคณิตศาสตร์ที่นำไปสู่ปัญหาในการออกกำลังกาย
คำนวณ

9
3 - "5"ตัวอย่างเช่นยกเป็นจุดที่ดีในตัวเอง: แม้ว่าคุณจะใช้เฉพาะ===สำหรับการเปรียบเทียบว่าเป็นเพียงตัวแปรวิธีการทำงานใน Javascript ไม่มีทางหนีรอดไปได้อย่างสมบูรณ์
Jarett Millard

23
@ Timmmm note ฉันเล่นเป็นผู้สนับสนุนของปีศาจที่นี่ ฉันไม่ได้ใช้==ในรหัสของตัวเองฉันคิดว่ามันเป็นรูปแบบการต่อต้านและฉันเห็นด้วยอย่างยิ่งว่าอัลกอริธึมความเท่าเทียมกันทางนามธรรมยากที่จะจำ สิ่งที่ฉันทำที่นี่คือการทำให้ผู้คนโต้แย้งกัน
Benjamin Gruenbaum

95

ปรากฎว่า jQuery ใช้โครงสร้าง

if (someObj == null) {
  // do something
}

อย่างกว้างขวางเป็นชวเลขสำหรับรหัสเทียบเท่า:

if ((someObj === undefined) || (someObj === null))  {
  // do something
}

นี่คือผลของข้อกำหนดทางภาษา ECMAScript § 11.9.3, อัลกอริธึมการเปรียบเทียบความเท่าเทียมกันทางนามธรรมซึ่งระบุในสิ่งอื่น ๆ

1.  If Type(x) is the same as Type(y), then  
    a.  If Type(x) is Undefined, return true.  
    b.  If Type(x) is Null, return true.

และ

2.  If x is null and y is undefined, return true.
3.  If x is undefined and y is null, return true.

เทคนิคเฉพาะนี้เป็นเรื่องธรรมดามากที่JSHintมีธงที่ออกแบบมาเป็นพิเศษ


10
ไม่มีคำตอบที่ยุติธรรมสำหรับคำถามของคุณเองฉันต้องการตอบคำถามนี้ :) == null or undefinedเป็นที่เดียวที่ฉันไม่ได้ใช้===หรือ!==
pllee

26
เพื่อความยุติธรรม jQuery นั้นแทบจะไม่ได้เป็น codebase ของโมเดลเลย ต้องอ่านแหล่ง jQuery หลายครั้งมันเป็นหนึ่งในฐานโค้ดที่ฉันโปรดปรานน้อยที่สุดที่มีเทอร์เทิร์นซ้อนซ้อนบิตไม่ชัดเจนบิตซ้อนและสิ่งต่าง ๆ ที่ฉันจะหลีกเลี่ยงในโค้ดจริง อย่าใช้คำของฉันเลย - อ่านมันgithub.com/jquery/jquery/tree/master/srcแล้วเปรียบเทียบกับ Zepto ซึ่งเป็นโคลน jQuery: github.com/madrobby/zepto/tree/master/src
Benjamin Gruenbaum

4
โปรดทราบด้วยว่า Zepto นั้นดูเหมือนว่าจะเป็นค่าเริ่มต้น==และใช้เฉพาะ===ในกรณีที่จำเป็นเท่านั้น: github.com/madrobby/zepto/blob/master/src/event.js
เฮ้

2
@Hey ที่จะยุติธรรม Zepto นั้นแทบจะไม่ได้เป็น codebase ของรุ่น แต่อย่างใด - มันน่าอับอายสำหรับการใช้งาน__proto__และบังคับให้มันเกือบจะเป็นหนึ่งเดียวในการกำหนดภาษาเพื่อหลีกเลี่ยงการทำลายเว็บไซต์มือถือ
Benjamin Gruenbaum

2
@BenjaminGruenbaum ที่ไม่ได้เป็นการเรียกร้องให้ตัดสินคุณภาพของ codebase ของพวกเขาเพียงแค่ชี้ให้เห็นว่าโครงการต่าง ๆ เป็นไปตามอนุสัญญาที่แตกต่างกัน
เฮ้

15

การตรวจสอบค่าสำหรับnullหรือundefinedเป็นสิ่งหนึ่งตามที่ได้รับการอธิบายอย่างมากมาย

มีอีกอย่างที่==ส่อง:

คุณสามารถกำหนดการเปรียบเทียบได้จากสิ่งที่>=ชอบ (คนมักจะเริ่มจาก>แต่ฉันพบว่ามันดูหรูหรากว่านี้):

  • a > b <=> a >= b && !(b >= a)
  • a == b <=> a >= b && b >= a
  • a < bและa <= bถูกทิ้งไว้เป็นแบบฝึกหัดให้ผู้อ่าน

ที่เรารู้ว่าใน JavaScript "3" >= 3และจากการที่คุณได้รับ"3" <= 3 3 == "3"คุณสามารถชี้ให้เห็นว่าเป็นความคิดที่น่ากลัวที่จะอนุญาตให้ทำการเปรียบเทียบระหว่างสตริงและตัวเลขโดยการแยกสตริง แต่ให้ที่นี้เป็นวิธีการทำงาน==เป็นอย่างวิธีที่ถูกต้องในการดำเนินการว่าผู้ประกอบการมีความสัมพันธ์

ดังนั้นสิ่งที่ดีจริง ๆ ก็==คือมันสอดคล้องกับความสัมพันธ์อื่น ๆ ทั้งหมด หากต้องการเขียนให้แตกต่างกันถ้าคุณเขียนสิ่งนี้:

function compare(a, b) {
  if (a > b) return 1;
  if (a < b) return -1;
  return 0;
}

คุณใช้งานโดยปริยาย==แล้ว

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

  • แอตทริบิวต์เป็นสตริงเสมอ
  • คีย์เป็นสตริงเสมอ (กรณีการใช้งานที่คุณใช้Objectเพื่อให้มีแผนที่ห่างจาก ints เป็นค่า)
  • อินพุตของผู้ใช้และค่าการควบคุมฟอร์มเป็นสตริงเสมอ (แม้ว่าแหล่งที่มาตรงกันinput[type=number])

ด้วยเหตุผลทั้งหมดที่ทำให้เหมาะสมกับการทำให้สตริงทำงานเหมือนตัวเลขเมื่อต้องการ และสมมติว่าการเปรียบเทียบสตริงและการต่อสตริงมีตัวดำเนินการแตกต่างกัน (เช่น::สำหรับการเรียงและวิธีการเปรียบเทียบ (ซึ่งคุณสามารถใช้พารามิเตอร์ทุกชนิดเกี่ยวกับความไวของตัวพิมพ์เล็กและตัวพิมพ์เล็ก)) อันที่จริงแล้วจะไม่ยุ่งเหยิง แต่ตัวดำเนินการโอเวอร์โหลดนี้อาจเป็นความจริงที่ว่า "Java" ใน "JavaScript" มาจาก;)


4
ความยุติธรรม>=ไม่ได้เป็นสกรรมกริยาจริงๆ มันเป็นไปได้มากทีเดียวใน JS ว่าไม่ว่าa > bมิได้a < bมิได้b == a(ตัวอย่างเช่น: NaN)
Benjamin Gruenbaum

8
@BenjaminGruenbaum: นั่นก็เหมือนกับการพูดว่า+ไม่ใช่การสลับสับเปลี่ยนเพราะNaN + 5 == NaN + 5ไม่ได้ถือ ประเด็นก็คือ>=ทำงานได้กับค่า number-ish ซึ่ง==ทำงานได้อย่างต่อเนื่อง ไม่น่าแปลกใจที่ "ไม่ใช่ตัวเลข" คือโดยธรรมชาติแล้วไม่ใช่ number-ish;)
back2dos

4
ดังนั้นพฤติกรรมที่ไม่ดีของ==สอดคล้องกับพฤติกรรมที่ไม่ดีของ>=? เยี่ยมมากตอนนี้ฉันหวังว่าจะมี>==...
Eldritch Conundrum

2
@EldritchConundrum: ขณะที่ฉันพยายามอธิบายพฤติกรรมของ>=ค่อนข้างสอดคล้องกับส่วนที่เหลือของภาษา / API มาตรฐาน ในจำนวนทั้งสิ้น, JavaScript จัดการให้มากกว่าผลรวมของชิ้นส่วนที่แปลกประหลาด หากคุณต้องการคุณ>==จะต้องการเข้มงวด+หรือไม่ ในทางปฏิบัติการตัดสินใจหลายอย่างทำให้ง่ายขึ้นมาก ดังนั้นฉันจะไม่รีบตัดสินพวกเขาจนเป็นคนจน
back2dos

2
@EldritchConundrum: อีกครั้ง: ตัวดำเนินการความสัมพันธ์หมายถึงการเปรียบเทียบค่าตัวเลขโดยที่หนึ่งตัวถูกดำเนินการอาจเป็นสตริง สำหรับประเภทตัวถูกดำเนินการที่>=มีความหมายมีความหมาย==เท่ากันนั่นคือทั้งหมด ไม่มีใครบอกว่าคุณควรจะเปรียบเทียบกับ[[]] falseในภาษาอย่าง C ผลลัพธ์ของการไร้สาระระดับนี้เป็นพฤติกรรมที่ไม่ได้กำหนด เพียงทำแบบเดียวกัน: อย่าทำ และคุณจะสบายดี คุณไม่จำเป็นต้องจำกฎเวทมนต์ใด ๆ แล้วมันก็ค่อนข้างตรงไปตรงมา
back2dos

8

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

==ไม่ได้สะท้อน :

A == A อาจเป็นเท็จเช่น

NaN == NaN // false

==ไม่ใช่สกรรมกริยา :

A == BและB == Cกันไม่ได้หมายความว่าA == Cเช่น

'1' == 1 // true
1 == '01' // true
'1' == '01' // false

สถานที่ให้บริการสมมาตรเท่านั้นที่รอดชีวิต:

A == Bบอกเป็นนัยว่าB == Aการละเมิดใดที่ไม่อาจคิดได้ในกรณีใด ๆ และอาจนำไปสู่การกบฏที่ร้ายแรง;)

ทำไมความสัมพันธ์ที่เท่าเทียมกันมีความสำคัญ?

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

เหตุใดจึงเป็นความคิดที่น่ากลัวที่จะเขียน==เพื่อความสัมพันธ์ที่ไม่เท่าเทียมกัน?

เพราะมันทำให้ความคุ้นเคยและสัญชาตญาณของเราแตกต่างกันไปตามความสัมพันธ์ที่น่าสนใจของความคล้ายคลึงกันความเท่าเทียมความสมภาคกันความสมมาตรมอร์ฟิซึ่มซเอกลักษณ์อื่น ๆ คือความเท่าเทียมกัน

การแปลงประเภท

แทนที่จะอาศัยความเท่าเทียมที่ใช้งานง่ายJavaScriptแนะนำการแปลงประเภท:

ตัวดำเนินการความเท่าเทียมกันจะแปลงตัวถูกดำเนินการหากพวกมันไม่ใช่ประเภทเดียวกันดังนั้นจึงใช้การเปรียบเทียบที่เข้มงวด

แต่การแปลงประเภทกำหนดไว้อย่างไร? ผ่านชุดของกฎที่ซับซ้อนที่มีข้อยกเว้นมากมายใช่ไหม

พยายามสร้างความสัมพันธ์ที่เท่าเทียมกัน

booleans ชัดเจนtrueและfalseไม่เหมือนกันและควรอยู่ในคลาสที่แตกต่างกัน

เบอร์ โชคดีที่ความเท่าเทียมกันของตัวเลขนั้นถูกนิยามไว้อย่างดีแล้วซึ่งตัวเลขที่แตกต่างกันสองตัวนั้นไม่เคยอยู่ในระดับความเท่ากัน ในวิชาคณิตศาสตร์นั่นก็คือ ใน JavaScript ความคิดของจำนวนที่มีรูปร่างผิดปกติค่อนข้างผ่านการปรากฏตัวของแปลกใหม่มากขึ้น-0, และInfinity -Infinityสัญชาตญาณทางคณิตศาสตร์ของเราบอกว่า0และ-0ควรอยู่ในระดับเดียวกัน (ในความ-0 === 0เป็นจริงtrue) ในขณะที่แต่ละ infinities เป็นชั้นแยก

ตัวเลขและบูลีน เมื่อกำหนดจำนวนคลาสเราจะวางบูลีนที่ไหน falseกลายเป็นคล้ายกับ0ในขณะที่trueกลายเป็นคล้ายกับ1แต่ไม่มีหมายเลขอื่น ๆ :

true == 1 // true
true == 2 // false

มีเหตุผลอะไรบ้างที่จะนำมาtrueรวมกับ1? เป็นที่ยอมรับ1มีความโดดเด่น แต่ก็เป็น-1เช่นนั้น ผมเองไม่เห็นเหตุผลใด ๆ ที่จะแปลงไปtrue1

และมันยิ่งแย่ลงไปอีก:

true + 2 // 3
true - 1 // 0

ดังนั้นtrueจะถูกแปลงเป็น1ตัวเลขทั้งหมด! มันเป็นตรรกะหรือไม่ มันใช้งานง่าย? คำตอบที่เหลือคือการออกกำลังกาย;)

แต่สิ่งที่เกี่ยวกับเรื่องนี้:

1 && true // true
2 && true // true

บูลีนเพียงxกับx && trueความเป็นอยู่คือtrue x = trueซึ่งพิสูจน์ได้ว่าทั้งสอง1และ2(และหมายเลขอื่น ๆ0) แปลงเป็นtrue! สิ่งที่มันแสดงให้เห็นว่าการแปลงของเราล้มเหลวคุณสมบัติที่สำคัญอื่น - เป็นbijection หมายความว่าเอนทิตีที่แตกต่างกันสองรายการสามารถแปลงเป็นเอนทิตีเดียวกันได้ ซึ่งโดยตัวของมันเองไม่จำเป็นต้องเป็นปัญหาใหญ่ ปัญหาใหญ่เกิดขึ้นเมื่อเราใช้การแปลงนี้เพื่ออธิบายความสัมพันธ์ของ "ความเหมือน" หรือ "ความเท่าเทียมกันหลวม" ของสิ่งที่เราต้องการเรียกมันว่า แต่สิ่งหนึ่งที่ชัดเจน - มันจะไม่เป็นความสัมพันธ์ที่เท่าเทียมกันและมันจะไม่อธิบายอย่างสังหรณ์ใจผ่านคลาสที่เท่าเทียมกัน

แต่เราทำได้ดีกว่าได้ไหม

อย่างน้อยทางคณิตศาสตร์ - ใช่แน่นอน! ความสัมพันธ์ที่เท่าเทียมกันง่ายในหมู่ booleans และตัวเลขจะสร้างมีเพียงfalseและ0อยู่ในระดับเดียวกัน ดังนั้นfalse == 0จะเป็นเพียงความเท่าเทียมกันหลวมที่ไม่น่ารำคาญ

แล้วสตริงล่ะ?

เราสามารถตัดสตริงจาก whitespaces ที่จุดเริ่มต้นและจุดสิ้นสุดเพื่อแปลงเป็นตัวเลขได้เช่นกันเราสามารถละเว้นเลขศูนย์หน้าได้:

'   000 ' == 0 // true
'   0010 ' == 10 // true

ดังนั้นเราจึงได้กฎง่าย ๆ สำหรับสตริง - ตัดช่องว่างและเลขศูนย์ด้านหน้า เราจะได้จำนวนหรือสตริงว่างซึ่งในกรณีนี้เราแปลงเป็นตัวเลขหรือศูนย์ หรือเราไม่ได้ตัวเลขซึ่งในกรณีนี้เราไม่ได้รับการแปลงและดังนั้นจึงไม่มีความสัมพันธ์ใหม่

วิธีนี้เราสามารถได้รับความสัมพันธ์ที่สมบูรณ์แบบจริง ๆ ในชุดบูลีน, ตัวเลขและสตริงทั้งหมด! ยกเว้นว่า ... ผู้ออกแบบ JavaScript มีความคิดเห็นอื่นอย่างชัดเจน:

' ' == '' // false

ดังนั้นทั้งสองสายที่ทั้งคู่เปลี่ยนไปใน0ทันทีก็ไม่เหมือนกัน! ทำไมหรือเพราะอะไร ตามกฎแล้วสตริงจะเท่ากันอย่างแม่นยำเมื่อพวกเขาเท่ากันอย่างเคร่งครัด! ไม่เพียง แต่กฏนี้จะทำลายทรานสวิฟท์ตามที่เราเห็น แต่ยังเป็นกฎซ้ำซ้อน! จุดประสงค์ในการสร้างโอเปอเรเตอร์อื่น==เพื่อให้เหมือนกันกับโอเปอเรเตอร์อื่นอย่างเคร่งครัด===คืออะไร

ข้อสรุป

ตัวดำเนินการความเสมอภาคแบบหลวม==อาจมีประโยชน์มากถ้ามันปฏิบัติตามกฎทางคณิตศาสตร์พื้นฐานบางอย่าง แต่เนื่องจากมันไม่ได้น่าเศร้า


เกี่ยวกับNaNอะไร นอกจากนี้หากมีการบังคับใช้รูปแบบตัวเลขที่เฉพาะเจาะจงสำหรับการเปรียบเทียบกับสตริงการเปรียบเทียบสตริงที่ไม่ได้ใช้งานง่ายหรือไม่ส่งผลจะต้องส่งผล
โซโลมอน Ucko

@SolomonUcko NaNทำหน้าที่เป็นพลเมืองที่ไม่ดี :-) Transivity สามารถและควรได้รับการรักษาสำหรับการเปรียบเทียบความเท่าเทียมกันใด ๆ ที่ใช้งานง่ายหรือไม่
Dmitri Zaitsev

7

ใช่ฉันเคยใช้งานกรณีการใช้งานนั่นคือเมื่อคุณเปรียบเทียบคีย์กับค่าตัวเลข:

for (var key in obj) {
    var some_number = foo(key, obj[key]);  // or whatever -- this is just an example
    if (key == some_number) {
        blah();
    }
}

ฉันคิดว่ามันมากเป็นธรรมชาติมากขึ้นในการดำเนินการเปรียบเทียบเป็นkey == some_numberมากกว่าที่จะเป็นหรือเป็นNumber(key) === some_numberkey === String(some_number)


3

วันนี้ฉันเจอแอพพลิเคชั่นที่มีประโยชน์มาก หากคุณต้องการเปรียบเทียบจำนวนเบาะเช่นเดียว01กับจำนวนเต็มปกติ==ทำงานได้ดี ตัวอย่างเช่น:

'01' == 1 // true
'02' == 1 // false

มันช่วยให้คุณลบ 0 และแปลงเป็นจำนวนเต็ม


4
ฉันค่อนข้างมั่นใจว่าวิธีที่ 'ถูกต้อง' ในการทำเช่นนี้คือ'04'-0 === 4หรือเป็นไปได้parseInt('04', 10) === 4
ratbum

ฉันไม่ทราบว่าคุณสามารถทำได้
Jon Snow

7
ฉันได้รับมาก
Jon Snow

1
@ratbum or+'01' === 1
Eric Lagergren

1
'011' == 011 // falseในโหมดที่ไม่เข้มงวดและ SyntaxError ในโหมดเข้มงวด :)
Brian S

3

ฉันรู้ว่านี่เป็นคำตอบที่ล่าช้า แต่ดูเหมือนจะมีความสับสนที่เป็นไปได้เกี่ยวกับnullและundefinedซึ่ง IMHO เป็นสิ่งที่ทำให้เกิด==ความชั่วร้ายมากขึ้นเพื่อที่จะขาดความคล่องตัวซึ่งไม่ดีพอ พิจารณา:

p1.supervisor = 'Alice';
p2.supervisor = 'None';
p3.supervisor = null;
p4.supervisor = undefined;

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

  • p1 มีหัวหน้างานที่มีชื่อว่า "Alice"
  • p2 มีหัวหน้างานที่มีชื่อว่า "ไม่มี"
  • p3อย่างชัดเจนแจ่มแจ้งไม่ได้มีผู้บังคับบัญชา
  • p4อาจหรืออาจมีหัวหน้างาน เราไม่รู้เราไม่สนใจเราไม่ควรรู้ (ปัญหาความเป็นส่วนตัวหรือไม่) เนื่องจากไม่มีธุรกิจของเรา

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

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

ตอนนี้โดยวิธีที่ฉันไม่มีปัญหากับnullและundefinedทั้งสองเป็นเท็จ! มันก็โอเคที่จะพูดอย่างสมบูรณ์แบบ

if (p.supervisor) { ... }

จากนั้นnullและundefinedจะทำให้โค้ดที่ประมวลผลหัวหน้างานถูกข้ามไป ถูกต้องเพราะเราไม่รู้หรือไม่มีหัวหน้างาน ทั้งหมดดี. แต่ทั้งสองสถานการณ์จะไม่เท่ากัน นี่คือเหตุผลที่==ผิด อีกครั้งสิ่งต่าง ๆ อาจผิดพลาดและใช้ในความรู้สึกในการพิมพ์เป็ดซึ่งยอดเยี่ยมสำหรับภาษาแบบไดนามิก มันเป็น JavaScript, Pythonic, Rubyish ที่เหมาะสม ฯลฯ แต่อีกครั้งสิ่งเหล่านี้ไม่เท่ากัน

และไม่ได้รับฉันเริ่มต้นที่ไม่กริยา: "0x16" == 10, แต่ไม่10 == "10" "10" == "0x16"ใช่จาวาสคริปต์เป็นประเภทที่ไม่รุนแรง ใช่มันเป็นการบีบบังคับ แต่การข่มขู่ไม่ควรนำไปใช้กับความเสมอภาค

อย่างไรก็ตาม Crockford มีความคิดเห็นที่ดี แต่คุณรู้อะไรไหม? เขาถูกต้องที่นี่!

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

TL; DR: ความผิดพลาดเป็นแนวคิดที่ยอดเยี่ยม ไม่ควรขยายสู่ความเท่าเทียมกัน


ขอบคุณที่แสดงสถานการณ์ต่าง ๆ :) อย่างไรก็ตามคุณหายไปp5... สถานการณ์หนึ่งtypeof(p5.supervisor) === typeof(undefined)ที่ซึ่งผู้บังคับบัญชาไม่ได้มีอยู่ในแนวคิด: D
TheCatWhisperer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.