2011-08-24 55 views
54

Đọc qua nguồn jQuery tôi stumbled khi các đoạn mã sau đây (có sẵn here):Đối với vòng lặp thay vì vòng lặp while

for (; i < length;) { 
    if (callback.apply(object[i++], args) === false) { 
     break; 
    } 
} 

Tại sao một vòng lặp for sử dụng ở đây thay vì một vòng lặp while?

+6

Tôi tự hỏi liệu mã này có ngắn hơn khi được thu nhỏ không? Đó là mã khủng khiếp, và các nhân viên jQuery là những người thông minh, vì vậy tôi nghĩ rằng đó là vì mục đích rút gọn. –

+9

Xóa tất cả khoảng trắng, phiên bản của @ aroth ngắn hơn. Bất kỳ tên biến nào có thể rút ngắn được sử dụng một số lần bằng nhau. Có thể thậm chí còn ngắn hơn. 'while (i user113716

+0

Có thể lập luận rằng việc thay thế tất cả các vòng lặp với dạng thức này trong mã được nén nhỏ hơn sẽ tốt hơn. Mặc dù vậy, không biết đó là những gì họ nghĩ đến. –

Trả lời

44

Tôi bỏ phiếu cho một người có ái lực với kiểu mã hóa kém. Đó là lời giải thích duy nhất tôi có thể thấy cho cả hai vòng lặp fori++ được đặt bên trong một chỉ số mảng. Tôi nghĩ rằng đây sẽ là tốt hơn:

while (i < length && callback.apply(object[i], args)) { 
    i++; 
} 

Hoặc nếu bạn tình cờ cảm thấy rằng các === điều hành trong ví dụ ban đầu có giá trị, sau đó:

while (i < length && callback.apply(object[i], args) !== false) { 
    i++; 
} 

Một lý do khác có thể để làm điều này có thể có được như tối ưu hóa hiệu suất. Mặc dù điều này nhanh chóng benchmark mà tôi đặt lại với nhau dường như bác bỏ lý thuyết đó. Trên Windows, vòng lặp while ở trên nhanh hơn 20% so với vòng lặp ban đầu for trong Chrome, trong IE và Firefox cả hai vòng lặp đều giống nhau. Trên OS X, vòng lặp for có lợi thế 10% trong Firefox, không có sự khác biệt giữa hai trong Chrome và Safari thích vòng lặp while thêm 6%.

Vì vậy, từ quan điểm hiệu suất, đó là việc rửa. Nếu bất cứ điều gì sau đó đánh giá theo thị phần bạn có thể muốn tối ưu hóa cho Chrome trên Windows trước khi tối ưu hóa cho Firefox trên Mac, trong trường hợp này, vòng lặp while sẽ được ưu tiên hơn.

Điều đó nói với tôi rằng không chắc rằng tối ưu hóa hiệu suất đã đóng một yếu tố với mã này. Và tôi quay trở lại lý thuyết ban đầu của mình rằng nó chỉ là một ví dụ về phong cách mã hóa kém khiến nó vượt qua quá trình xem xét mã.

+4

Kiểm tra 'sai' nghiêm ngặt là cần thiết vì đó là giá trị trả về * one * sẽ phá vỡ phép lặp. – user113716

+0

Chẳng phải 'tôi' sẽ là 1 trong ví dụ của bạn sao? – AnteSim

+0

Phiên bản thứ hai là bắt buộc để tương đương với bản gốc trong trường hợp cuộc gọi lại có thể trả về 'undefined' hoặc' 0'. Phiên bản đầu tiên sẽ không hoạt động giống nhau trong những trường hợp đó. – jfriend00

2

Tôi nhận thấy rằng những điều như thế này xảy ra khi tôi viết lại mọi thứ hoặc nếu nhiều người chạm vào một đoạn mã. Không thể thấy bất kỳ lý do cụ thể nào cho nó.

Tôi hy vọng i được khởi chạy đúng cách trên khối này.

6

Trước tiên, có bao giờ là một chi phí thời gian cho việc sử dụng một vòng lặp for qua một vòng lặp while, nhưng bạn sẽ có được chức năng bổ sung với for vòng lặp, vì vậy một số lập trình viên luôn sử dụng for:

