# Нагадайки-поясняйки

## Escape characters

**`\n`** — перенос рядка

```javascript
console.log("1\n2\n3\n4");
```

**`\t`** — [табуляція](https://uk.wikipedia.org/wiki/%D0%A2%D0%B0%D0%B1%D1%83%D0%BB%D1%8F%D1%86%D1%96%D1%8F) (горизонтальна)

```javascript
console.log("1\t2\t3\t4");
```

**\\** — екранування наступного символа. Екранований символ просто відображається як текст, а не використаний як спеціальна штука з мови програмування. Наприклад:

```javascript
console.log("ці лапки \"заекрановані\", тому все відобразиться");
console.log("ці лапки не "заекрановані", тому буде помилка");

/*
Помилка буде, бо без екрану це перетворюється на 2 окремих рядка 
    "ці лапки не "
та
    ", тому буде помилка"
а між ними - якась незрозуміла для комп'ютера фігня, яка все ламає
*/
```

**Увага**:  `\n`,  `\t` та інші [escape characters](https://en.wikipedia.org/wiki/Escape_character) треба екранувати разом із їх бекслешем:

```javascript
console.log("Перенос рядка")
console.log("екранований: a1\\nb");
console.log("не екранований: a\nb");
console.log("\nТабуляція")
console.log("екранована: a\\tb");
console.log("не екранована: b\tb");
// і т.д. і т.п.
```

Не лякайтесь посилання: крім `\n`,  `\t` та екранованих лапок вам на Zero інші escapes не знадобляться :)

**p.s.** Конкретно лапки можна вставляти в рядки й без екрану, якщо вони різних типів:

```javascript
console.log("одинарні 'в' подвійних");
console.log('подвійні "в" одинарних');
console.log(`а у бектіках 'взагалі' "що'''" завгодно"''чудить" можна :)`);
// https://ru.wikipedia.org/wiki/%D0%93%D1%80%D0%B0%D0%B2%D0%B8%D1%81
// це та кнопка, де тільда (~), тільки без Shift (у EN або US розкладках)
```

## Про =, == та ===

{% embed url="<https://uk.csstricks.net/8224659-difference-between-and-in-javascript-examples>" %}

## Літерали

**Літерал** — це "голе" значення. Умовно кажучи: те, що можна покласти до змінної. Наприклад:

```javascript
let n = "222";
n = 100500;

console.log(n + ", " + 12345);
n = true;
```

У цьому прикладі літерали — це:

* &#x20;`"222"`
* `100500`
* `", "`
* `12345`
* `true`

## Скорочення

### Числа

Штуки типу **`i = i + 2`** або **`i = i + "*"`**&#x432;арто скорочувати через **+=.**&#x20;

|        Довго       |     Коротко     |
| :----------------: | :-------------: |
|  **`i = i + 123`** | **`i +=  123`** |
|  **`i = i + "*"`** |  **`i += "*"`** |
| **`i = i + ":)"`** | **`i += ":)"`** |
| **`i = i + "\n"`** | **`i += "\n"`** |
|  **`i = i - 15`**  |  **`i -= 15`**  |
|  **`i = i * -3`**  |  **`i *= -3`**  |
| **`i = i / 7.98`** | **`i /= 7.98`** |

Це працює і зі змінними, і з літералами. Звісно, змінна може називатись не лише **`i`**

**Якщо треба додати / відняти саме одиницю**, є ще коротші форми: інкремент та декремент.

|    Дуже довго   |     Довго    |  Гарнюня  |
| :-------------: | :----------: | :-------: |
| **`i = i + 1`** | **`i += 1`** | **`i++`** |
| **`i = i - 1`** | **`i -= 1`** | **`i--`** |

Увага: **=** в інкременті не треба. Треба просто **`i++`** або **`i--`**: як є, без нічого. Умовно кажучи, у цих спецсимволах **`=`** вже "вшитий під капотом".

Запис типу **`i = i++`** або **`i = i--`** працюватиме, але це неправильно і нівелює саму суть скорочення запису.

Запустіть код та читайте консоль

