Hiệu quả của Javascript: 'for' so với 'forEach' [đã đóng]


103

Tiêu chuẩn hiện tại trong năm 2017 trong Javascript là gì với vòng lặp for () so với .forEach.

Tôi hiện đang làm việc theo cách của mình thông qua Colt Steeles "Web Dev Bootcamp" trên Udemy và ông ủng hộ forEachtrên fortrong bài giảng của ngài. Tuy nhiên, tôi đã tìm kiếm nhiều thứ khác nhau trong các bài tập như một phần của khóa học và tôi thấy ngày càng nhiều khuyến nghị sử dụng a for-loop hơn làforEach . Hầu hết mọi người dường như nói rằng vòng lặp for hiệu quả hơn.

Đây có phải là điều gì đó đã thay đổi kể từ khi khóa học được viết (khoảng năm 2015) hay thực sự ưu nhược điểm của chúng đối với từng cái, cái nào rút kinh nghiệm sẽ rõ hơn.

Bất kỳ lời khuyên sẽ được đánh giá rất cao.


11
Tại sao lại tự trói mình vào ý tưởng chủ quan của ai đó về tiêu chuẩn năm 2017? Áp dụng một tiêu chuẩn vượt thời gian, giống như viết sạch, mã duy trì, biết rằng các kỹ sư đang nỗ lực để làm cho các cấu trúc phổ biến nhất được sử dụng rất hiệu quả, và sau đó tối ưu hóa cho hiệu suất khi bạn gặp rắc rối hoạt động cụ thể

2
Một người bản địa forrất khó đánh bại vì tốc độ thuần túy. forEach()gọi lại cho mỗi lần lặp lại; vì vậy, điều đó rõ ràng mang theo một số chi phí.
canon

1
là một nhà phát triển mà tôi hầu như không sử dụng hoặc nói trước, hầu hết công việc được thực hiện bằng các phương pháp bản đồ, lọc hoặc thu nhỏ.
AT

12
@AT miễn là bạn không phải là một trong những người sử dụng maphoàn toàn để lặp lại và loại bỏ mảng mới mà nó tạo ra. Tôi không biết có bao nhiêu người mà tôi đã phải sửa lựa chọn chức năng cụ thể đó chỉ trên trang web này.
canon

1
@canon đã đồng ý, lựa chọn vòng lặp là quan trọng và người ta nên lưu ý đầu ra và dư lượng của các phương pháp đó trong khi lựa chọn. Tôi tin rằng nên tránh "vòng lặp for" để dễ đọc.
AT

Câu trả lời:


198

cho

forvòng lặp hiệu quả hơn nhiều. Nó là một cấu trúc lặp được thiết kế đặc biệt để lặp lại trong khi một điều kiện là đúng , đồng thời cung cấp một cơ chế bước (nói chung là để tăng trình lặp). Thí dụ:

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

Điều này không có nghĩa là for -loops sẽ luôn hiệu quả hơn, chỉ là các công cụ JS và trình duyệt đã tối ưu hóa chúng để trở nên như vậy. Trong những năm qua, đã có những thỏa hiệp về việc cấu trúc lặp nào hiệu quả hơn (cho, trong khi, giảm, đảo ngược trong khi, v.v.) - các trình duyệt và công cụ JS khác nhau có các triển khai riêng cung cấp các phương pháp khác nhau để tạo ra kết quả giống nhau. Khi các trình duyệt tối ưu hóa hơn nữa để đáp ứng nhu cầu hiệu suất, về mặt lý thuyết [].forEachcó thể được triển khai theo cách nhanh hơn hoặc có thể so sánh với a for.

Những lợi ích:

  • Có hiệu quả
  • chấm dứt sớm vòng lặp (danh hiệu breakcontinue)
  • điều khiển điều kiện ( i<ncó thể là bất kỳ thứ gì và không bị ràng buộc với kích thước của một mảng)
  • biến Phạm vi ( var iicó sẵn sau khi vòng lặp kết thúc)

cho mỗi

.forEachlà các phương thức chủ yếu lặp qua các mảng (cũng trên các kiểu liệt kê khác, chẳng hạn như MapSetđối tượng). Chúng mới hơn và cung cấp mã dễ đọc hơn về mặt chủ quan. Thí dụ:

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

Những lợi ích:

  • không liên quan đến thiết lập biến (lặp qua từng phần tử của mảng)
  • functions / arrow-functions phạm vi biến tới khối
    Trong ví dụ trên, valsẽ là một tham số của hàm mới được tạo. Do đó, bất kỳ biến nào được gọi valtrước vòng lặp, sẽ giữ giá trị của chúng sau khi nó kết thúc.
  • về mặt chủ quan dễ bảo trì hơn vì có thể dễ dàng hơn để xác định mã đang làm gì - nó lặp lại trên một liệt kê; trong khi vòng lặp for có thể được sử dụng cho bất kỳ số lượng sơ đồ lặp nào

