Comment on page
Нагадайки-поясняйки
\n
— перенос рядкаconsole.log("1\n2\n3\n4");
console.log("1\t2\t3\t4");
\ — екранування наступного символа. Екранований символ просто відображається як текст, а не використаний як спеціальна штука з мови програмування. Наприклад:
console.log("ці лапки \"заекрановані\", тому все відобразиться");
console.log("ці лапки не "заекрановані", тому буде помилка");
/*
Помилка буде, бо без екрану це перетворюється на 2 окремих рядка
"ці лапки не "
та
", тому буде помилка"
а між ними - якась незрозуміла для комп'ютера фігня, яка все ламає
*/
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. Конкретно лапки можна вставляти в рядки й без екрану, якщо вони різних типів:
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 розкладках)
Літерал — це "голе" значення. Умовно кажучи: те, що можна покласти до змінної. Наприклад:
let n = "222";
n = 100500;
console.log(n + ", " + 12345);
n = true;
У цьому прикладі літерали — це:
"222"
100500
", "
12345
true
Штуки типу
i = i + 2
або i = i + "*"
варто скорочувати через +=. Довго | Коротко |
---|---|
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--
працюватиме, але це неправильно і нівелює саму суть скорочення запису.Запустіть код та читайте консоль
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 + " ");
}
!
— логічне заперечення, логічне "не". 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
структура така:if(якщо тут true) {
то виконай цей код
} else {
інакше, тобто якщо false, виконай цей код
}
А тернарним оператором те ж саме записується так:
якщо тут true ? то виконай цей код : інакше, тобто якщо false, вик онай цей код
Тобто, наприклад
let number = 3;
let message;
if (number > 3) {
message = "number більше 3";
} else {
message = "number менше або дорівнює 3";
}
З тернарником скорочується до
let number = 3;
let message = number > 3 ? "number більше 3" : "number менше або дорівнює 3";
А якщо звернути увагу, що в обох варіантах початок та кінець повторюються, можна ще коротше:
let number = 3;
let message = "number " + (number > 3 ? "більше" : "менше або дорівнює") + " 3";
Тут слід пам'ятати, що тернарник, на відміну від
if else
— це окрема незалежна сутність (як масив, наприклад). І тому, якщо треба результат передати до функції, не треба викликати її саму в тернарнику двічі поспіль. Можна сам тернарник передати, як аргумент 😉
Тобто, краще не писати так:
let number = 3;
number > 3 ? console.log("number більше 3") : console.log("number менше або дорівнює 3");
А замість того писати так:
let number = 3;
console.log("number " + (number > 3 ? "більше" :" менше або дорівнює") + " 3");
Як
if else
можуть вкладатись одне в одного, так і тернарники можуть бути вкладеними в інші тернарники.let number = 3;
console.log("number " + (number > 3 ? "більше" : number < 3 ? "менше" : "дорівнює") + " 3");
Кількість рівнів вкладеності необмежена.
У цій кракозябрі легко заплутатись, але тернарник у більшості випадків нормаль но розуміє перенос рядків, тому можна записати якось так:
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
без необхідності, а просто тому, що це якась прикольна штука 😉
Якщо ви гуглили, що воно таке, то, скоріш за все, натикались на статтю з Вікіпедії. Якщо зрозуміли - круто. Але якщо той математичний канцелярит не зайшов, є простіше пояснення.
Є
a % b
. Беремо найбільше число, кратне b
, яке менше або дорівнює a
. Віднімаємо від a
це число. Отримана різниця - і є результат. На прикладі 10 % 3
: найближче до 10
, яке можна націло розділити на 3
(тобто кратне 3
) - це 9
. 10 - 9
= 1
. Тобто10 % 3
буде 1
. Ось демо-код. Повводьте туди різні числа, в т.ч. від'ємні та не цілі (
6.21
і т.п.). І дивіться, що буде.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 разів просто виводити щось на кожній ітерації, корисніше та зручніше — складати значення до змінної (додавати до неї, конкатенувати з нею) а потім один раз виводити саме цю змінну.
Тобто замість
for(let i = 0; i < 10; i++) {
console.put(i);
}
якось типу так
let buffer = "";
for(let i = 0; i < 10; i++) {
buffer += i;
}
console.log(buffer);
let n;
console.log()
n = "123"; // рядок
n = +n; // число
n = +"123" // так теж можна
// ЧИСЛО В РЯДОК
n = 123; // це число
n += ""; // будь-що складаємо з рядком — отримуємо рядок
Значення | Перетворене на число | Перетворене на рядок | Перетворене на 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 |
Скоуп (область видимості) — це шматок кода всередині
{ }
for(1) {
for(2) {
while(3) {
}
}
for(4) {
}
}
Цикли 2, 3 та 4 входять до скоупу 1.
3 входить до скоупів 1 та 2.
4 входить до скоупу 1.
І є ще глобальний скоуп, куди входять вони всі разом. Це "нульовий" рівень, тобто ВЕСЬ код в редакторі. Можете уявити, що весь код в IDE загорнутий у верховні невидимі
{ }
.{ // це типу умовна "невидима верховна дужка" початку глобального скоупу
for(1) {
for(2) {
while(3) {
}
}
for(4) {
}
}
} // а це — верховна дужка кінця. теж умовна і невидима
Змінні зі внутрішнього скоупу "бачать" зовнішні. Але із зовнішнього скоупу не видно внутрішні.
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
}
Тобто правило просте: назовні — бачимо, всередину — ні.
Тіло цикла — все, що знаходиться всередині цикла
{
тут }
for() {
тіло цикла
}
while() {
тіло цикла
}
do {
тіло цикла
} while();
- Якщо треба повторити дії конкрет ну кількість разів, то юзаємо for.
- Якщо вказати кількість повторів заздалегідь неможливо: while.
- Якщо треба зробити щось незалежно від обставин як мінімум 1 раз, а далі — по ситуації: do while
for(1; 2; 3)
1
: місце для створення однієї або кількох змінних (якщо кілька — через кому)2
: вираз або змінна, який цикл конвертує в boolean (див. табличку вище). Доки 2
буде true
, цикл повторюватиметься. Якщо стане false
— цикл перерветься.3
: дії, які виконаються в кінці кожної ітерації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
входять в скоуп цикла, в якому вони створені.Те саме, що
for
, але має лише блок 2
. 1
Треба руками записувати перед циклом десь ззовні, а 3
— в тілі циклу (дляповної тотожності — в самому кінці перед }
.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 {
X
} while (Y);
Що б там не було, бодай 1 раз виконати все, що в
X
. Потім перевірити, чи Y == true
. Якщо так — повторювати X
доти, доки Y == true
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
: "завершити цикл" (точно так же, як якщо б в блоку 2
стало false)
Увага:
continue
та break
впливають лише на свій скоуп і не чіпають зовнішній. Умовно:for(let i = 0; i < 10; i++) {
for(let j = 0; j < 10; j++) {
if (щось) {
break; // тут перерветься лише j-цикл. А i-цикл продовжиться
}
if (ще щось) {
continue; // перейде до наступної і терації j, а на i не вплине
}
}
}
А взагалі варто уникати
continue
та break
. В тому сенсі, що, якщо можливо без них — робіть без них. Вони не про "коли завершити" а "якщо щось трапилось — завершити".Ну типу, навіщо робити якось так:
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;
}
}
let i = 0;
while (i <= 10) {
console.log(i);
i++;
}
//ну і відповідно
for (let i = 0; i <= 10; i++) {
console.log(i);
}
break
/ continue
доречні, коли треба зреагувати на щось, що виникає внаслідок роботи самого циклу. Наприклад: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
, а не через умову переривання в голові цикла — з алгоритмом щось не так, і його варто оптимізувати.Last modified 1yr ago