วิธีการย่อข้อความตามเงื่อนไขของฉันให้สั้นลง


154

ฉันมีคำสั่งที่มีเงื่อนไขยาวมากดังต่อไปนี้:

if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
    // do something.
}

ฉันสงสัยว่าถ้าฉันสามารถ refactor การแสดงออก / คำสั่งนี้ในรูปแบบที่กระชับมากขึ้น

ความคิดเกี่ยวกับวิธีการบรรลุสิ่งนี้?


23
คุณสามารถวางไว้ในอาร์เรย์และใช้in?
jeremy


ตอนนี้ก็ต่อเมื่อใครบางคนสามารถตรวจสอบว่าใครเร็วที่สุด
Muhammad Umer

3
นี่อาจเป็นเรื่องที่ทุกคนตกใจ แต่สิ่งที่ OP มีคือผู้ชนะอย่างรวดเร็ว !!!!!!! อาจจะทำให้เกิดการเพิ่มประสิทธิภาพของเบราว์เซอร์สำหรับจำนวนมากนี้ .. ผล: (1) ||ถ้ามี (2) switchข้อความ (3) regex ~(4) jsperf.com/if-statements-test-techsin
Muhammad Umer

3
คุณอาจกำลังเข้าใกล้ทางนี้ผิด ในกรณีนี้ทั้งสี่ประเภทมีบางอย่างที่เหมือนกัน มันคืออะไร? ถ้าเราทำสิ่งนี้ให้เป็นกรณีที่รุนแรงมากขึ้นจะเกิดอะไรขึ้นถ้าเราต้องการเพิ่มประเภทอีก 10 ชนิดเพื่อให้ตรงกับเงื่อนไขนี้ หรือ 100 หากมีมากขึ้นคุณอาจไม่พิจารณาใช้โซลูชันนี้หรืออื่น ๆ ที่แนะนำ คุณจะเห็นคำสั่งขนาดใหญ่เช่นนี้และคิดว่ามันเป็นกลิ่นรหัสซึ่งเป็นสัญญาณที่ดี วิธีที่ดีที่สุดในการทำให้รัดกุมยิ่งขึ้นนี้คือถ้าคุณสามารถเขียนได้ว่า (test.your_common_condition) ง่ายต่อการเข้าใจในบริบทนี้และสามารถขยายได้มากขึ้น
gmacdougall

คำตอบ:


241

ใส่ค่าของคุณลงในอาร์เรย์และตรวจสอบว่ารายการของคุณอยู่ในอาร์เรย์:

if ([1, 2, 3, 4].includes(test.type)) {
    // Do something
}

หากเบราว์เซอร์ที่คุณสนับสนุนไม่มีArray#includesวิธีคุณสามารถใช้polyfill นี้ได้


คำอธิบายสั้น ๆ ของ~ทางลัดตัวหนอน:

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

แทนที่จะตรวจสอบว่าผลลัพธ์indexOfเป็น>= 0หรือไม่มีทางลัดที่ดีเล็กน้อย:

if ( ~[1, 2, 3, 4].indexOf(test.type) ) {
    // Do something
}

นี่คือซอ: http://jsfiddle.net/HYJvK/

มันทำงานอย่างไร หากพบรายการในอาร์เรย์ให้indexOfส่งคืนดัชนี -1หากรายการไม่พบก็จะกลับมา โดยไม่ลงรายละเอียดมากเกินไป~เป็นค่าที่เหมาะสมไม่ได้ผู้ประกอบการที่จะกลับมาเฉพาะสำหรับ0-1

