2012-03-09 27 views
16

Hầu hết các trường hợp sử dụng của phương thức reduce() có thể được viết lại dễ dàng bằng vòng lặp for. Và thử nghiệm trên JSPerf cho thấy rằng giảm() thường chậm hơn 60% -75%, tùy thuộc vào các hoạt động được thực hiện bên trong mỗi lần lặp.Có lợi ích thực sự nào khi sử dụng phương thức javascript Array reduce() không?

Có lý do thực sự nào để sử dụng hàm reduce() sau đó, ngoài việc có thể viết mã theo 'kiểu chức năng'? Nếu bạn có thể đạt được hiệu suất 60% bằng cách viết thêm một chút mã, tại sao bạn lại sử dụng reduce()?

EDIT: Trên thực tế, các phương thức chức năng khác như forEach() và map() đều hiển thị hiệu suất tương tự, chậm hơn ít nhất 60% so với đơn giản cho các vòng lặp.

Dưới đây là một liên kết đến bài kiểm tra JSPerf (với chức năng cuộc gọi): forloop vs forEach

Trả lời

5
  • Bạn có thể muốn xác định phạm vi. Ví dụ bạn có thể muốn thực hiện chức năng gọi lại hoặc có tham chiếu đến đối tượng javascript. Để biết thêm thông tin, hãy xem tại sao javascript không bị chặn phạm vi. [chỉnh sửa: javascript hiện tại hiện hỗ trợ let biến. Quay trở lại trước ESv6, khi bạn khai báo biến số var, nó đã được hoisted như thể nó được viết ở trên cùng của khóa mã hàm, do đó bạn thường phải viết các phần của vòng lặp như các hàm. Điều này sau vẫn áp dụng mặc dù:] Nếu bạn đã có một chức năng bằng văn bản, cũng có thể sử dụng phong cách chức năng, trừ khi đó là một nút cổ chai đáng kể.
  • Mã của bạn không phải lúc nào cũng cần chạy ở tốc độ máy đầy đủ. Bạn thậm chí không thể tối ưu hóa mã trong nút cổ chai.
  • Ngoài ra, bạn không cung cấp "thử nghiệm trên JSPerf" để chúng tôi có thể phê bình nó. Ví dụ, nếu bạn đã có một chức năng giảm (hoặc bản đồ hoặc forEach chức năng), sau đó tôi đặt cược hiệu suất sẽ là ngang hàng. Thậm chí nếu không, phương pháp thử nghiệm có thể không hoàn thiện, đặc biệt khi nhiều trình duyệt có thể tối ưu hóa khác nhau hoặc có chức năng gọi điện trên cao khác nhau.

sidenote: đây là một so sánh hiệu suất hợp lệ giữa cú pháp, nhưng một sự so sánh hiệu suất không hợp lệ trong khi cú pháp không phải là câu hỏi trong tầm tay:

myArray.map(function(x){return x+1}) 

// ...versus... 

for(var i=0; i<myArray.length; i++) { 
    myArray[i] = myArray[i]+1; 
} 

Đây sẽ là một so sánh hiệu suất hợp lệ:

myArray.forEach(function(x){return x+1}) 

// ...versus... 

var plusOne = function(x){return x+1}; 
for(var i=0; i<myArray.length; i++) { 
    plusOne(myArray[i]); 
} 

// (may need a side-effect if the compiler is smart enough to optimize this) 

(Cũng trong bài trả lời để chỉnh sửa của bạn: .forEach().map() cung cấp rõ ràng hơn rất nhiều, và tránh sự cần thiết cho vòng lặp rõ ràng int i=0; i<array.length; i++ đối số.)

+2

Tôi không đồng ý với bạn về những gì cấu thành so sánh hiệu suất hợp lệ. _first_ là so sánh hợp lệ, bởi vì chắc chắn (ví dụ của bạn) câu hỏi là "Phương pháp nào là nhanh nhất khi thêm một phần tử vào mỗi mảng?", Không phải "Phương thức nào là nhanh nhất nhưng bất kỳ phương thức nào không sử dụng lệnh gọi hàm đều bị loại từ mục nhập ". Tôi sẽ đồng ý rằng nếu bạn cho rằng bạn muốn có một hàm cho mục đích scoping/closure thì bạn cũng có thể sử dụng '.reduce()' hoặc '.forEach()' hoặc bất cứ thứ gì. – nnnnnn

+0

Câu hỏi này là chính xác về cú pháp, vì vậy nó là một so sánh hiệu suất hợp lệ. Có lẽ tôi nên thuật lại câu hỏi trong một kịch bản mà bạn muốn siết chặt mọi hiệu suất có thể. Trong trường hợp đó tôi không thể tìm ra lý do chính đáng để không sử dụng đồng bằng cho vòng lặp. Bạn có thể cung cấp một ví dụ cụ thể trong đó phạm vi là hoàn toàn cần thiết? –

+0

@EvanYou: '[1,2,3].forEach (function (x) {setTimeout (function() {alert (x)}, 1000)}) '(cảnh báo 1,2,3) so với' for (var i = 0; i <4; i ++) {setTimeout (function() {alert (i)}, 1000)} '(cảnh báo 4,4,4) – ninjagecko

Các vấn đề liên quan