Почему в бесконечном цикле при отмене ввода, цикл все равно продолжает работать?

Есть такое задание: Напишите цикл, который предлагает prompt ввести число, большее 100. Если посетитель ввёл другое число – попросить ввести ещё раз, и так далее.

Цикл должен спрашивать число пока либо посетитель не введёт число, большее 100, либо не нажмёт кнопку Отмена (ESC).

Я написал такой код

outer: while (true) {
  let value = +prompt('Введите число больше 100?', 0);
  
  if (value < 100) {
    continue outer;
  } else if (!value || value > 100) {
    break outer;
  }
}

Почему при отмене все равно выводится промт?


Ответы (2 шт):

Автор решения: Grundy

При нажатии кнопки отмена prompt возвращает null, который при приведении к числу превращается в 0.

таким образом, выбирается вариант value < 100 и цикл не заканчивается.

Проверять на null стоит до приведения к числу:

outer: while (true) {
  let value = prompt('Введите число больше 100?', 0);
  
  if (value == null)  break outer;

  value = +value;
  if (value < 100) {
    continue outer;
  } else if (!value || value > 100) {
    break outer;
  }
}
→ Ссылка
Автор решения: EzioMercer

Замечания:

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

  • При отмене приходит null, который превращатся в 0, потому срабатывает value < 100

  • На null надо проверять до приведения к числу, так вы сможете отличить 0 и null

  • Если ввести строку, которая не переводится в число, например 'qwe', то он вместо числа запишет NaN, потому проверку на него тоже надо делать

  • Писать else после break/continue, в цикле, так же бессмыслленно как в функциях писать else после return-а, потому его можно убрать

Учитывая замечания, ваш код можно написать так:

while (true) {
  const value = prompt('Введите число больше 100?', 0);
  
  if (value === null) break;
  
  const valueAsNum = Number(value);
  
  if (isNaN(valueAsNum) || valueAsNum > 100) break;
  
  if (valueAsNum < 100) continue; //Эту строку можно убрать, если нет дополнительной логики
}

→ Ссылка