Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
101 changes: 72 additions & 29 deletions modules/50-loops/10-while/ru/README.md
Original file line number Diff line number Diff line change
@@ -1,46 +1,89 @@
Циклы позволяют выполнять одно и то же действие многократно.
Помимо условных конструкций, в программировании невозможно обойтись без циклов. Это специальный механизм, позволяющий выполнять любое действие многократно. На его базе строятся практически любые вычисления — от подсчёта среднего балла в группе до обработки входящих запросов на сайтах.

## while
Цикл хранит повторяющееся действие в одном месте и запускает его снова, пока условие остаётся истинным.

Цикл `while` выполняет тело, пока условие истинно.
## Первый пример

Пусть программа должна пять раз вывести строку `'Hello!'`. Чтобы остановить повторение в нужный момент, программе нужна переменная, которая хранит номер текущего шага. Такую переменную обычно называют счётчиком.

В примере счётчик называется `counter`. Перед циклом он равен `0`. После каждого вывода строки мы увеличиваем его на единицу.

```javascript
let i = 0;
while (i < 3) {
console.log(i);
i += 1;
let counter = 0;
while (counter < 5) {
console.log('Hello!');
counter += 1;
}
// 0
// 1
// 2

// => Hello!
// => Hello!
// => Hello!
// => Hello!
// => Hello!
```

## Счётчик и обратный отсчёт
После `while` в круглых скобках записывается условие, а тело цикла — в фигурных скобках. Пока `counter < 5`, выполняется тело цикла. После выполнения тела движок возвращается к условию и проверяет его заново. Когда условие становится ложным (`false`), программа выходит из цикла и продолжает выполнять код дальше.

Без изменения счётчика условие никогда не станет ложным, и цикл превратится в **бесконечный**. Со стороны это выглядит так, как будто программа зависла.

## Работа цикла по шагам

Перед первым повтором `counter` равен `0`.

**Шаг 1.** Проверяется `counter < 5`. Значение `0` меньше `5`, поэтому выполняется тело цикла. На экран выводится `Hello!`, а `counter` увеличивается до `1`.

**Шаг 2.** Условие проверяется снова. Значение `1` всё ещё меньше `5`, тело цикла выполняется ещё раз. На экран снова выводится `Hello!`, а `counter` увеличивается до `2`.

Так продолжается, пока `counter` не станет равен `5`. При следующей проверке условие `counter < 5` будет ложным, поэтому цикл завершится.

```text
counter = 0
┌──→ counter < 5?
│ true │
│ ↓
│ console.log('Hello!')
│ counter += 1
└──────────┘
false → выход из цикла
```

## Тело цикла и продолжение программы

К телу цикла относится всё, что находится внутри фигурных скобок. Код после цикла выполняется один раз:

```javascript
function printCountdown(seconds) {
while (seconds > 0) {
console.log(seconds);
seconds -= 1;
}
console.log('Go!');
let counter = 0;
while (counter < 2) {
console.log('Hello!');
counter += 1;
}

printCountdown(3);
// 3
// 2
// 1
// Go!
console.log('End of loop');
```

## Бесконечный цикл
Здесь `console.log('Hello!')` и `counter += 1` находятся внутри цикла, а `console.log('End of loop')` стоит за его пределами, поэтому выполнится один раз после завершения цикла.

## Цикл внутри функции

Если условие никогда не станет `false`, цикл будет работать вечно. Всегда убедитесь, что переменная изменяется внутри тела цикла.
Теперь перенесём цикл в функцию. Она напечатает числа от `1` до переданного значения:

```javascript
// Бесконечный цикл — никогда не останавливается!
// let i = 0;
// while (i < 3) {
// console.log(i); // i не изменяется
// }
const printNumbers = (n) => {
let i = 1;
while (i <= n) {
console.log(i);
i += 1;
}
console.log('Finished!');
};

printNumbers(3);
// => 1
// => 2
// => 3
// => Finished!
```

Цикл `while` печатает числа, пока `i` не станет больше `n`. После этого программа выходит из цикла и выполняет `console.log('Finished!')`.

Условие и изменение счётчика зависят от задачи. Счётчик можно увеличивать на `1`, на `2` или сразу на `10`. Его можно уменьшать, если цикл идёт от большего значения к меньшему. Главное, чтобы условие когда-нибудь стало ложным, иначе цикл будет работать бесконечно.
24 changes: 24 additions & 0 deletions modules/50-loops/23-aggregation-strings/ru/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,27 @@ result = `${result}hexlet`; // hexlet
result = `${result}hexlet`; // hexlethexlet
result = `${result}hexlet`; // hexlethexlethexlet
```

Наглядно процесс наращивания строки выглядит так:

```text
repeat('hexlet', 3):

