Почему использование break для выхода из цикла (кроме бесконечных циклов) считается антипаттерном?

168
11 октября 2021, 09:20

Допустим есть массив

const arr = [44, 22, 454, 213, 76, 83, 23, 44, 99];

Нужно проверить есть ли в массиве 2 и больше значений меньше 50. Я делаю это так:

let count = 0;
for (let i in arr ) {
  if (arr[i] < 50) {
    counter++;
    if (counter == 2) {
   // do something
     break;
   }
  }
 }

Как можно по другому правильно реализовать этот код? что-то нагуглить ничего не удалось

Answer 1

Использование break для выхода из цикла в общем случае НЕ является антипаттерном.

Избегать нужно следующих вариантов:

  1. Безусловный break:

    for (...) {
        // ...
        break;
    }
    
  2. Условный break, который можно вынести в условия цикла:

    while(foo < 5) {
        if (bar > 0) break; // головоломка
        // ...
    }
    while(foo < 5 && bar <= 0) { // вот так понятно
        // ...
    }
    

    Однако, из этого правила есть исключение - в том случае, когда условие цикла является идиомой, break использовать можно:

    for(var i=0; i<10; i++) { // идиоматичный цикл от 0 до 9
        if (bar > 0) break; // сойдёт
        // ...
    }
    for(var i=0; i<10 && bar <= 0; i++) { // тоже сойдёт
        // ...
    }
    
Answer 2

Используйте значение counter как условие выхода из цикла

let counter = 0;
let i=0;
for (i=0; i<arr.length && counter!=2 ;i++) {
  if (arr[i] < 50) {
    counter++;
    if (counter == 2) {
   // do something
   }
  }
 }
Answer 3

const arr = [44, 22, 454, 213, 76, 83, 23, 44, 99]; 
 
function arrLength(arr){ 
   let d = []; 
   let key; 
  for( key of arr ){ 
    if( key < 50 ){ 
      d.push(key); 
    } 
 } 
 console.log( `количество чисел меньше 50: ${d.length}`   ) 
} 
 
arrLength(arr)

const arr = [44, 22, 454, 213, 76, 83, 23, 44, 99]; 
let arr2 = []; 
for( let i = 0; i < arr.length; i++ ){ 
  if( arr[i] > 50 ) continue 
    arr2.push( arr[i]  ); 
    console.log(  `количество чисел ${arr2.length} : числа меньше 50: ${arr[i] }`   ) 
}