Hiệu suất

Hiệu suất là một chủ đề phức tạp, thường đòi hỏi một số kinh nghiệm khi suy nghĩ trước hoặc tiếp cận. Để xác định trước (trong khi phát triển) mức độ tối ưu hóa có thể được yêu cầu, một lập trình viên phải có một ý tưởng tốt về kinh nghiệm trong quá khứ với trường hợp vấn đề, cũng như hiểu rõ về các giải pháp tiềm năng.

Việc sử dụng jQuery trong một số trường hợp đôi khi có thể quá chậm (một nhà phát triển có kinh nghiệm có thể biết điều đó), trong khi những trường hợp khác có thể không phải là vấn đề, trong trường hợp này, thư viện tuân thủ nhiều trình duyệt và dễ dàng thực hiện các chức năng khác (ví dụ: AJAX, xử lý sự kiện) sẽ đáng để tiết kiệm thời gian phát triển (và bảo trì).

Một ví dụ khác là, nếu hiệu suất và tối ưu hóa là tất cả mọi thứ, sẽ không có mã nào khác ngoài máy hoặc lắp ráp. Rõ ràng là không phải như vậy vì có nhiều ngôn ngữ cấp cao và cấp thấp khác nhau, mỗi ngôn ngữ đều có sự cân bằng của riêng chúng. Những sự cân bằng này bao gồm, nhưng không giới hạn ở sự chuyên môn hóa, tính dễ dàng và tốc độ phát triển, sự dễ dàng và tốc độ bảo trì, mã được tối ưu hóa, mã không có lỗi, v.v.

Tiếp cận

Nếu bạn không hiểu rõ liệu thứ gì đó sẽ yêu cầu mã được tối ưu hóa, thì thông thường, trước tiên bạn nên viết mã có thể bảo trì được. Từ đó, bạn có thể kiểm tra và xác định những gì cần chú ý hơn khi nó được yêu cầu.

Điều đó nói rằng, một số tối ưu hóa rõ ràng nhất định nên là một phần của thực tiễn chung và không cần phải suy nghĩ. Ví dụ, hãy xem xét vòng lặp sau:

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

Đối với mỗi lần lặp lại của vòng lặp, JavaScript đang truy xuất arr.length, một thao tác tính phí tra cứu khóa trên mỗi chu kỳ. Không có lý do gì khiến điều này không nên xảy ra:

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

Điều này thực hiện tương tự, nhưng chỉ truy xuất arr.lengthmột lần, lưu vào bộ nhớ đệm của biến và tối ưu hóa mã của bạn.


22
Câu trả lời xuất sắc, kỹ lưỡng, không tự phụ, không bị ràng buộc vào một điểm duy nhất về thời gian, cách thực hiện hoặc bài kiểm tra vi điểm.

1
Hoàn hảo, đó chính xác là những gì tôi đang tìm kiếm và cung cấp nhiều chiều sâu hơn video có thể. Tôi thực sự đánh giá cao điều này, là người mới có rất nhiều điều để học hỏi và đây là những điều dễ dàng bỏ qua nếu chỉ thích cái này hơn cái kia mà không có lý do gì có thể cản trở bạn trong tương lai. Cảm ơn nhiều!
tonyrobbins

2
vòng lặp for thường có lợi thế hơn về mặt gỡ lỗi: chúng là trivila để bước vào, ngắt và kiểm tra. Với forEach (), mức gọi lại bổ sung có thể phức tạp hơn một chút.
Eric Grange

1
@FelipeBuccioni cảm ơn bạn, tôi thực sự sẽ xem xét điều đó vì tôi nghĩ rằng các công cụ hiện kiểm tra xem một mảng có bị đột biến hay không để xác định xem độ dài có được lưu vào bộ nhớ đệm hay không. Mặc dù vậy, đối với các mục đích kế thừa, tôi nghĩ rằng các công cụ tối ưu hóa không rộng rãi và độ dài là một tác động đến hiệu suất trên mỗi lần lặp. Tôi sẽ xem qua bài viết của bạn và đưa nó vào câu trả lời khi tôi có thời gian, hoặc hy vọng một thành viên xuất sắc của cộng đồng sẽ sửa đổi dưới dạng chỉnh sửa cho tôi :)
vol7ron

6
Tôi thực sự thích lời giải thích trong câu trả lời này và cụm từ [...], if performance and optimization was everything, there would be no other code than machine or assembly.. Tôi tin rằng với letcâu lệnh khai báo biến cục bộ phạm vi khối, lợi ích thứ hai của forEachkhông còn là lợi thế so với forvòng lặp trừ khi trong môi trường không có hỗ trợ let.
user7393973
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.