ฉันชอบใช้~ทางลัดเนื่องจากมันสั้นกว่าการเปรียบเทียบค่าส่งคืน ฉันหวังว่าจาวาสคริปต์จะมีin_arrayฟังก์ชั่นที่ส่งกลับบูลีนโดยตรง (คล้ายกับ PHP) แต่นั่นเป็นเพียงแค่ความคิดที่ปรารถนา ( อัปเดต:ตอนนี้มันทำแล้วเรียกว่าincludesดูด้านบน) โปรดทราบว่า jQuery inArrayในขณะที่แชร์ลายเซ็นของวิธีการของ PHP จะเลียนแบบภาษาของจริงindexOfฟังก์ชัน (ซึ่งมีประโยชน์ในหลายกรณีหากดัชนีคือสิ่งที่คุณต้องการอย่างแท้จริง)

หมายเหตุสำคัญ:การใช้ช็อตคัตตัวหนอนดูเหมือนว่าจะมีการถกเถียงกันอย่างรุนแรงเนื่องจากบางคนเชื่อว่ารหัสไม่ชัดเจนเพียงพอและควรหลีกเลี่ยงค่าใช้จ่ายทั้งหมด (ดูความคิดเห็นในคำตอบนี้) หากคุณแบ่งปันความเชื่อมั่นคุณควรยึด.indexOf(...) >= 0แนวทางแก้ไข


คำอธิบายอีกต่อไปเล็กน้อย:

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

นี่คือตัวอย่างตัวเลขในรูปแบบไบนารี 32 บิต:

1 :    00000000000000000000000000000001
2 :    00000000000000000000000000000010
3 :    00000000000000000000000000000011
15:    00000000000000000000000000001111

ตอนนี้ที่นี่มีตัวเลขเดียวกัน แต่เป็นลบ:

-1 :   11111111111111111111111111111111
-2 :   11111111111111111111111111111110
-3 :   11111111111111111111111111111101
-15:   11111111111111111111111111110001

ทำไมชุดค่าผสมดังกล่าวแปลกสำหรับจำนวนลบ? ง่าย จำนวนลบเป็นเพียงค่าผกผันของจำนวนบวก + 1 0การเพิ่มจำนวนลบไปยังหมายเลขที่ดีควรผลผลิตเสมอ

เพื่อให้เข้าใจสิ่งนี้ลองทำเลขคณิตไบนารีง่ายๆ

นี่คือวิธีการที่เราจะเพิ่ม-1ไป+1:

   00000000000000000000000000000001      +1
+  11111111111111111111111111111111      -1
-------------------------------------------
=  00000000000000000000000000000000       0

และนี่คือวิธีการที่เราจะเพิ่ม-15ไป+15:

   00000000000000000000000000001111      +15
+  11111111111111111111111111110001      -15
--------------------------------------------
=  00000000000000000000000000000000        0

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

ตอนนี้เป็นคุณจะแจ้งให้ทราบเมื่อมีการเพิ่มจำนวนลบไปยังหมายเลขบวกที่คอลัมน์ขวามากที่สุดที่ไม่ได้ทั้งหมด0เสมอจะมีสอง1s 2ซึ่งเมื่อรวมเข้าด้วยกันจะส่งผลให้ การแทนเลขฐานสองของสิ่งมีชีวิตทั้งสอง10เราจะนำ1ไปยังคอลัมน์ถัดไปและวาง0ผลลัพธ์ในคอลัมน์แรก คอลัมน์อื่น ๆ ทางด้านซ้ายมีเพียงหนึ่งแถว1เท่านั้นดังนั้นการ1ดำเนินการจากคอลัมน์ก่อนหน้าจะรวมกันอีกครั้ง2ซึ่งจะดำเนินการต่อไป ... กระบวนการนี้จะทำซ้ำตัวเองจนกว่าเราจะไปที่คอลัมน์ซ้ายสุด ที่1จะต้องดำเนินการต่อไปไม่มีที่ไหนเลยดังนั้นมันจึงล้นและหายไปและเราก็เหลือไว้ด้วย0กัน

ระบบนี้เรียกว่าการเติมเต็ม 2 คุณสามารถอ่านเพิ่มเติมเกี่ยวกับเรื่องนี้ได้ที่นี่:

การเป็นตัวแทนที่สมบูรณ์ของ 2 สำหรับจำนวนเต็มที่ลงนามแล้ว


ตอนนี้หลักสูตรความผิดพลาดในส่วนประกอบ 2 จบลงแล้วคุณจะสังเกตเห็นว่า-1เป็นหมายเลขเดียวที่มีการแทนค่าฐานสอง1ทั้งหมด

การใช้ตัวดำเนินการ~bitwise NOT บิตทั้งหมดในจำนวนที่กำหนดจะกลับด้าน วิธีเดียวที่จะ0กลับมาจากการแปลงกลับบิตทั้งหมดคือถ้าเราเริ่มต้นด้วย1ทุกอย่าง

ดังนั้นทั้งหมดนี้เป็นวิธีที่ยืดยาวในการบอกว่า~nจะกลับมา0ถ้าnเป็น-1เท่านั้น


59
ในขณะที่ใช้โอเปอเรเตอร์บิตเตอร์แน่ใจว่าเซ็กซี่!== -1ใช่หรือไม่ ตรรกะบูลีนที่ชัดเจนไม่เหมาะสมกว่าการใช้ความเท็จโดยปริยายของศูนย์หรือไม่?
Phil

21
มีเทคนิคดีมาก แต่ฉันไม่ชอบ ยังไม่ชัดเจนในตอนแรกสิ่งที่ทำรหัสซึ่งทำให้ไม่สามารถทำความเข้าใจได้ ฉันชอบคำตอบของ "Yuriy Galanter" มาก
Jon Rea

65
โปรแกรมเมอร์ใหม่ -1 คนเห็นคำตอบเช่นนี้คิดว่ามันเป็นวิธีการเขียนโค้ดที่ยอดเยี่ยมและเป็นที่ยอมรับจากนั้นใน 5 ปีฉันต้องรักษารหัสและฉีกผมออก
BlueRaja - Danny Pflughoeft

23
สำนวนนี้ไม่ธรรมดาในภาษาเช่น C #, Java หรือ Python ซึ่งเป็นพื้นที่ของความเชี่ยวชาญของฉัน และฉันเพิ่งถามผู้เชี่ยวชาญ Javascript ในพื้นที่ที่นี่และไม่มีใครเคยเห็นมาก่อน ดังนั้นจึงไม่ชัดเจนเหมือนกับที่คุณอ้างสิทธิ์ มันก็ควรจะหลีกเลี่ยงในความโปรดปรานของโรคที่ชัดเจนมากขึ้นและมากขึ้น != -1
BlueRaja - Danny Pflughoeft

12
-1 เนื่องจากการเล่นซอร์บิตที่ไม่จำเป็นในภาษาซึ่งไม่ได้ระบุอะไรมากมายเกี่ยวกับการเป็นตัวแทนบิตตั้งแต่แรก ยิ่งกว่านั้นคำตอบนี้ส่วนใหญ่กำลังอธิบายถึงการทำจิ๊กซอว์ หากคุณต้องเขียน 20 ย่อหน้าเพื่ออธิบายการแฮ็กมันช่วยประหยัดเวลาได้จริงเหรอ?
ปุย

242

คุณสามารถใช้คำสั่ง switch ด้วย fall thru:

switch (test.type) {

  case "itema":
  case "itemb":
  case "itemc":
  case "itemd":
    // do something
}

9
โดยพื้นฐานแล้วเหมือนกับถ้าดัชนีของวิธีอาร์เรย์ดีกว่าไกล
NimChimpsky

6
@kojiro มันน่าเศร้าคำตอบที่ถูกต้องคือสิ่งนี้ แต่มันเป็นไปไม่ได้ที่จะได้รับความสนใจกับสิ่งนี้แทนที่จะเป็นเคล็ดลับอาร์เรย์สีขาวที่ยอดเยี่ยม
Manu343726