for(;<condition>;){} 
while(<condition>){} 

Điều đó nói rằng, tôi nghĩ mục đích ở đây có thể là nhất quán với mã xung quanh.

Ví dụ: đây là một phần của mã gốc. Như bạn có thể thấy, trong mã này bạn có thể ở lại "cho" chế độ vòng lặp suy nghĩ trong suốt thời gian, vì vậy nó cảm thấy nhất quán hơn:

if (args) { 
    if (isObj) { 
     for (name in object) { 
      if (callback.apply(object[name], args) === false) { 
       break; 
      } 
     } 
    } else { 
     for (; i < length;) { 
      if (callback.apply(object[i++], args) === false) { 
       break; 
      } 
     } 
    } 
} 

Hãy so sánh này để thay thế cho vòng lặp thứ hai với một while.Khi bạn đọc mã này, bạn phải chuyển từ chế độ vòng lặp "for" cho chế độ vòng lặp "while" của suy nghĩ. Bây giờ tôi không biết về bạn, nhưng tôi tìm thấy nó nhanh hơn một chút cho đôi mắt của tôi để chuyển đổi giữa các điều kiện vòng lặp ở trên như trái ngược với các điều kiện vòng lặp dưới đây. Điều này là do trong trường hợp trên, chúng tôi chỉ có thể tập trung vào các điều kiện, trong khi trong trường hợp bên dưới mắt tôi bị thu hút vào đọc lại whilefor mỗi lần, vì họ là khác nhau:

if (args) { 
    if (isObj) { 
     for (name in object) { 
      if (callback.apply(object[name], args) === false) { 
       break; 
      } 
     } 
    } else { 
     while (i < length) { 
      if (callback.apply(object[i++], args) === false) { 
       break; 
      } 
     } 
    } 
} 
0

Các ngắn nhất và trung thực nhất câu trả lời là khá ngắn "chỉ vì". Hoàn toàn không có lý do thực tế để làm điều đó, chúng tôi không đạt được bất kỳ lợi nhuận nào từ vòng lặp 2 nụ cười đó.

Đối với những lý do nêu trên, chẳng hạn như:

  • refactoring - đó là nhiều nhất có thể, tuy nhiên đây không phải là một cái cớ.
  • cân nhắc rút gọn - ít hơn, ít khả thi hơn.
  • vấn đề về tâm lý/khả năng đọc/mã hỗ trợ - Tôi rất ngờ vực rằng ai đó viết mã như vậy lưu ý rằng người dùng có thể bị nhầm lẫn với một số công trình mã và tập trung lỏng lẻo;

cũng vì những lý do này - tất cả đều đáng nhắc đến, nhưng, thành thật mà nói, kiểu mã jquery là, tốt, không lý tưởng. Đôi khi có lý do tại sao nó như vậy, một số lần, nó chỉ là một vấn đề của thực tế.

Mã sản xuất không phải lúc nào cũng là mã đẹp nhất. Đọc mã sản xuất sẵn sàng, hardcore trên bất kỳ ngôn ngữ nào luôn tốt, nhưng không phải là 100% về kiểu mã. Nói, vim là phần mềm rất đẹp, rất mạnh mẽ, nhưng (đối với tôi) một số người thuần túy có thể ngạc nhiên với mã nguồn. Mặc dù các công cụ vòng lặp là ok))))

21

Đây là the commit that introduced this oddity.

Commit nhắn: lõi

jquery: giảm mã tại $.each$.curCSS.

Snip từ diff:

-  for (var i = 0, length = object.length; i < length; i++) 
-   if (callback.apply(object[ i ], args) === false) 
+  for (; i < length;) 
+   if (callback.apply(object[ i++ ], args) === false) 

Nó sẽ xuất hiện mà tác giả chỉ đơn giản là bỏ lỡ cơ hội để thay đổi for thành một while.

+0

cuộc gọi tốt. điều này có vẻ như là câu trả lời có khả năng nhất. – wprl

0

Vì vậy, t sẽ chạy ít nhất một lần, vì nếu bạn sử dụng vòng lặp while nếu logic sai thì nó sẽ không chạy. Đối với lopp ngay cả khi nó là sai nó sẽ chạy ít nhất một lần.

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