i=1: result = '' + 'hexlet' = 'hexlet'
i=2: result = 'hexlet' + 'hexlet' = 'hexlethexlet'
i=3: result = 'hexlethexlet' + 'hexlet' = 'hexlethexlethexlet'
└── результат
```

## Нейтральный элемент

Чтобы наращивание работало, нужно стартовое значение. Для строк таким значением является **пустая строка** `''`.

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

```javascript
console.log('' + 'abc'); // => abc
console.log('abc' + ''); // => abc
```

Поэтому именно пустая строка всегда используется как начальное значение при агрегации строк.
33 changes: 32 additions & 1 deletion modules/50-loops/25-iteration-over-string/ru/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,4 +21,35 @@ printNameBySymbol(name);
// => a
```

Самое главное в этом коде, поставить правильное условие в `while`. Это можно сделать сразу двумя способами: `i < name.length` или `i <= name.length - 1`. Оба способа приводят к одному результату.
Самое главное в этом коде — поставить правильное условие в `while`. Это можно сделать сразу двумя способами: `i < name.length` или `i <= name.length - 1`. Оба способа приводят к одному результату.

Цикл проходит по каждому символу строки по очереди:

```text
'Arya'
│ │ │ │
A r y a
↓ ↓ ↓ ↓
каждый символ обрабатывается по очереди
```

## Переворот строки

Вместо печати можно собирать новую строку. Например, напишем функцию, которая переворачивает строку:

```javascript
const reverseString = (text) => {
let result = '';
let i = text.length - 1;
while (i >= 0) {
result = `${result}${text[i]}`;
i -= 1;
}
return result;
};

console.log(reverseString('Arya')); // => ayrA
console.log(reverseString('hexlet')); // => telxeh
```

Переменная `result` инициализируется пустой строкой как нейтральным элементом для конкатенации. Цикл начинается с последнего индекса (`text.length - 1`), двигается к нулю и завершается, когда индекс становится меньше нуля. На каждом шаге к результату добавляется текущий символ — и строка собирается в обратном порядке.
56 changes: 41 additions & 15 deletions modules/50-loops/26-conditions-inside-loops/ru/README.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,48 @@
Тело цикла, как и тело функции, — это место выполнения инструкций. Значит, внутри него можно использовать всё изученное ранее, например условные конструкции. Так программа повторяет одно действие несколько раз, но на каждом повторе принимает решение.

Тело цикла, как и тело функции — это место выполнения инструкций. Значит, мы можем использовать внутри него всё изученное ранее, например — условные конструкции.
Пусть нужно пройти числа от `1` до `10` и напечатать только чётные. Цикл перебирает все числа подряд, а условие внутри решает, какие из них попадут на экран:

Представьте себе функцию, которая считает, сколько раз входит буква в предложение. Пример её работы:
```javascript
let number = 1;
while (number <= 10) {
if (number % 2 === 0) {
console.log(number);
}
number += 1;
}

// => 2
// => 4
// => 6
// => 8
// => 10
```

Счётчик увеличивается после проверки **в любом случае**. Это важно: если увеличивать `number` только внутри `if`, цикл остановится на первом нечётном числе и будет работать бесконечно.

## Работа по шагам

Перед первым повтором `number` равен `1`.

**Шаг 1.** Условие цикла `number <= 10` истинно, программа входит в тело. Число `1` нечётное, блок `if` не выполняется. Затем `number` увеличивается до `2`.

**Шаг 2.** Условие снова истинно. Число `2` чётное, поэтому печатается `2`. Затем `number` увеличивается до `3`.

Дальше цикл проверяет каждое число: нечётные пропускает, чётные выводит. Когда `number` станет равен `11`, условие `number <= 10` станет ложным, и цикл завершится.

## Условие меняет действие, а не движение

В таких циклах удобно разделять две части: счётчик переводит программу к следующему значению, а `if` решает, что делать с текущим значением.

Рассмотрим функцию, которая считает, сколько раз буква входит в предложение:

```javascript
countChars('Fear cuts deeper than swords.', 'e'); // 4
// Если вы ничего не нашли, то результат — 0 совпадений
// Если ничего не нашли, результат — 0 совпадений
countChars('Sansa', 'y'); // 0
```

Перед тем как посмотреть её содержимое, попробуйте ответить на вопросы:

* Является ли эта операция агрегацией?
* Какой будет проверка на вхождение символа?
Реализация:

```javascript
const countChars = (str, char) => {
Expand All @@ -21,18 +51,14 @@ const countChars = (str, char) => {
while (i < str.length) {
if (str[i] === char) {
// Считаем только подходящие символы
count = count + 1;
count += 1;
}
// Счетчик увеличивается в любом случае
i = i + 1;
// Счётчик увеличивается в любом случае
i += 1;
}

return count;
};
```

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

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

В остальном — это типичная агрегатная функция, которая возвращает количество нужных символов вызываемому коду.
Эта задача является агрегирующей. Несмотря на то что она считает не все символы, для подсчёта суммы всё равно приходится анализировать каждый символ. Ключевое отличие от обычной агрегации — наличие условия внутри тела: переменная `count` увеличивается только тогда, когда текущий символ совпадает с ожидаемым. Условие внутри цикла может проверять что угодно — чётность числа, совпадение символа, длину строки. Главное, чтобы счётчик продолжал меняться и цикл мог завершиться.
63 changes: 56 additions & 7 deletions modules/50-loops/30-syntax-sugar/ru/README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,59 @@
В программировании часто встречаются повторяющиеся конструкции. В JavaScript, как и во многих других языках, есть возможность сокращать их запись. Такие упрощения называют **синтаксическим сахаром** — они делают код короче и удобнее, сохраняя тот же результат.