1
ฉันรู้ว่าคำตอบนี้ต้องอยู่ที่นี่ แต่ฉันต้องเลื่อนลงไปด้านล่างเพื่อค้นหา มันเป็นสิ่งที่งบ switch ได้รับการออกแบบและนำไปใช้กับภาษาอื่น ๆ อีกมากมาย ฉันพบว่าผู้คนจำนวนมากไม่รู้เกี่ยวกับวิธีการ 'ตกลงผ่าน' ในคำสั่งสลับ
จิมมี่จอห์นสัน

3
โซลูชันนี้เร็วที่สุดใน Firefox และ Safari และเร็วที่สุดเป็นอันดับสอง (หลังจากต้นฉบับ||) บน Chrome ดูjsperf.com/if-statements-test-techsin
pabouk

3
ฉันคิดว่ามันจะแย่ถ้าเขียนในวิธีการถ้าคุณมีเงื่อนไขมากมาย ... ถ้าปรับได้สำหรับเงื่อนไขสองสามข้อ แต่สำหรับ 10 กว่านี้ฉันจะใช้อาร์เรย์เพื่อรักษาโค้ดให้เรียบร้อย
yu_ominae

63

การใช้วิทยาศาสตร์: คุณควรทำสิ่งที่ idfah พูดและสิ่งนี้เพื่อความเร็วที่เร็วที่สุดในขณะที่ให้รหัสสั้น:

นี่เร็วกว่า~วิธี

var x = test.type;
if (x == 'itema' ||
    x == 'itemb' ||
    x == 'itemc' ||
    x == 'itemd') {
    //do something
}

http://jsperf.com/if-statements-test-techsin ป้อนคำอธิบายรูปภาพที่นี่ (ชุดด้านบน: Chrome, ชุดด้านล่าง: Firefox)

สรุป:

ถ้าเป็นไปได้ไม่กี่และคุณรู้ว่าบางคนมีแนวโน้มที่จะเกิดขึ้นกว่าที่คุณได้รับประสิทธิภาพสูงสุดจากif ||, และswitch fall throughif(obj[keyval])

หากความเป็นไปได้มีมากมายและทุกคนในนั้นอาจเป็นสิ่งที่เกิดขึ้นมากที่สุดในอีกนัยหนึ่งคุณไม่สามารถรู้ได้ว่าสิ่งใดที่น่าจะเกิดขึ้นมากกว่าที่คุณจะได้รับประสิทธิภาพสูงสุดจากการค้นหาวัตถุif(obj[keyval])และregexถ้ามันเหมาะสม

http://jsperf.com/if-statements-test-techsin/12

ฉันจะอัปเดตหากมีอะไรใหม่เกิดขึ้น


2
+1 สำหรับโพสต์ที่ดีจริงๆ! ถ้าฉันเข้าใจถูกต้องswitch caseเป็นวิธีที่เร็วที่สุด?
user1477388

1
ใน firefox ใช่ใน chrome มันif ( ...||...||...)...
Muhammad Umer

8
มันเร็วกว่าถ้าคุณทำลูปหลาย ๆ อันผ่านอินพุตนี้ แต่มันจะช้ากว่ามากถ้าคุณมีลูปเดียวที่มี n ที่มีขนาดใหญ่มาก (จำนวนสตริง "itemX") ฉันแฮ็กตัวสร้างโค้ดนี้ขึ้นซึ่งคุณสามารถใช้ในการตรวจสอบ (หรืออาจปฏิเสธ) obj["itemX"]เร็วมากถ้า n มีขนาดใหญ่ โดยทั่วไปสิ่งที่รวดเร็วขึ้นอยู่กับบริบท มีความสุข.
kojiro

3
ดังนั้นมันจึงเป็นวิธีที่เร็วที่สุด แต่มันสำคัญไหม
congusbongus

1
@Mich อย่าเสียสละความงดงามของรหัสเพื่อความรวดเร็ว นี่คือสิ่งที่หลายคนจะพูดกับคุณ ในท้ายที่สุดเพียงใช้สามัญสำนึก
Andre Figueiredo