```javascript
let n = 2; // замість 2 може бути будь-яке число
console.log("Початкове значення: " + n);
console.log("тип n зараз: " + typeof n)

console.put("\n" + n);
n += 27; // те саме, що й n = n + 27
console.log(" += 27 🠖 " + n)

console.put("\n" + n);
n -= 8; // n = n - 8
console.log(" -= 8 🠖 " + n);

console.put("\n" + n);
n *= 3.14; // n = n * 3.14
console.log(" *= 3.14 🠖 " + n);

console.put("\n" + n);
n /= 0.123; // n = n / 0.123
console.log(" /= 0.123 🠖 " + n);


// до речі, += працює ще й для конкатенації (зклеювання рядків)
console.put("\n" + n);
n += "якийсь рядок";
console.log(" += \"якийсь рядок\" 🠖 " + n);

// але після цього, звісно, n сама стане рядком
console.log("\nтип n зараз: " + typeof n)

// тобто:
console.put("\n" + n);
n += 100500;
console.log(" += 100500 🠖 " + n + "\n");

console.put ("від 0, n++: ");
n = 0;
while (n < 10) {
    console.put(n++ + " ");
}

console.put("\nвід 0, ++n: ");
n = 0;
while (n < 10) {
    console.put(++n + " ");
}
```

### boolean

**`!`** — логічне заперечення, логічне "не".&#x20;

```javascript
let n;

// !n — те саме, що "не n", "щось протилежне n"
n = true; // спробуйте змінити це значення, пограйтесь
console.log("n = " + n);
console.log("!n = " + !n);

// !n не змінює вміст змінної
console.log("n все ще = " + n);
// щоб змінити:
n = !n;
console.log("хоба: n = " + n);

// у if, циклах та інших умовах, які зводяться до boolean, можна ще так:

if (n) {
    console.log("if(n) спрацював, n = " + n + " зараз");
}

if (!n) {
    console.log("if(!n) спрацював, n = " + n + " зараз");
}

if (n) {
    console.log("а це IF з if-else, n = " + n + " зараз");
} else {
    console.log("а це ELSE з if-else, n = " + n + " зараз");
}
```

## Тернарний оператор

Тернарний оператор — це коротка (та з парою особливих фіч) заміна `if else` для випадків, коли є лише 2 можливих варіанти розгалуження, а кожна дія може бути записана одним рядком коду.

У звичайного `if else` структура така:

```javascript
if(якщо тут true) {
    то виконай цей код
} else {
    інакше, тобто якщо false, виконай цей код
}
```

А тернарним оператором те ж саме записується так:

```javascript
якщо тут true ? то виконай цей код : інакше, тобто якщо false, виконай цей код
```

Тобто, наприклад

```javascript
let number = 3;
let message;

if (number > 3) {
    message = "number більше 3";
} else {
    message = "number менше або дорівнює 3";
}
```

З тернарником скорочується до

```javascript
let number = 3;
let message = number > 3 ? "number більше 3" : "number менше або дорівнює 3";
```

А якщо звернути увагу, що в обох варіантах початок та кінець повторюються, можна ще коротше:

```javascript
let number = 3;
let message = "number " + (number > 3 ? "більше" : "менше або дорівнює") + " 3";
```

Тут слід пам'ятати, що тернарник, на відміну від `if else` — це окрема незалежна сутність (як масив, наприклад). І тому, якщо треба результат передати до функції, не треба викликати її саму в тернарнику двічі поспіль. Можна сам тернарник передати, як аргумент :wink:&#x20;

Тобто, краще **не** писати так:

```javascript
let number = 3;
number > 3 ? console.log("number більше 3") : console.log("number менше або дорівнює 3");
```

А замість того писати так:

```javascript
let number = 3;
console.log("number " + (number > 3 ? "більше" :" менше або дорівнює") + " 3");
```

### Вкладені тернарники

Як `if else` можуть вкладатись одне в одного, так і тернарники можуть бути вкладеними в інші тернарники.

```javascript
let number = 3;
console.log("number " + (number > 3 ? "більше" : number < 3 ? "менше" : "дорівнює") + " 3");
```

Кількість рівнів вкладеності необмежена.

