javascript if คำสั่งที่มีหลายเงื่อนไขทดสอบทั้งหมดหรือไม่


100

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

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

 a = 1
 b = 2
 c = 1

 if (a==1 && b==1 && c==1)

จาวาสคริปต์จะทดสอบเงื่อนไขทั้ง 3 เงื่อนไขเหล่านั้นหรือหลังจากเห็นว่า b ไม่เท่ากับ 1 ดังนั้นจึงเป็นเท็จมันจะออกจากคำสั่งหรือไม่

ฉันถามจากมุมมองด้านประสิทธิภาพ ตัวอย่างเช่นหากฉันกำลังทดสอบตัวเลือก jQuery ที่ซับซ้อน 3 ตัวฉันไม่อยากให้ jQuery สำรวจ DOM 3 ครั้งหากเห็นได้ชัดจากอันแรกที่จะส่งคืน FALSE (ซึ่งในกรณีนี้มันสมเหตุสมผลกว่าที่จะซ้อนคำสั่ง 3 if)

เพิ่มเติม: อยากรู้อยากเห็นมากขึ้นคำที่เหมาะสมสำหรับสิ่งนี้คืออะไร? ฉันสังเกตว่าหลาย ๆ ท่านใช้คำว่า 'ไฟฟ้าลัดวงจร' นอกจากนี้บางภาษาทำเช่นนี้และบางภาษาไม่ทำเช่นนี้


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

21
พูดอย่างเคร่งครัดนี่ไม่ใช่การเพิ่มประสิทธิภาพก่อนกำหนด ในภาษาที่มีลอจิกลัดวงจรสิ่งสำคัญคือต้องทราบภายใต้เงื่อนไขที่วิธีการบางอย่างจะไม่ถูกดำเนินการ หากคุณกำลังพึ่งพาผลข้างเคียงของพวกเขาเช่น
Rob

5
นี่คืออีกคำถามเกี่ยวกับ "การประเมินไฟฟ้าลัดวงจร": stackoverflow.com/questions/1232603/…
David

@ เดวิด. ขอบคุณ! การอ่านที่น่าสนใจ
DA.

คำตอบ:


152

ตัว&&ดำเนินการ "ลัดวงจร" - นั่นคือถ้าเงื่อนไขด้านซ้ายเป็นเท็จจะไม่ต้องกังวลกับการประเมินค่าที่ถูกต้อง

ในทำนองเดียวกันตัว||ดำเนินการลัดวงจรหากเงื่อนไขด้านซ้ายเป็นจริง

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


1
คำตอบที่ดีเยี่ยม (ทั้งในส่วนทางเทคนิคและปัญหาการจัดการ) ขอบคุณ!
DA.

5
หากคุณต้องการให้รันทุกส่วนของสถานะบูลีนคุณสามารถใช้ & และ | สำหรับและและหรือตามลำดับ
Zoidberg

25
เงื่อนไขนี้ไม่จำเป็นต้องเกี่ยวกับประสิทธิภาพเสมอไป บางครั้งคุณอาจทำการตรวจสอบค่าว่างและบอกว่าการตรวจสอบค่าว่างของคุณเป็นเงื่อนไข a หรือไม่จากนั้นคุณพยายามทำ (b == ค่า + 1) สำหรับการตรวจสอบครั้งที่สองของคุณคุณจะได้รับข้อผิดพลาดหากเงื่อนไขทั้งสามเงื่อนไขถูกตรวจสอบ
infocyde

4
อันที่จริงการลัดวงจรไม่ได้เกี่ยวกับประสิทธิภาพ อย่างไรก็ตามคำถามเดิมถามจากมุมมองด้านประสิทธิภาพ
อานนท์.

1
ดีมาก. การเพิ่มประสิทธิภาพไมโครประเภทนี้ (อื่น ๆ ) อาจส่งผลกระทบอย่างมากภายในลูปเหตุการณ์การเลื่อนเช่นการคำนวณพารัลแลกซ์ของหลายองค์ประกอบเช่นหรือแม้แต่แถบเหนียว ใช้เช่นนี้: if (!barSticky && bar.parent().offset().top <= document.documentElement.scrollTop)เงื่อนไขที่สองเป็นการคำนวณที่มีราคาแพงกว่าเงื่อนไขแรกเป็นเพียงบูลีน :)
อันโตนี

13

จากมุมมองด้านประสิทธิภาพนี่ไม่ใช่การเพิ่มประสิทธิภาพระดับไมโคร

ถ้าเรามีตัวแปรบูลีน 3 ตัว a, b, c นั่นคือการเพิ่มประสิทธิภาพระดับไมโคร

ถ้าเราเรียก 3 ฟังก์ชันที่ส่งคืนตัวแปรบูลีนแต่ละฟังก์ชันอาจใช้เวลานานและไม่เพียง แต่จะต้องรู้วงจรลัดนี้เท่านั้น แต่จะเรียงลำดับอย่างไร ตัวอย่างเช่น:

if (takesSeconds() && takesMinutes())

ดีกว่ามาก

if (takesMinutes() && takesSeconds())

หากทั้งสองมีแนวโน้มที่จะคืนค่าเท็จเท่า ๆ กัน


12

นั่นเป็นเหตุผลที่คุณสามารถทำได้ในโค้ดจาวาสคริปต์เช่น