32

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

มิฉะนั้นฉันสงสัยว่าพยายามย่อให้สั้นลงจะทำให้รหัสของคุณงงงวย พิจารณาการพันลายเส้นเพื่อทำให้สวย

if (test.type == 'itema' ||
    test.type == 'itemb' ||
    test.type == 'itemc' ||
    test.type == 'itemd') {
    do something.
}

4
คำตอบนี้เป็นผู้ชนะในแง่ของความเร็ว jsperf.com/if-statements-test-techsin
Muhammad Umer

1
นี่เป็นวิธีที่ง่ายที่สุดในการขยายเมื่อโครงการเข้าสู่โหมดการบำรุงรักษา (ด้วยกฎเช่น, (test.type == 'itemf' && foo.mode == 'detailed'))
Izkata

16
var possibilities = {
  "itema": 1,
  "itemb": 1,
  "itemc": 1,
…};
if (test.type in possibilities) {  }

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


จะสั้นกว่าปกติได้อย่างไรถ้าข้อความว่า FlyingCat พยายามย่อให้สั้นลง?
dcarson

1
เงื่อนไขของifคำสั่ง@dcarson OP ใช้เวลา 78 ตัวอักษรหากคุณลบช่องว่างทั้งหมด เหมืองแร่จะใช้เวลา 54 test.type in {"itema":1,"itemb":1,"itemc":1,"itemd":1}ถ้าคุณเขียนเช่นนี้ โดยพื้นฐานแล้วเขาใช้อักขระสี่ตัวสำหรับทุก ๆ สองทุ่นระเบิดสำหรับแต่ละคีย์เพิ่มเติม
kojiro

1
แต่คุณสามารถทำได้: ถ้า (เป็นไปได้ [test.type]) และบันทึกทั้ง 2 ตัวอักษร! :)
dc5

15
if( /^item[a-d]$/.test(test.type) ) { /* do something */ }

หรือหากรายการไม่เหมือนกันให้ทำดังนี้

if( /^(itema|itemb|itemc|itemd)$/.test(test.type) ) { /* do something */ }

9
"บางคนเมื่อเผชิญกับปัญหาคิดว่า 'ฉันรู้ฉันจะใช้สำนวนปกติ' ตอนนี้พวกเขามีปัญหาสองข้อ " - Jamie Zawinski, 1997
Moshe Katz

5
@MosheKatz ในขณะที่ฉันสามารถเข้าใจผู้คนชอบพูดพาดพิงถึงคำพูดนั้น - และผู้คนใช้การแสดงออกปกติสำหรับสิ่งที่ไม่เหมาะสมทั้งหมด แต่นี่ไม่ใช่หนึ่งในนั้น ในกรณีที่ได้รับจาก OP สิ่งนี้ไม่เพียงตรงกับเกณฑ์เท่านั้น แต่ทำได้ดีมาก นิพจน์ทั่วไปไม่ใช่ความชั่วโดยเนื้อแท้และสตริงที่ตรงกับพารามิเตอร์ที่กำหนดอย่างดีนั้นเป็นสิ่งที่ทำ
Thor84no

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

10

คำตอบที่ยอดเยี่ยม แต่คุณสามารถทำให้โค้ดอ่านง่ายขึ้นโดยการห่อหนึ่งในฟังก์ชัน

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

if(CheckIfBusinessRuleIsTrue())
{
    //Do Something
}

function CheckIfBusinessRuleIsTrue() 
{
    return (the best solution from previous posts here);
}

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


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

แสดงความคิดเห็นเช่นเดียวกับ// CheckIfBusinessRuleIsTrue?
daniel1426

4

คุณสามารถใส่คำตอบทั้งหมดลงในชุด Javascriptจากนั้นเพียงโทรหา.contains()ชุด

คุณยังต้องประกาศเนื้อหาทั้งหมด แต่การโทรแบบอินไลน์จะสั้นลง

