JSLint คาดหวัง '===' และเห็น '==' แทน


90

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

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

คำว่า "คาดว่า" จะบ่งบอกว่าควรทำทุกครั้ง ..... นั่นคือสิ่งที่ไม่สมเหตุสมผลสำหรับฉัน


7
ฉันก็เจอกับ JSLint เช่นกัน ฉันทำการอัปเดตจาก == เป็น === และมันทำให้โค้ดที่ใช้งานได้ก่อนหน้านี้พังจริง
kemiller2002

5
ถ้ารหัสของคุณมีมากกว่า 100 บรรทัดมันจะไม่ผ่าน jslint จริงๆมันเป็นไปไม่ได้

3
"ยากจน" เป็นคำที่รุนแรงเกินไป มันเปลี่ยนความหมายของรหัสของคุณ หากคุณกำลังทำการmyVar == nullตรวจสอบใช่การเปลี่ยนแปลงครั้งใหญ่ ; ^) ข้อโต้แย้งของ Crockford คือทำให้ความหมายของรหัสแม่นยำยิ่งขึ้นและยากที่จะโต้แย้ง
ruffin

คำตอบ:


127

IMO โดยใช้สุ่มสี่สุ่มห้าโดย===ไม่พยายามทำความเข้าใจว่าการแปลงประเภททำงานอย่างไรไม่สมเหตุสมผล

ความกลัวหลักเกี่ยวกับตัวดำเนินการ Equals ==คือกฎการเปรียบเทียบที่ขึ้นอยู่กับประเภทที่เปรียบเทียบสามารถทำให้ตัวดำเนินการไม่สกรรมกริยาตัวอย่างเช่นถ้า:

A == B AND
B == C

ไม่รับประกันว่า:

A == C

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

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

ตัวดำเนินการ Strict Equals ===ไม่จำเป็นจริงๆเมื่อคุณเปรียบเทียบค่าประเภทเดียวกันตัวอย่างที่พบบ่อยที่สุด:

if (typeof foo == "function") {
  //..
}

เราเปรียบเทียบผลลัพธ์ของตัวtypeofดำเนินการซึ่งมักจะเป็นสตริงกับสตริงลิเทอรัล ...

หรือเมื่อคุณทราบกฎการบังคับประเภทเช่นตรวจสอบว่ามีบางสิ่งnullหรือundefinedบางสิ่ง:

if (foo == null) {
  // foo is null or undefined
}

// Vs. the following non-sense version:

if (foo === null || typeof foo === "undefined") {
  // foo is null or undefined
}

1
ฉันเกลียดกฎของ JSLint ฉันคิดว่าปัญหาที่แท้จริงคือคนไม่ควรใช้ตัวดำเนินการในรูปแบบที่พวกเขาไม่เข้าใจ (แดกดันพวกนี้มักจะเป็นคนประเภทเดียวกันที่จะแทนที่ '===' ด้วย '==') แน่นอนว่ามีบางกรณีตามปกติที่เกิดขึ้นเมื่อเปรียบเทียบหมายเลข 0 กับสตริงต่างๆ แต่ถ้าคุณเปรียบเทียบข้อมูลที่ไม่เกี่ยวข้องเช่น 0 == 'นี่คือสตริง' - โค้ดของคุณอาจมีปัญหาใหญ่กว่าสองเท่า! หากคุณรู้แน่ชัดว่าคุณกำลังจัดการกับประเภทใดและคุณรู้ว่าพวกเขาโต้ตอบกับ == อย่างไรฉันคิดว่าคุณควรใช้มัน
จอน

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

2
ฉันพบว่าการเปรียบเทียบค่าโมฆะ == แทบจะเป็นสิ่งสำคัญ ปัญหาจะมีความสำคัญน้อยลงหากโค้ดของคุณได้รับการทดสอบอย่างดี
จอน

