Циклы for с метками

let n = 10;

nextPrime:
for (let i = 2; i <= n; i++) { // Для всех i...

  for (let j = 2; j < i; j++) { // проверить, делится ли число..
    if (i % j == 0) continue nextPrime; // не подходит, берём следующее
  }

  alert( i ); // простое число

Объясните принцип работы этого примера. Думал забью на него и дальше как нибудь разберусь, но перешел к функциям (следующ. теме) и снова встретил давнего врага.

Я написал сам что то подобное, и что тут не так?

let num = 90;
firstFor: 
for(i = 8; i<num; i++) {
    for (k = 2; k < i; k=+2) {
      if(k === 12)  break firstFor
}
console.log(i)
}
let n = 10;

nextPrime: for (let i = 2; i <= n; i++) { // Для всех i...
  for (let j = 2; j < i; j++) { // проверить, делится ли число..
    if (i % j == 0) {
      continue nextPrime;
    } 
  }
  alert( i );
}

Что такое метка. Метка это способ переместиться либо в следующую итерацию цикла либо выйти из цикла. Синтаксически метка ставится перед циклом в виде ИМЯ_МЕТКИ: ТЕЛО ЦИКЛА. outerLoop: for (let i = 0; i < 10; i += 1) {console.log (i)}. continue ИМЯ_МЕТКИ переводит выполнение кода в начало цикла помеченного меткой. break ИМЯ_МЕТКИ прекращает выполнение цикла помеченного меткой.

Что такое простое число. Тут чтобы понять суть происходящего нужно освежить в памяти что такое простое число. Это которое делится на 1 и на само себя и более ни на что. Подход к решению - взять все числа от 2 до n, а потом проверить делится ли какое-то из них на нечто кроме самого себя. Если число делится только на само себя - значит оно простое.

Что происходит в коде примера. В нем описаны 2 цикла. Внешний цикл помечен меткой nextPrime. Внешний цикл бежит по натуральному ряду начиная с 2 (2, 3, 4, 5 …) чисел по n-ое число, и моделирует чисто которое будет проверяться на простоту. В переменной i записано значение из натурального ряда. Можно думать про i как про число-кандидата в простые. Внутренний цикл так же бежит по натуральному ряду чисел начиная с 2, но до i, и пытается поделить кандидата в простые значения на каждое значение от 2 до i. % операция которая дает значение остатка при делении левого значения на правое. Иначе говоря 2 % 3 вернет 2, 5 % 3 вернет 2, 8 % 2 вернет 0. Получается что если внутренний цикл дойдет до такого такого j, на которое i поделится без остатка i % j === 0, то число i не простое. Получается не имеет смысл продолжать итерировать, а нужно перейти к проверке следующего числа-кандидата. continue nextPrime перейдет к следующей итерации внешнего цикла. А вот если внутренний цикл завершился без перехода к верхнему, то выполнится код alert. То что внутренний цикл завершился без перехода к внешнему означает что i не смогло поделиться ни на одно от 2 до i, что и есть определение простого числа.


На практике метки почти никогда не нужны. Если не понимаешь их работы и твоя цель научиться писать программы, можно забить и двигаться дальше. Если же у тебя цель подготовиться к собеседованию, особенно на новичка-середнячка то метки стоит изучить на всякий случай.

На практике в 98% случаев когда мне нужно выйти из цикла не дожидаясь последней итерации я использую return. Разумеется, для этого фрагмент кода с циклом должен быть в функции.


Внутренний цикл получится бесконечным. Значение k не меняется потому что выражение k =+2 всегда записывает в k значение 2. Поменяй на += и заработает.


Подобные проблемы отлично отлавливаются с помощью отладчика, говоря ангилицзмом дебаггером. Вставляй debugger в ту строку где нужно интерпретатору остановиться, разберись со значением 3-4 кнопок (выполнить строку, выполнить скоуп, продолжить выполнение), и наслаждайся конкретными значениями переменных в любой момент в середи выполнения кода. В видео демке я пользуюсь кнопкой “выполнить следующее выражение” и “продолжить выполнение программы”. Вот так выглядит применение того что я описываю. Исполняемый код примера уже исправлен.

Screen Recording 2023-03-14 at 20.12.17

1 лайк

Спасибо. Очень помогли.

Спасибо, но еще кое что хочу спросить.
Вот i % j == 0. Что это значит? Если там будет написано !== 0.
Это четное/нечетное число?
Где при ==0 - четное - пропускаем итерацию и по новому кругу, где внешний цикл == 4 и внутренний 3?
и при !==0 - нечетное - спускаемся на alert