Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Цикл for и изменение переменных Введение в программирование

Видео может быть заблокировано из-за расширений браузера. В статье вы найдете решение этой проблемы.

Транскрипт урока

Этот урок будет быстрым и простым, так что пристегнитесь.

Вызовем функцию факториала с циклом while:

const factorial = (n) => {
  let counter = 1;
  let result  = 1;

  while (counter <= n) {
    result = result * counter;
    counter = counter + 1;
  }

  return result;
}

Когда мы работаем с переменными, мы часто поступаем так: меняем их значения, прибавляя к ним сколько-нибудь или умножая их на что-то. Или просто прибавляем или вычитаем единицу.

Как и во многих других языках программирования в JavaScript есть для этого упрощенные формы.

Вместо result = result * counter вы можете сказать result *= counter. Результат будет тот же самый, это просто способ сократить запись. Точно так же вы можете поступить со знаками плюс, минус и остатком от деления:

result *= counter;    // то же, что result = result * counter
result += counter;    // то же, что result = result + counter
result -= counter;    // то же, что result = result - counter
result %= counter;    // то же, что result = result % counter
result /= counter;    // то же, что result = result / counter

Добавление единицы к переменной — тоже очень типичная операция, поэтому вместо counter = counter + 1 можно записать counter++. Так же для минуса — counter = counter - 1 равносильно counter--. Это операторы инкрементирования и декрементирования.

Есть два вида, проще их понять на примере:

// Postfix
let a = 3;
let b;
b = a++;    // b = 3, a = 4

// Prefix
let a = 3;
let b;
b = ++a;    // b = 4, a = 4

Если вы поставите ++ после имени переменной — это постфиксная нотация — то фактическое сложение произойдёт после того, как значение вернётся. Вот почему b тут 3: оно получает значение перед тем как меняется a.

Если вы поставите ++ перед именем переменной — это префиксная нотация — то фактическое сложение произойдёт перед тем, как значение вернётся. Вот почему b тут 4: оно получает значение после того как меняется a.

Но в конце в обоих случаях a становится 4.

Это обновлённая функция факториала:

const factorial = (n) => {
  let counter = 1;
  let result  = 1;

  while (counter <= n) {
    result *= counter;
    counter++;
  }

  return result;
}

Здесь не имеет значения, используем мы префикс или постфикс когда инкрементируем counter, потому что значение не хранится больше нигде.

Этот код немного проще и короче. Иметь цикл — этот повторяющийся код — со счётчиком контролирующим повторения — распространённый в программировании приём. Поэтому кроме цикла while существует цикл for. В нем есть встроенные счетчики.

Это та же функция факториала, но с циклом for вместо цикла while:

const factorial = (n) => {
  let result  = 1;

  for (let counter = 1; counter <= n; counter++) {
    result *= counter;
  }

  return result;
}

Здесь три момента:

  1. Инициализация счётчика.
  2. Условие цикла. Так же как и в цикле while, этот цикл будет повторяться пока это условие истинно.
  3. Обновление счётчика. Как менять счётчик в каждом шаге.

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

Пришло время использовать все эти навороченные знания и написать код! Переходите к тесту и упражнению прямо сейчас!

Дополнение к уроку

Скрытые сложности

Операции декремента и инкремента кажутся мощными механизмами, но их использование привносит ненужную сложность в программы. Код, написанный с их использованием, часто превращается в ребус. Попробуйте ответить, чему равно значение:

let x = 5;
let y = 10;

console.log(x++ + ++y);

Как видите, этот код заставляет думать, так как кроме арифметических выражений, мы имеем дело с побочными эффектами.

Во многих языках таких операций нет в принципе. Линтеры (программы, проверяющие код на соответствие стандартам) в JS настроены так, чтобы "ругаться" при виде этих операций в коде. Вместо них предлагается делать так:

x += 1; // x = x + 1;

Что гораздо проще и понятнее. Да, не получится записать выражение в одну строку, но сам код будет очевидным и без сюрпризов.

Соответствующее правило в eslint: https://eslint.org/docs/rules/no-plusplus

Switch

Конструкция switch может заменить собой несколько условий if. Вот пример обычного условия с if:

let answer;

if (num === 1) {
  answer = "One";
} else if (num === 2) {
  answer = "Two";
} else {
  answer = "Nothing";
}

А вот как его можно переписать с помощью switch:

switch(num) {
  case 1:  // if (num === 1)
    answer = "One";
    break;

  case 2:  // if (num === 2)
    answer = "Two";
    break;

  default:
    answer = "Nothing";
    break;
}

break необходим, чтобы выйти из блока switch. Если break отсутствует, то выполнение пойдёт ниже по следующим случаям, игнорируя проверки. break также можно использовать в циклах for для мгновенного выхода из цикла.

Если в примере выше убрать все break'и, а num будет равен 1, то выполнятся все строки:

answer = "One";
answer = "Two";
answer = "Nothing";

Так что в итоге answer будет иметь значение "Nothing".

Несколько значений case можно группировать.

switch(num) {
  case 1:  // if (num === 1)
    answer = "One";
    break;

  case 2:  // if (num === 2)
  case 3:  // if (num === 3)
  case 4:  // if (num === 4)
    answer = "Two to four";
    break;

  default:
    answer = "Nothing";
    break;
}

Выводы

Арифметические шорткаты:

b *= a;    // same as b = b * a
b += a;    // same as b = b + a
b -= a;    // same as b = b - a
b %= a;    // same as b = b % a

Операторы инкрементирования и декрементирования:

// Postfix
let a = 3;
let b;
b = a++;    // b = 3, a = 4

// Prefix
let a = 3;
let b;
b = ++a;    // b = 4, a = 4

Пример цикла:

const factorial = (n) => {
  let result  = 1;

  // initialization↓    condition↓     update↓
  for (let counter = 1; counter <= n; counter++) {
    result *= counter;
  }

  return result;
}

Тут следует упомянуть о том, что все 3 выражения в цикле for не обязательны.

Например, в блоке инициализации не требуется определять переменные:

let counter = 1;
for (; counter <= n; counter++) {
  // любой код
}

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

for (let counter = 1;; counter++) {
  if (counter <= n) break;
  // любой код
}

Вы можете пропустить все 3 блока. Снова убедитесь, что используете break, чтоб закончить цикл, а также изменить счётчик так, чтоб условие для break было истинно в нужный момент.

let counter = 1;
for (;;) {
  if (counter >= n) break;
  // любой код
  counter++;
}

Обратите внимание на то, что если внутри тела цикла использовать оператор return, то выполнение цикла будет прервано и функция вернет значение.

// Функция должна посчитать сумму всех чисел от 1 до n
const sum = (n) => {
  let result = 0;
  for (let counter = 1; counter <= n; counter++) {
    return 10; // return прерывает цикл

    result += counter;
  }

  return result;
}

sum(5); // 10
sum(20); // 10
sum(50); // 10

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»