1
ในความเป็นจริงมีหลายครั้งที่การใช้ == เป็นสิ่งสำคัญเพื่อทำการทดสอบที่จำเป็น หาก foo.toString () จะดำเนินการในรูปแบบที่คาดเดาได้และต้องทดสอบสตริงธรรมดากับเอาต์พุตนั้นดังนั้นการเขียน foo == stringToTest นั้นสะอาดกว่า foo.toString () === stringToTest มาก
Crispen Smith

2
@Alternatex ถ้าประเด็นคือความชัดเจนพวกเขาไม่ควรทำให้มันเท่ากับ TRIPLE! ไม่มีผู้เริ่มต้นเข้าใจมัน อย่างน้อยสองเท่าเป็นที่รู้จักจากภาษาอื่น นอกจากนี้ยังthere is no reasonable situationเป็นการแสดงข้อมูลที่ขัดต่อข้อเท็จจริงอย่างร้ายแรง คิดเกี่ยวกับ (native) ประเภท Javascript และNumber Stringการดำรงอยู่ของพวกเขาพิสูจน์ผู้เขียน Javascript ==มีกรณีการใช้งานบางอย่างในใจสำหรับ คุณคิดว่าnew String('hi') === 'hi'การประเมินfalseเป็นมีความชัดเจนมากหรือไม่? โปรดเขียนข้อมูลโค้ดที่ทดสอบอาร์กิวเมนต์ฟังก์ชันของคุณกับการ'hi'ยอมรับทั้ง String และ string และบอกฉันว่าชัดเจน
Stijn de Witt

25

JSLint มีการป้องกันมากกว่าที่ไวยากรณ์ Javascript อนุญาตโดยเนื้อแท้

จากเอกสาร JSLint:

ตัวดำเนินการ==และ!=ประเภทบังคับก่อนที่จะเปรียบเทียบ สิ่งนี้ไม่ดีเพราะมันทำให้' \t\r\n' == 0เป็นจริง สิ่งนี้สามารถมาสก์ข้อผิดพลาดประเภท

เมื่อเปรียบเทียบกับค่าใด ๆ ต่อไปนี้ให้ใช้===หรือ!==ตัวดำเนินการ (ซึ่งไม่ได้ทำการบังคับประเภท):0 '' undefined null false true

หากคุณสนใจเพียงว่าค่าเป็นจริงหรือเท็จให้ใช้รูปแบบสั้น ๆ แทน

(foo != 0)

เพียงแค่พูดว่า

(foo)

และแทนที่จะเป็น

(foo == 0)

พูด

(!foo)

ตัวดำเนินการ===และ!==เป็นที่ต้องการ


8
ฉันต้องสรุปว่าคนจาก JSLint ทำงานในหอคอยงาช้างที่สูงมากซึ่งพวกเขาไม่เคยออกไปไหน Javascript ถูกออกแบบมาเพื่อใช้กับตัว==ดำเนินการ ===เป็นกรณีพิเศษ ... JSLint พยายามที่จะทำให้มันดูเหมือนเช่นการใช้==อย่างใดจะมีความผิด ... var x = 4, y = new Number(4); if (x == y) {alert('Javascript depends on == just embrace it!');}แต่ลองนี้ ประเภทดั้งเดิมมีคลาสที่สอดคล้องกันซึ่งใช้แทน ( Number, String) และ Javascript ขึ้นอยู่กับตัว==ดำเนินการในการเปรียบเทียบธรรมชาติเหล่านี้
Stijn de Witt

17

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

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


4
นอกจากนี้ยังไม่สามารถเป็นบริบทที่ชาญฉลาดเท่าโปรแกรมเมอร์ เพียงแค่ทำงานบนพื้นฐานที่ผู้ใช้ส่วนใหญ่สะดุดโดยการแปลงประเภทอัตโนมัติที่มีอยู่ในระบบ (เช่นความรุนแรง - "ช่วยด้วยฉันกำลังอดกลั้น!")
Rudu

14

