ประสิทธิภาพของ Javascript: 'for' vs 'forEach' [closed]


107

อะไรคือมาตรฐานปัจจุบันในปี 2017 ใน Javascript ที่มีสำหรับ () ลูปกับ a .forEach

ฉันกำลังทำงานของฉันผ่านทางหนุ่มสตีล "Web Dev Bootcamp" ใน Udemy และเขาโปรดปรานforEachมากกว่าforในคำสอนของพระองค์ ฉันได้ แต่ค้นหาสิ่งต่างๆในระหว่างการออกกำลังกายเป็นส่วนหนึ่งของการทำงานการเรียนการสอนและฉันพบมากขึ้นและคำแนะนำเพิ่มเติมที่จะใช้for-loop forEachมากกว่า คนส่วนใหญ่ดูเหมือนจะระบุว่า for loop นั้นมีประสิทธิภาพมากกว่า

นี่คือสิ่งที่เปลี่ยนแปลงไปตั้งแต่เริ่มเขียนหลักสูตร (ประมาณปี 2015) หรือเป็นข้อดีข้อเสียของแต่ละข้อซึ่งจะได้เรียนรู้ด้วยประสบการณ์ที่มากขึ้น

คำแนะนำใด ๆ จะได้รับการชื่นชมอย่างมาก


11
ทำไมต้องผูกตัวเองกับความคิดส่วนตัวของใครบางคนเกี่ยวกับมาตรฐานปี 2017? ใช้มาตรฐานที่เป็นอมตะเช่นการเขียนโค้ดที่สะอาดและบำรุงรักษาได้โดยรู้ว่าวิศวกรกำลังทำงานอย่างหนักเพื่อสร้างโครงสร้างที่ใช้บ่อยที่สุดให้มีประสิทธิภาพมากที่สุดจากนั้นจึงเพิ่มประสิทธิภาพเมื่อคุณมีปัญหาด้านประสิทธิภาพที่เฉพาะเจาะจง

2
เจ้าของภาษาforนั้นยากที่จะเอาชนะด้วยความเร็วที่แท้จริง forEach()เรียกใช้การเรียกกลับสำหรับการวนซ้ำแต่ละครั้ง ดังนั้นเห็นได้ชัดว่ามีค่าใช้จ่ายบางส่วนด้วย
ศีล

1
การเป็นนักพัฒนาฉันแทบจะไม่ได้ใช้หรือมองหน้างานส่วนใหญ่ทำโดยใช้แผนที่กรองหรือลดวิธีการ
AT

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

1
@canon เห็นด้วยการเลือกลูปเป็นสิ่งสำคัญและควรคำนึงถึงผลลัพธ์และส่วนที่เหลือของวิธีการดังกล่าวในขณะที่เลือก ฉันเชื่อว่าควรหลีกเลี่ยง "for loops" สำหรับการอ่านแบบธรรมดา
AT

คำตอบ:


210

สำหรับ

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

for (var i=0, n=arr.length; i < n; ++i ) {
   ...
}

นี่ไม่ได้หมายความว่าสำหรับ -loops จะมีประสิทธิภาพมากกว่าเสมอไปเพียงแค่ที่เอ็นจิ้น JS และเบราว์เซอร์ได้ปรับแต่งให้เป็นเช่นนั้น ในช่วงหลายปีที่ผ่านมามีการประนีประนอมว่าโครงสร้างแบบวนซ้ำมีประสิทธิภาพมากกว่า (สำหรับในขณะที่ลดขณะย้อนกลับ ฯลฯ ) เบราว์เซอร์และเอ็นจิน JS ที่แตกต่างกันมีการใช้งานของตัวเองซึ่งเสนอวิธีการที่แตกต่างกันเพื่อให้ได้ผลลัพธ์ที่เหมือนกัน เนื่องจากเบราว์เซอร์ได้รับการปรับให้เหมาะสมยิ่งขึ้นเพื่อตอบสนองความต้องการด้านประสิทธิภาพในทางทฤษฎี[].forEachสามารถนำไปใช้ในลักษณะที่เร็วกว่าหรือเทียบได้กับไฟล์for.