У цій кракозябрі легко заплутатись, але тернарник у більшості випадків нормально розуміє перенос рядків, тому можна записати якось так:

```javascript
let number = 3;
console.log("number " +
    (number > 3 ? "більше"
        : number < 3 ? "менше"
            : "дорівнює")
    + " 3");
    
// або взагалі так, щоб максимально схоже на if else
console.log("number " +
    (number > 3 
        ? "більше"
        : number < 3 
            ? "менше"
            : "дорівнює")
    + " 3");
```

Це теж далеко не зразок читабельності. Але вже набагато більше схоже на знайомі `if else`. Та одночасно непогано демонструє вкладені один у одного тернарники.

Проте, якщо доводиться щось таке писати, то тернарник майже 100% буде не найкращим рішенням. Тому що він про скорочення, а тут не дуже й коротко; ну а без переносів це не дуже читабельно.

Тож дійте за обставинами, керуйтесь здоровим глуздом і не туліть всюди тернарники замість `if else` без необхідності, а просто тому, що це якась прикольна штука :wink:&#x20;

## Остача від ділення націло (%)

Якщо ви гуглили, що воно таке, то, скоріш за все, натикались на [статтю з Вікіпедії](https://uk.wikipedia.org/wiki/%D0%94%D1%96%D0%BB%D0%B5%D0%BD%D0%BD%D1%8F_%D0%B7_%D0%BE%D1%81%D1%82%D0%B0%D1%87%D0%B5%D1%8E). Якщо зрозуміли - круто. Але якщо той математичний канцелярит не зайшов, є простіше пояснення.

Є `a % b` . Беремо найбільше число, кратне `b`, яке менше або дорівнює `a` . Віднімаємо від `a` це число. Отримана різниця - і є результат. На прикладі `10 % 3`: найближче до `10`, яке можна націло розділити на `3` (тобто кратне `3`) - це `9`. `10 - 9` = `1`. Тобто`10 % 3` буде `1`.  &#x20;

Ось демо-код. Повводьте туди різні числа, в т.ч. від'ємні та не цілі (`6.21` і т.п.). І дивіться, що буде.

```javascript
let number, divider, operatorResult, loopResult;

number = +prompt("Введіть число");
while (typeof number !== "number" || isNaN(number)) {
    number = +prompt("Некоректне число, введіть нормальне");
}

divider = +prompt(`${number} % `);
while (typeof divider !== "number" || isNaN(divider) || divider === 0) {
    divider = +prompt("На це не можна ділити. Спробуйте знову\n" + number + "%");
}

operatorResult = number % divider;
console.log(`${number} % ${divider} => ${operatorResult}\n`);

console.log("Чому так:");
loopResult = Math.abs(number);

if (divider < 0 || number < 0) {
    console.log("Увага! Від'ємні беремо по модулю\n");
    divider = Math.abs(divider);
}

while (divider > 0 && loopResult >= divider) {
    console.log(`${loopResult} - ${divider} = ${loopResult - divider}`);
    loopResult -= divider;
}

console.log(`\nОстача (${loopResult}) менша за дільник (${divider}).`);

if (number < 0) {
    loopResult = -loopResult;
}

console.log(`От вона і є результат: ${loopResult}`);
if (number < 0 && loopResult !== 0) {
    console.log("(вже не по модулю, звісно)");
}
```

Яке у цього практичне застосування? Та дуже просте. Якщо остача `a % b === 0`, то `a` ділиться без остачі на `b`. Тобто `a` кратне `b`. Так, наприклад, можна перевірити число на парність/непарність,  визначивши, чи кратне воно двійці. Або можна дізнатись, скільки мінімум автобусів потрібно для перевозки групи `a` туристів, якщо в кожному автобусі - максимум `b` місць. Або ще щось таке, придумайте самі :)

## Складання у змінну

Інколи (навіть часто), коли в циклах щось виводимо на консоль, замість 100500 разів просто виводити щось на кожній ітерації, корисніше та зручніше — складати значення до змінної (додавати до неї, конкатенувати з нею) а потім один раз виводити саме цю змінну.

Тобто замість

```javascript
for(let i = 0; i < 10; i++) {
    console.put(i);
}
```