Triple-equal แตกต่างกับ double-equal เพราะนอกจากจะตรวจสอบว่าทั้งสองด้านมีค่าเท่ากันหรือไม่แล้ว triple-equal ยังตรวจสอบว่าเป็นประเภทข้อมูลเดียวกัน

ดังนั้น("4" == 4)เป็นความจริงในขณะที่("4" === 4)เป็นเท็จ

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

JSLint มีเป้าหมายโดยเจตนาที่จะทำให้โค้ด JavaScript ของคุณเข้มงวดมากที่สุดโดยมีจุดประสงค์เพื่อลดข้อบกพร่องที่คลุมเครือ มันเน้นสิ่งนี้เพื่อพยายามให้คุณเขียนโค้ดในลักษณะที่บังคับให้คุณเคารพประเภทข้อมูล

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

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


3
ฉันไม่ได้ถามว่า "=== คืออะไร" ดังนั้นฉันจึงไม่แน่ใจว่าทำไมคุณถึงตอบมัน
Metropolis

8
@ มหานคร: ถ้าไม่มีเหตุผลอื่นก็เป็นพื้นหลังเผื่อว่ามีคนอื่นอ่านคำตอบที่ไม่รู้ ฉันพยายามตอบคำถามของคุณในย่อหน้าหลังจากนั้น
Spudley

@Spudley + 1 สำหรับข้อมูลเพิ่มเติมและเป็นประโยชน์
Ben Junior

1
ใช่มันเร็วขึ้น 10-100 เท่า: การทดสอบความเร็ว
jsperf

8

คำพูดจากhttp://javascript.crockford.com/code.html :

=== และ! == ตัวดำเนินการ

การใช้ตัวดำเนินการ === และ! == จะดีกว่าเกือบตลอดเวลา ตัวดำเนินการ == และ! = ทำการบังคับประเภท โดยเฉพาะอย่าใช้ == เพื่อเปรียบเทียบกับค่าที่เป็นเท็จ

JSLint นั้นเข้มงวดมาก 'webjslint.js' ของพวกเขาไม่ผ่านการตรวจสอบความถูกต้องของตัวเอง


คำชี้แจงที่ดี นั่นเป็นความจริงเกี่ยวกับการwebjslint.jsไม่ตรวจสอบความถูกต้อง - แม้ว่าข้อผิดพลาดส่วนใหญ่ที่ฉันเห็นในตอนนี้เกี่ยวข้องกับการเว้นวรรค เห็นได้ชัดว่าเราต้องใช้สามัญสำนึกและวิจารณญาณอย่างสมเหตุสมผลเมื่อตรวจสอบ JavaScript โดยใช้ JSLint
hotshot309

การใช้คำalwaysนี้ตัดสิทธิ์โดยอัตโนมัติคำพูดนี้เป็นภูมิปัญญา โปรแกรมเมอร์ที่ฉลาดไม่ได้ดันทุรัง พวกเขาใช้สิ่งที่ดีที่สุดในสถานการณ์ที่กำหนด และพวกเขายินดีและยอมรับเครื่องมือใด ๆ ที่สร้างขึ้นเพื่อเป็นแกนหลักของภาษาไม่ใช่แค่ปิดด้วยไฟล์just never touch it. บรรทัดล่าง: รหัสของฉันสั้นลง (ไม่ใช่แค่การบันทึก=อักขระเพียงตัวเดียว) ดังนั้นไซต์ของฉันจึงโหลดได้เร็วขึ้นด้วยต้นทุนแบนด์วิดท์ที่น้อยลงผู้ใช้ของฉันจึงให้บริการได้ดีขึ้น
Stijn de Witt

4

หากคุณต้องการทดสอบความเท็จ JSLint ไม่อนุญาต

if (foo == null)

แต่ไม่อนุญาต

if (!foo)

ใช้===ซึ่ง JSLint แนะนำ
clickbait

