Sự khác biệt giữa vòng lặp forEach và for of trong JavaScript là gì?

Một lần, chúng tôi đã phỏng vấn một ứng viên vị trí nhà phát triển tầm trung không thể trả lời một câu hỏi đơn giản liên quan đến vòng lặp

function generateTestArray[] {
  const result = [];
  for [let i = 0; i < 1000000; ++i] {
    result.push[{
      a: i,
      b: i / 2,
      r: 0,
    }];
  }
  return result;
}
6. Anh ấy giải thích rằng anh ấy chỉ viết mã khai báo và không còn ích lợi gì trong lập trình mệnh lệnh nữa. Mặc dù chúng tôi đồng ý một phần, nhưng điều đó khiến chúng tôi phải suy nghĩ. “Các lập trình viên có nên luôn ưu tiên các phương thức Mảng
function generateTestArray[] {
  const result = [];
  for [let i = 0; i < 1000000; ++i] {
    result.push[{
      a: i,
      b: i / 2,
      r: 0,
    }];
  }
  return result;
}
7,
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
0 và
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
1 hơn các vòng lặp đơn giản trong JavaScript không?”

Phong cách lập trình khai báo rất biểu cảm, dễ viết hơn và dễ đọc hơn nhiều. Nó tốt hơn 99% thời gian, nhưng không phải khi hiệu suất quan trọng. Các vòng lặp thường nhanh hơn ba lần hoặc hơn so với các vòng lặp khai báo của chúng. Nó không tạo ra sự khác biệt đáng kể trong hầu hết các ứng dụng. Tuy nhiên, khi xử lý lượng lớn dữ liệu trong một số ứng dụng kinh doanh thông minh, xử lý video, tính toán khoa học hoặc công cụ trò chơi, điều này sẽ ảnh hưởng lớn đến hiệu suất tổng thể

Chúng tôi đã chuẩn bị một số bài kiểm tra để chứng minh điều đó. Tất cả mã có sẵn trên GitHub. Hãy chơi xung quanh với nó

Chúng tôi rất thích phản hồi và đóng góp của bạn

Mục lục

  • Về các bài kiểm tra
  • Mảng. forEach so với cho và cho. của
  • Mảng. bản đồ vs cho vs cho. của
  • Mảng. giảm so với cho và cho. của
  • Phần kết luận

Về các bài kiểm tra

Ứng dụng thử nghiệm sử dụng thư viện điểm chuẩn để có được kết quả có ý nghĩa thống kê. Đầu vào cho các bài kiểm tra là một mảng gồm một triệu đối tượng có cấu trúc

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
2. Đây là mã tạo ra mảng này

function generateTestArray[] {
  const result = [];
  for [let i = 0; i < 1000000; ++i] {
    result.push[{
      a: i,
      b: i / 2,
      r: 0,
    }];
  }
  return result;
}

Chúng tôi sử dụng máy tính xách tay Lenovo T480s với Intel Core i5-8250, RAM 16Gb chạy Ubuntu 20. 04 LTS với Nút v14. 16. 0 để lấy kết quả

Mảng. forEach so với cho và cho. của

Hoạt động mỗi giây, cao hơn là tốt hơn

Thử nghiệm này tính toán tổng của

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
3 và
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
4 cho mọi phần tử mảng và lưu nó vào
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
5

array.forEach[[x] => {
   x.r = x.a + x.b;
}];

Chúng tôi đã cố tình tạo một trường

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
5 trong đối tượng trong quá trình tạo mảng để tránh thay đổi cấu trúc đối tượng vì nó sẽ ảnh hưởng đến điểm chuẩn

Ngay cả với những thử nghiệm đơn giản này, các vòng lặp nhanh hơn gần ba lần. Vòng lặp

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
7 nhỉnh hơn một chút so với phần còn lại, nhưng sự khác biệt không đáng kể. Tối ưu hóa vi mô của vòng lặp
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8 hoạt động ở một số ngôn ngữ khác, như lưu vào bộ đệm độ dài mảng hoặc lưu trữ một phần tử để truy cập lặp lại trong một biến tạm thời, không có tác dụng trong JavaScript chạy trên V8. Có lẽ V8 đã làm chúng dưới mui xe

Vì vòng lặp

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
1 không khác lắm so với vòng lặp
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
7, nên trong hầu hết các trường hợp, chúng tôi không thấy có ý nghĩa gì khi sử dụng nó thay cho vòng lặp truyền thống. Nó chỉ đáng sử dụng khi bạn đã có một hàm để gọi trên mọi phần tử mảng. Trong trường hợp này, đó là một lớp lót, không có sự suy giảm hiệu suất

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
3

Mảng. bản đồ vs cho vs cho. của