สิทธิประโยชน์:

  • มีประสิทธิภาพ
  • การสิ้นสุดลูปในช่วงต้น (เกียรตินิยมbreakและcontinue)
  • การควบคุมเงื่อนไข ( i<nสามารถเป็นอะไรก็ได้และไม่ผูกมัดกับขนาดของอาร์เรย์)
  • กำหนดขอบเขตตัวแปร ( var iใบiใช้ได้หลังจากวงปลาย)

แต่ละ

.forEachเป็นวิธีการที่เน้นย้ำบนอาร์เรย์เป็นหลัก (รวมถึงการแจกแจงอื่น ๆ เช่นMapและSetอ็อบเจ็กต์) พวกเขามีความใหม่และให้รหัสที่เป็นผู้กระทำให้อ่านง่ายขึ้น ตัวอย่าง:

[].forEach((val, index)=>{
   ...
});

สิทธิประโยชน์:

  • ไม่เกี่ยวข้องกับการตั้งค่าตัวแปร (วนซ้ำในแต่ละองค์ประกอบของอาร์เรย์)
  • ฟังก์ชัน / ฟังก์ชันลูกศรกำหนดขอบเขตตัวแปรไปยังบล็อก
    ในตัวอย่างด้านบนvalจะเป็นพารามิเตอร์ของฟังก์ชันที่สร้างขึ้นใหม่ ดังนั้นตัวแปรใด ๆ ที่เรียกvalก่อนลูปจะเก็บค่าไว้หลังจากสิ้นสุด
  • สามารถบำรุงรักษาได้ง่ายขึ้นเนื่องจากอาจระบุได้ง่ายกว่าว่าโค้ดกำลังทำอะไรอยู่ซึ่งจะทำซ้ำมากกว่าจำนวนที่สามารถระบุได้ ในขณะที่สามารถใช้ for-loop สำหรับรูปแบบการวนซ้ำจำนวนเท่าใดก็ได้

ประสิทธิภาพ

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

การใช้ jQuery ในบางกรณีอาจช้าเกินไปในบางครั้ง (นักพัฒนาที่มีประสบการณ์อาจทราบเรื่องนั้น) ในขณะที่บางครั้งอาจไม่ใช่ปัญหาซึ่งในกรณีนี้การปฏิบัติตามข้อกำหนดข้ามเบราว์เซอร์ของไลบรารีและความสะดวกในการใช้งานฟังก์ชันอื่น ๆ (เช่น AJAX, การจัดการเหตุการณ์) จะคุ้มค่ากับเวลาในการพัฒนา (และการบำรุงรักษา) ที่ประหยัดได้

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

วิธีการ

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

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

for (var i=0; i < arr.length; ++i ){}

สำหรับการวนซ้ำแต่ละครั้ง JavaScript จะดึงการarr.lengthดำเนินการคิดต้นทุนการค้นหาคีย์ในแต่ละรอบ ไม่มีเหตุผลที่ไม่ควร:

for (var i=0, n=arr.length; i < n; ++i){}

สิ่งนี้ทำสิ่งเดียวกัน แต่จะดึงข้อมูลเพียงarr.lengthครั้งเดียวแคชตัวแปรและเพิ่มประสิทธิภาพโค้ดของคุณ


26
คำตอบที่ยอดเยี่ยมละเอียดถี่ถ้วนไม่เกรงใจไม่ผูกมัดกับจุดเดียวในเวลาการนำไปใช้งานหรือการทดสอบมาตรฐานระดับไมโคร

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

3
for-loop มักมีข้อได้เปรียบในแง่ของการดีบั๊ก: พวกมันเป็นเรื่องเล็กน้อยในการก้าวเข้าสู่เบรกพอยต์และตรวจสอบ ด้วย forEach () ระดับการเรียกกลับพิเศษอาจทำให้สิ่งต่างๆซับซ้อนขึ้นเล็กน้อย
Eric Grange

6
ฉันสนุกกับคำอธิบายในคำตอบและวลี[...], if performance and optimization was everything, there would be no other code than machine or assembly.นี้มาก ฉันเชื่อว่าด้วยletคำสั่งสำหรับการประกาศตัวแปรโลคัลขอบเขตการบล็อกประโยชน์ที่สองของforEachจะไม่ใช่ข้อได้เปรียบเหนือforลูปอีกต่อไปเว้นแต่ในสภาพแวดล้อมที่ไม่มีการสนับสนุนสำหรับlet.
user7393973

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