1
@NarawaGames โซลูชันนี้เป็นที่ยอมรับอย่างสมบูรณ์

คำตอบนี้ไม่ดี สิ่งนี้ก็คือทั้งสองสิ่งนี้หมายถึงอย่างอื่น foo == nullตรวจสอบค่าว่างหรือไม่ได้กำหนด !fooตรวจสอบค่าว่างไม่ได้กำหนด 0 และสตริงว่าง
Markos

@Markos คำตอบนี้มีไว้เพื่อเป็นทางเลือกที่เป็นประโยชน์ในการทำให้ JSLint มีความสุขและทำให้รหัสตรรกะของคุณเหมือนเดิมไม่ให้เทียบเท่ากัน นี่คือเหตุผลที่ฉันขึ้นต้นคำตอบว่า "หากตรวจสอบความผิดปกติ"
nano2nd

3

เพื่อช่วยอธิบายคำถามนี้และอธิบายว่าเหตุใด NetBeans (จาก) 7.3 จึงเริ่มแสดงคำเตือนนี้ซึ่งเป็นส่วนสกัดจากการตอบสนองบนตัวติดตามข้อบกพร่องของ NetBeans เมื่อมีคนรายงานว่าสิ่งนี้เป็นข้อบกพร่อง:

เป็นแนวทางปฏิบัติที่ดีในการใช้ === แทนที่จะใช้ == ใน JavaScript

ตัวดำเนินการ == และ! = ทำการบังคับประเภทก่อนเปรียบเทียบ สิ่งนี้ไม่ดีเพราะทำให้ '\ t \ r \ n' == 0 เป็นจริง สิ่งนี้สามารถมาสก์ข้อผิดพลาดประเภท JSLint ไม่สามารถระบุได้อย่างน่าเชื่อถือว่ามีการใช้ == อย่างถูกต้องหรือไม่ดังนั้นจึงเป็นการดีที่สุดที่จะไม่ใช้ == และ! = เลยและใช้ตัวดำเนินการ === และ! == ที่เชื่อถือได้มากกว่าแทนเสมอ

ข้อมูลอ้างอิง


1
ฉันพบข้อผิดพลาดนี้เมื่อใช้ Netbeans เช่นกัน เป็นเรื่องแปลกที่พวกเขาจะปฏิบัติต่อสิ่งนี้ด้วยการเตือนภัยเนื่องจากกรณีตัวอย่างที่แปลกประหลาดที่พวกเขาให้ไว้
งดเว้น

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

@oMiKeY ใช่ฉันเข้าใจว่าคุณหมายถึงอะไรพวกเขาสามารถให้ตัวอย่างที่เป็นจริงมากขึ้น!
EM-Creations

2

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


1
แต่ทำไมถึงใช้คำว่า "คาดว่า"? นั่นทำให้ดูเหมือนว่าคุณควรทำสิ่งนี้เสมอ
Metropolis

4
ผู้ประเมินกำลังมองหาคำตอบที่ถูกต้องเนื่องจากกำลังพยายามตรวจสอบความถูกต้อง หากไม่ได้รับคำตอบที่ถูกต้องแสดงว่าไม่เป็นไปตามที่คาดหวัง ตัวตรวจสอบความถูกต้องเริ่มต้นด้วยสมมติฐานที่ว่าทุกอย่างเรียบร้อยดีจากนั้นจะชี้ให้เห็นข้อผิดพลาดเมื่อมันเคลื่อนผ่านโค้ด ไม่จำเป็นต้องเข้าใจว่าอะไรคือคำตอบที่ไม่ถูกต้อง แต่ก็รู้เมื่อเห็นคำตอบที่ไม่ถูกต้อง นอกจากนี้ยังสามารถทำงานในทางกลับกันโดยจงใจค้นหารหัสที่ไม่ดีตามกฎของสิ่งที่ไม่ดี การอนุญาตพิเศษเทียบกับบัญชีดำ
Rushyo

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