สิ่งที่ต้องการ:

var itemSet = new Set(["itema","itemb","itemc","itemd"]);
if( itemSet.contains( test.type ){}

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

@ กัปตันเย็น: ดี OP ถามหารัดกุมไม่ใช่รอยความทรงจำ อาจเป็นชุดที่สามารถนำมาใช้ซ้ำสำหรับการดำเนินงานอื่น ๆ ?
Guido Anselmi

1
แน่นอน แต่ถึงอย่างนั้นคุณจะซื่อสัตย์หรือไม่ ที่เคยทำเช่นนี้ตัวเอง? หากฉันเคยเห็นสิ่งนี้ในป่าฉันจะพิจารณาว่าเป็น WTF สำคัญ
KaptajnKold

1
ใช่คุณพูดถูก (ฉันให้ +1 ให้คุณ) แต่ก็ถือว่าการตรวจสอบนี้เสร็จสมบูรณ์ ถ้ามันถูกทำในหลาย ๆ ที่และ / หรือการเปลี่ยนแปลงการทดสอบแล้วการใช้ชุดอาจทำให้รู้สึก ฉันปล่อยให้ OP เลือกวิธีที่ดีที่สุด ทั้งหมดที่กล่าวว่าหากนี่เป็นการใช้งานแบบเดี่ยวฉันจะยอมรับว่าการใช้ชุดจะต้องได้รับหมวกแห่งความละอาย
Guido Anselmi

2
ฉันคิดว่าคำตอบที่เลือกนั้นแย่มากและแย่กว่านั้นเมื่อใช้ Set เพราะไม่สามารถอ่านได้
Guido Anselmi

2

หนึ่งในวิธีที่ฉันโปรดปรานในการทำสิ่งนี้ให้สำเร็จคือใช้ห้องสมุดเช่น underscore.js ...

var isItem = _.some(['itema','itemb','itemc','itemd'], function(item) {
    return test.type === item;
});

if(isItem) {
    // One of them was true
}

http://underscorejs.org/#some


1
containsเป็นวิธีแก้ปัญหาที่ดีกว่าsome
Dennis

1
ไม่จำเป็นต้องใช้ไลบรารีสำหรับสิ่งนี้: someเป็นฟังก์ชั่นบนต้นแบบ Array ใน EC5
KaptajnKold

2
จริง แต่ไม่ใช่ทุกคนมีการสนับสนุน EC5 นอกจากนี้ฉันชอบขีดเส้นใต้จริงๆ :)
jcreamer898

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

2

อีกวิธีหนึ่งหรืออีกวิธีที่ยอดเยี่ยมที่ฉันพบคือ ...