var x = x || 2;

ซึ่งหมายความว่าถ้า x ไม่ได้กำหนดหรือเป็น "เท็จ" ค่าเริ่มต้นคือ 2


3
สิ่งนี้สามารถใช้ได้แม้ว่า JS จะไม่รองรับการประเมินการลัดวงจร
pswg

1
นี่เทียบเท่ากับ ternary หรือไม่?
Mark Carpenter Jr

10

ในกรณีที่มีคนสงสัยว่ามีวิธีบังคับให้ประเมินเงื่อนไขทั้งหมดหรือไม่ในบางกรณีตัวดำเนินการระดับบิต&และ|สามารถใช้ได้

var testOr = true | alert(""); //alert pops up
var testAnd = false & alert(""); //alert pops up

ควรใช้สิ่งเหล่านี้อย่างระมัดระวังเนื่องจากตัวดำเนินการแบบบิตเป็นตัวดำเนินการทางคณิตศาสตร์ที่ทำงานบนบิตเดียวของตัวถูกดำเนินการและไม่สามารถทำงานเป็นเวอร์ชัน "ไม่ลัดวงจร" &&และ||

ตัวอย่าง:

-2147483648 && 1 = 1 

แต่

-2147483648 & 1 = 0

หวังว่าจะช่วยให้ใครบางคนที่มาถึงที่นี่กำลังมองหาข้อมูลเช่นนี้ (เช่นฉัน) และขอบคุณ @Max สำหรับการแก้ไขและตัวอย่างตอบโต้


1
คำตอบนี้ผิด & และ | เป็นตัวดำเนินการระดับบิตซึ่งไม่ใช่ '&& และ ||' เวอร์ชันที่ไม่ลัดวงจร ตัวดำเนินการ Bitwise คือตัวดำเนินการทางคณิตศาสตร์ที่ทำงานบนบิตเดียวของตัวถูกดำเนินการ ตัวอย่าง: -2147483648 && 1 = 1 แต่ -2147483648 & 1 = 0 ข้อมูลเพิ่มเติมที่นี่: en.wikipedia.org/wiki/Bitwise_operation
สูงสุด

1
@ แม็กซ์ฉันไม่รู้จริงๆฉันใช้สิ่งนี้ (ตอนนี้ฉันเรียกว่า "เคล็ดลับ") ตั้งแต่ฉันเรียน C. โชคดีที่ปัจจัยการผลิตที่จะทำลายรหัสของฉันไม่เคยเกิดขึ้น ฉันแก้ไขคำตอบแล้วฉันเป็นหนี้คุณ
ivcandela

@DJDaveMark ขออภัยฉันไม่สามารถfalse && (alert(""))แก้ปัญหาของคุณได้: /
ivcandela

@ivcandela ก็ไม่ได้เช่นกันถ้าฉันไม่ได้ใช้โทรศัพท์ฉันจะต้องทดสอบมันก่อน o) สงสารคุณไม่สามารถแก้ไขความคิดเห็นได้ ฉันเพิ่งลบมันและเพิ่มอีกรายการด้านล่าง
DJDaveMark

วิธีที่ง่ายและดีกว่าในการบังคับให้ประเมินคือบันทึกผลลัพธ์ในตัวแปรจากนั้นทดสอบกับตัวแปรเช่น:var a=false; var b=check(); alert(a && b);
DJDaveMark

7

มันจะทดสอบเงื่อนไขทั้งหมดก็ต่อเมื่อเงื่อนไขแรกเป็นจริงทดสอบด้วยตัวคุณเอง:

javascript: alert (false && alert("A") && false);


3

อีกสาเหตุหนึ่งที่หยุดการประเมินโดยมีพารามิเตอร์ 1 ตัวขึ้นไปทางซ้าย

ถ้า (response.authResponse && (response.authResponse.accessToken! = user.accessToken)) {... }

การประเมินผลครั้งที่สองขึ้นอยู่กับครั้งแรกที่เป็นจริงและจะไม่ส่งข้อผิดพลาดในการคอมไพล์หาก response.authResponse เป็นโมฆะหรือไม่ได้กำหนดเป็นต้นเนื่องจากเงื่อนไขแรกล้มเหลว

ภาษาอื่นมีปัญหานี้ในช่วงแรก ๆ และฉันคิดว่ามันเป็นแนวทางมาตรฐานในการสร้างคอมไพเลอร์ตอนนี้



2

สำหรับใครก็ตามในคำถามนี้สับสนเพราะไม่เห็นพฤติกรรมการลัดวงจรเมื่อใช้||ร่วมกับตัว?ดำเนินการดังนี้:

x = 1 || true ? 2 : 3 // value of x will be 2, rather than 1 as expected

ดูเหมือนว่ากฎการลัดวงจรไม่ทำงาน เหตุใดจึงประเมินระยะที่สองของ||(จริง 2: 3) เมื่อครั้งแรกเป็นจริง ปรากฎว่าเป็นคำสั่งของปัญหาการดำเนินงานเนื่องจากข้างต้นเทียบเท่ากับ

x = (1 || true) ? 2 : 3

กับผู้||ประเมินก่อนและ?ประเมินครั้งที่สอง สิ่งที่คุณต้องการคือ:

x = 1 || (true ? 2 : 3)

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