Hoạt động mỗi giây, cao hơn là tốt hơn

Các thử nghiệm này ánh xạ mảng này sang một mảng khác với

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
31 cho mỗi phần tử

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
5

Các vòng lặp ở đây cũng nhanh hơn nhiều.

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
7 tạo một mảng trống và
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
33-es mọi phần tử mới

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8

Đó không phải là cách tiếp cận tối ưu vì mảng được phân bổ lại động và di chuyển dưới mui xe. Phiên bản

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8 phân bổ trước mảng với kích thước mục tiêu và đặt mọi phần tử bằng cách sử dụng chỉ mục

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
0

Ở đây, chúng tôi cũng đã kiểm tra xem việc phá hủy có ảnh hưởng gì đến hiệu suất hay không. Với

function generateTestArray[] {
  const result = [];
  for [let i = 0; i < 1000000; ++i] {
    result.push[{
      a: i,
      b: i / 2,
      r: 0,
    }];
  }
  return result;
}
7, điểm chuẩn giống hệt nhau và với
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
7, kết quả không khác nhiều và có thể chỉ là điểm chuẩn

Mảng. giảm so với cho và cho. của

Hoạt động mỗi giây, cao hơn là tốt hơn

Ở đây ta chỉ tính tổng của

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
3 và
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
4 cho cả mảng

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
4

Cả

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8 và
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
7 đều là 3. Nhanh gấp 5 lần so với
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
51. Tuy nhiên, các vòng lặp dài dòng hơn nhiều

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8

Viết nhiều dòng mã đó chỉ cho một khoản tiền đơn giản phải có lý do chính đáng, vì vậy trừ khi hiệu suất quá quan trọng, thì

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
0 vẫn tốt hơn nhiều. Các thử nghiệm một lần nữa cho thấy không có sự khác biệt giữa các vòng lặp

Phần kết luận

Các điểm chuẩn đã chứng minh rằng lập trình bắt buộc với các vòng lặp mang lại hiệu suất tốt hơn so với sử dụng các phương thức Array tiện lợi. Gọi hàm gọi lại không miễn phí và bổ sung cho các mảng lớn. Tuy nhiên, đối với mã phức tạp hơn một tổng đơn giản, sẽ không có nhiều sự khác biệt tương đối vì bản thân các phép tính sẽ mất nhiều thời gian hơn

Mã mệnh lệnh dài dòng hơn rất nhiều trong hầu hết các trường hợp. Năm dòng mã cho một tổng đơn giản là quá nhiều và

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
51 chỉ là một lớp lót. Mặt khác,
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
1 gần giống như
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8 hoặc
array.forEach[[x] => {
   x.r = x.a + x.b;
}];
7, chỉ chậm hơn. Không có nhiều sự khác biệt về hiệu suất giữa hai vòng lặp và bạn có thể sử dụng bất kỳ thuật toán nào phù hợp hơn với thuật toán

Không giống như trong AssemblyScript, tối ưu hóa vi mô của vòng lặp

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
8 không có ý nghĩa đối với mảng trong JavaScript. V8 đã làm rất tốt và thậm chí có thể loại bỏ cả việc kiểm tra ranh giới

Phân bổ trước một mảng có độ dài đã biết nhanh hơn nhiều so với việc dựa vào tăng trưởng động với

array.forEach[[x] => {
   x.r = x.a + x.b;
}];
33. Chúng tôi cũng đã xác nhận rằng việc hủy bỏ là miễn phí và nên được sử dụng bất cứ khi nào thuận tiện.

Các nhà phát triển giỏi nên biết mã hoạt động như thế nào và chọn giải pháp tốt nhất trong mọi tình huống. Lập trình khai báo, với sự đơn giản của nó, chiếm phần lớn thời gian. Viết mã cấp thấp hơn chỉ có ý nghĩa trong hai trường hợp

Sự khác biệt giữa vòng lặp forEach và for là gì?

Vòng lặp For thực thi một khối mã cho đến khi một biểu thức trả về false trong khi vòng lặp ForEach thực thi một khối mã thông qua các mục trong bộ sưu tập đối tượng . Vòng lặp for có thể thực thi với các bộ sưu tập đối tượng hoặc không có bất kỳ bộ sưu tập đối tượng nào trong khi vòng lặp ForEach chỉ có thể thực thi với các bộ sưu tập đối tượng.

Cái nào nhanh hơn for loop hoặc forEach JS?

Vòng lặp while với số lần giảm khoảng 1. Chậm hơn 5 lần so với vòng lặp for. Một vòng lặp sử dụng chức năng gọi lại [như forEach tiêu chuẩn], chậm hơn khoảng 10 lần so với vòng lặp for

Chủ Đề