if ('a' in oc(['a','b','c'])) { //dosomething }

function oc(a)
{
  var o = {};
  for(var i=0;i<a.length;i++)  o[a[i]]='';
  return o;
}

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

http://snook.ca/archives/javascript/testing_for_a_v

ใช้ตัวดำเนินการเช่น ~ && || ((), ()) ~~ ใช้ได้ก็ต่อเมื่อรหัสของคุณแตกหักในภายหลัง คุณจะไม่รู้ว่าจะเริ่มจากตรงไหน ดังนั้นการอ่านมีค่ามาก

ถ้าคุณต้องทำให้มันสั้นลง

('a' in oc(['a','b','c'])) && statement;
('a' in oc(['a','b','c'])) && (statements,statements);
('a' in oc(['a','b','c']))?statement:elseStatement;
('a' in oc(['a','b','c']))?(statements,statements):(elseStatements,elseStatements);

และถ้าคุณต้องการที่จะทำผกผัน

('a' in oc(['a','b','c'])) || statement;

2

เพียงแค่ใช้switchคำสั่งแทนifคำสั่ง:

switch (test.type) {

  case "itema":case "itemb":case "itemc":case "itemd":
    // do your process
  case "other cases":...:
    // do other processes
  default:
    // do processes when test.type does not meet your predictions.
}

Switch ยังทำงานได้เร็วกว่าการเปรียบเทียบเงื่อนไขจำนวนมากภายใน if


2

สำหรับรายการสตริงที่ยาวมาก ๆ ความคิดนี้จะช่วยตัวละครสองสามตัว (ไม่ได้บอกว่าฉันแนะนำในชีวิตจริง แต่ควรใช้งานได้)

เลือกตัวละครที่คุณรู้ว่าจะไม่เกิดขึ้นใน test.type ของคุณใช้มันเป็นตัวคั่นติดมันทั้งหมดลงในสายยาวหนึ่งอันแล้วค้นหาว่า:

if ("/itema/itemb/itemc/itemd/".indexOf("/"+test.type+"/")>=0) {
  // doSomething
}

หากสายอักขระของคุณมีข้อ จำกัด เพิ่มเติมคุณสามารถละเว้นตัวคั่นได้ ...

if ("itemaitembitemcitemd".indexOf(test.type)>=0) {
  // doSomething
}

... แต่คุณต้องระวังข้อผิดพลาดที่เป็นบวกในกรณีนั้น (เช่น "embite" จะจับคู่ในเวอร์ชันนั้น)


2

เพื่อความสามารถในการอ่านสร้างฟังก์ชั่นสำหรับการทดสอบ (ใช่ฟังก์ชั่นหนึ่งบรรทัด):

function isTypeDefined(test) {
    return test.type == 'itema' ||
           test.type == 'itemb' ||
           test.type == 'itemc' ||
           test.type == 'itemd';
}

จากนั้นเรียกมันว่า:


    if (isTypeDefined(test)) {

}
...

1

ฉันคิดว่ามี 2 วัตถุประสงค์เมื่อเขียนเงื่อนไขแบบนี้

  1. ความกะทัดรัด
  2. การอ่าน

เช่น # 1 บางครั้งอาจเร็วที่สุด แต่ฉันจะใช้ # 2 เพื่อการบำรุงรักษาง่ายในภายหลัง ขึ้นอยู่กับสถานการณ์ฉันมักจะเลือกคำตอบของวอลเตอร์

เพื่อเริ่มต้นฉันมีฟังก์ชั่นที่ใช้งานได้ทั่วโลกซึ่งเป็นส่วนหนึ่งของห้องสมุดที่มีอยู่ของฉัน

function isDefined(obj){
  return (typeof(obj) != 'undefined');
}

และเมื่อฉันต้องการรันเงื่อนไข if คล้ายกับของคุณฉันจะสร้างวัตถุที่มีรายการค่าที่ถูกต้อง:

var validOptions = {
  "itema":1,
  "itemb":1,
  "itemc":1,
  "itemd":1
};
if(isDefined(validOptions[test.type])){
  //do something...
}

มันไม่เร็วเท่ากับคำสั่ง switch / case และ verbose มากกว่าตัวอย่างอื่น ๆ เล็กน้อย แต่ฉันมักจะนำวัตถุกลับมาใช้ที่อื่นในรหัสซึ่งค่อนข้างมีประโยชน์

Piggybacking กับหนึ่งในตัวอย่าง jsperf ที่สร้างขึ้นด้านบนฉันเพิ่มการทดสอบนี้และการเปลี่ยนแปลงเพื่อเปรียบเทียบความเร็ว http://jsperf.com/if-statements-test-techsin/6สิ่งที่น่าสนใจที่สุดที่ฉันสังเกตคือชุดทดสอบใน Firefox นั้นเร็วกว่า Chrome มาก


1

สิ่งนี้สามารถแก้ไขได้ด้วยการวนรอบอย่างง่าย:

test = {};
test.type = 'itema';

for(var i=['itema','itemb','itemc']; i[0]==test.type && [
    (function() {
        // do something
        console.log('matched!');
    })()
]; i.shift());

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

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