якось типу так

```javascript
let buffer = "";
for(let i = 0; i < 10; i++) {
    buffer += i;
}
console.log(buffer);
```

## Приведення типів

### Найчастіші процедури на Zero

```javascript
let n;

console.log()
n = "123"; // рядок
n = +n; // число
n = +"123" // так теж можна

// ЧИСЛО В РЯДОК
n = 123; // це число
n += ""; // будь-що складаємо з рядком — отримуємо рядок
```

### Таблиця конвертацій

Табличка [звідси](https://www.w3schools.com/js/js_type_conversion.asp)

| **Значення** | **Перетворене на число** | **Перетворене на рядок** | **Перетворене на boolean** |
| ------------ | ------------------------ | ------------------------ | -------------------------- |
| false        | 0                        | "false"                  | false                      |
| true         | 1                        | "true"                   | true                       |
| 0            | 0                        | "0"                      | false                      |
| 1            | 1                        | "1"                      | true                       |
| "0"          | 0                        | "0"                      | true                       |
| "000"        | 0                        | "000"                    | true                       |
| "1"          | 1                        | "1"                      | true                       |
| "20"         | 20                       | "20"                     | true                       |
| ""           | 0                        | ""                       | false                      |
| "twenty"     | NaN                      | "twenty"                 | true                       |
| NaN          | NaN                      | "NaN"                    | false                      |
| Infinity     | Infinity                 | "Infinity"               | true                       |
| -Infinity    | -Infinity                | "-Infinity"              | true                       |
| null         | 0                        | "null"                   | false                      |
| undefined    | NaN                      | "undefined"              | false                      |
| \[ ]         | 0                        | ""                       | true                       |
| \[20]        | 20                       | "20"                     | true                       |
| \[10,20]     | NaN                      | "10,20"                  | true                       |

## **Скоуп**&#x20;

Скоуп (область видимості) — це шматок кода всередин&#x456;**`{ }`**

```javascript
for(1) {
    for(2) {
        while(3) {

        }
    }
    for(4) {
        
    }
}
```

Цикли 2, 3 та 4 входять до скоупу 1.\
3 входить до скоупів 1 та 2.\
4 входить до скоупу 1.

І є ще глобальний скоуп, куди входять вони всі разом. Це "нульовий" рівень, тобто ВЕСЬ код в редакторі. Можете уявити, що весь код в IDE загорнутий у верховні невидимі **`{ }`**.

```javascript
{ // це типу умовна "невидима верховна дужка" початку глобального скоупу
for(1) {
    for(2) {
        while(3) {

        }
    }
    for(4) {
        
    }
}
} // а це — верховна дужка кінця. теж умовна і невидима
```

Змінні зі внутрішнього скоупу "бачать" зовнішні. Але із зовнішнього скоупу не видно внутрішні.

```javascript
let n = 100500;
for (let i = 0; i < 10; i++) {
    n++; // так можна, бо ми звертаємось "назовні"
    console.log(i); // так можна, бо i оголошена в цьому ж скоупі
    for(let j = 0; j < 10; j++) {
        console.log(i); // можна, бо теж ідемо в зовнішній скоуп
        console.log(j); // можна
    }
    console.log(j); // а так не можна, буде помилка, бо в цьому скоупі вже нема j
}
```

Тобто правило просте: **назовні — бачимо, всередину — ні.**

## Цикли

**Тіло цикла** — все, що знаходиться всередині цикла `{` тут `}`

```javascript
for() {
    тіло цикла
}

while() {
    тіло цикла
}

do {
    тіло цикла
} while();
```

### Структура циклів

* Якщо треба повторити дії конкретну кількість разів, то юзаємо **for**.
* Якщо вказати кількість повторів заздалегідь неможливо: **while**.
* Якщо треба зробити щось незалежно від обставин як мінімум 1 раз, а далі — по ситуації: **do while**

#### for

```javascript
for(1; 2; 3)
```

`1`: місце для створення однієї або кількох змінних (якщо кілька — через кому)

`2`: вираз або змінна, який цикл конвертує в boolean (див. табличку вище).  Доки `2` буде `true`, цикл повторюватиметься. Якщо стане `false` — цикл перерветься.

`3`: дії, які виконаються в кінці кожної ітерації

```javascript
for (let i = 0, j = 10, k = true; i < 25; i++, j--, k = !k) {
    console.log(`i=${i}\tj=${j}\tk=${k}`)
    if (i > 0 && i % 5 == 0) {
        console.log(":)\n")
    }
}
```

У цьому прикладі:

`1`: `let i = 0, j = 10, k = true`\
`2`: `i < 25`\
`3`: `i++, j--, k = !k`

**Увага**: `1`, `2` та `3` входять в скоуп цикла, в якому вони створені.

#### **while**

Те саме, що `for`, але має лише блок **`2`**. **`1`** Треба руками записувати перед циклом десь ззовні, а **`3`** — в тілі циклу (дляповної тотожності — в самому кінці перед **`}`**.

```javascript
let i = 0, j = 10, k = true;
while (i < 25) {
    console.log(`i=${i}\tj=${j}\tk=${k}`)
    if (i > 0 && i % 5 == 0) {
        console.log(":)\n")
    }
    i++;
    j--;
    k = !k;
}
```

#### do while

```javascript
do {
    X
} while (Y);
```

Що б там не було, бодай 1 раз виконати все, що в `X`. Потім перевірити, чи `Y == true`. Якщо так — повторювати `X` доти, доки `Y == true`

```javascript
let i = 0, j = 10, k = true;
do {
    console.log(`i=${i}\tj=${j}\tk=${k}`)
    if (i > 0 && i % 5 == 0) {
        console.log(":)\n")
    }
    i++;
    j--;
    k = !k;
} while (i < 25);
```

### continue та break

**`continue`**: "ігнорувати весь код в наступних рядках та перейти до наступної ітерації цикла"

**`break`:** "завершити цикл" (точно так же, як якщо б в блоку **`2`** стало **false**)

**Увага**: `continue` та `break` впливають лише на свій скоуп і не чіпають зовнішній. Умовно:

```javascript
for(let i = 0; i < 10; i++) {
    for(let j = 0; j < 10; j++) {
        if (щось) {
            break; // тут перерветься лише j-цикл. А i-цикл продовжиться
        }
        if (ще щось) {
            continue; // перейде до наступної ітерації j, а на i не вплине
        }
    }
}
```

Брейкати зовнішні скоупи [можливо](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label), але це не знадобиться на Zero.

А взагалі варто уникати `continue` та `break`. В тому сенсі, що, якщо можливо без них — робіть без них. Вони не про "**коли** завершити" а "**якщо щось трапилось** — завершити".

Повну різницю між ними зрозумієте на курсі [P2P CS](/zero/arrangements/p2p-cs-entrytest.md).&#x20;

Ну типу, навіщо робити якось так:

```javascript
let i = 0;
while (true) {
    console.log(i);
    if (i == 10) {
        break;
    }
    i++;
}

// або взагалі
for (let i = 0; ; i++) {
    console.log(i);
    if (i == 10) {
        break;
    }
}
```

коли сама [структура циклів](#struktura-cikliv) підштовхує робити так:

```javascript
let i = 0;
while (i <= 10) {
    console.log(i);
    i++;
}

//ну і відповідно
for (let i = 0; i <= 10; i++) {
    console.log(i);
}
```

`break` / `continue` доречні, коли треба **зреагувати на щось, що виникає внаслідок роботи самого циклу**. Наприклад:

```javascript
let inputText;
let counterA = 0;
let counterB = 0;
while (true) {
    counterA++;
    inputText = prompt("Введи щось");

    if (inputText == "пропусти") {
        alert("Ок, на цій ітерації counterB не збільшуємо");
        continue;
    }

    if (inputText == "зупинись") {
        break;
    }

    counterB++;
}

console.log("counterA = " + counterA + "\ncounterB = " + counterB);
```

Коротше кажучи, у більшості випадків, якщо цикл переривається через `break`, а не через умову переривання в голові цикла — з алгоритмом щось не так, і його варто оптимізувати.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://shpp.gitbook.io/zero/tutorials/nagadaiki-poyasnyaiki.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