Подобные конструкции `index = index + 1` в JavaScript используются довольно часто, поэтому создатели языка добавили сокращённый вариант записи: `index += 1`. Такие сокращения принято называть **синтаксическим сахаром**, потому что они делают процесс написания кода немного проще и приятнее, «подслащивая» его :)
## Сокращённые формы присваивания

Существуют сокращённые формы для всех арифметических операций и для конкатенации строк:
Часто требуется изменить значение переменной: что-то прибавить, вычесть, умножить или разделить. Базовый вариант выглядит так:

- `a = a + 1` → `a += 1`
- `a = a - 1` → `a -= 1`
- `a = a * 2` → `a *= 2`
- `a = a / 1` → `a /= 1`
- `a = a + 'foo'` → `a += 'foo'`
```javascript
index = index + 1;
count = count * 2;
total = total - 5;
price = price / 3;
```

JavaScript позволяет записать это короче, с помощью комбинированных операторов:

```javascript
index += 1; // то же самое, что index = index + 1

Check notice on line 17 in modules/50-loops/30-syntax-sugar/ru/README.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] modules/50-loops/30-syntax-sugar/ru/README.md#L17

Possible typo: you repeated a word (ENGLISH_WORD_REPEAT_RULE) Suggestions: `index` Rule: https://community.languagetool.org/rule/show/ENGLISH_WORD_REPEAT_RULE?lang=en-US Category: MISC
Raw output
modules/50-loops/30-syntax-sugar/ru/README.md:17:42: Possible typo: you repeated a word (ENGLISH_WORD_REPEAT_RULE)
 Suggestions: `index`
 Rule: https://community.languagetool.org/rule/show/ENGLISH_WORD_REPEAT_RULE?lang=en-US
 Category: MISC
count *= 2; // то же самое, что count = count * 2
total -= 5; // то же самое, что total = total - 5
price /= 3; // то же самое, что price = price / 3
```

## Сахар в циклах

В циклах такие сокращения встречаются особенно часто: обычно мы меняем счётчик и накапливаем результат.

Check notice on line 25 in modules/50-loops/30-syntax-sugar/ru/README.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] modules/50-loops/30-syntax-sugar/ru/README.md#L25

Unpaired symbol: ‘'’ seems to be missing (EN_UNPAIRED_QUOTES) URL: https://languagetool.org/insights/post/punctuation-guide/#what-are-parentheses Rule: https://community.languagetool.org/rule/show/EN_UNPAIRED_QUOTES?lang=en-US Category: PUNCTUATION
Raw output
modules/50-loops/30-syntax-sugar/ru/README.md:25:141: Unpaired symbol: ‘'’ seems to be missing (EN_UNPAIRED_QUOTES)
 URL: https://languagetool.org/insights/post/punctuation-guide/#what-are-parentheses 
 Rule: https://community.languagetool.org/rule/show/EN_UNPAIRED_QUOTES?lang=en-US
 Category: PUNCTUATION

Check notice on line 25 in modules/50-loops/30-syntax-sugar/ru/README.md

View workflow job for this annotation

GitHub Actions / LanguageTool

[LanguageTool] modules/50-loops/30-syntax-sugar/ru/README.md#L25

Unpaired symbol: ‘'’ seems to be missing (EN_UNPAIRED_QUOTES) URL: https://languagetool.org/insights/post/punctuation-guide/#what-are-parentheses Rule: https://community.languagetool.org/rule/show/EN_UNPAIRED_QUOTES?lang=en-US Category: PUNCTUATION
Raw output
modules/50-loops/30-syntax-sugar/ru/README.md:25:185: Unpaired symbol: ‘'’ seems to be missing (EN_UNPAIRED_QUOTES)
 URL: https://languagetool.org/insights/post/punctuation-guide/#what-are-parentheses 
 Rule: https://community.languagetool.org/rule/show/EN_UNPAIRED_QUOTES?lang=en-US
 Category: PUNCTUATION

```javascript
let sum = 0;
let index = 1;

while (index <= 5) {
sum += index; // то же самое, что sum = sum + index
index += 1; // то же самое, что index = index + 1
}

console.log(sum); // => 15
```

Без сокращений тело цикла было бы длиннее:

```javascript
while (index <= 5) {
sum = sum + index;
index = index + 1;
}
```

## Другие операции

Такая запись работает не только с числами. Для строк используется оператор конкатенации:

```javascript
let text = 'Hello';
text += ' World'; // то же самое, что text = text + ' World'
```

## Поддерживаемые сокращения

Сокращённая форма существует почти для всех операторов: `+=`, `-=`, `*=`, `/=`, `%=`, `**=`. Все они работают по одному принципу: берут текущее значение переменной, применяют операцию и сохраняют результат в ту же переменную.
Loading
Loading