034.3 Урок 1
Сертифікат: |
Основи веброзробки |
---|---|
Версія: |
1.0 |
Розділ: |
034 JavaScript-програмування |
Тема: |
034.3 Структури та функції керування JavaScript |
Урок: |
1 з 2 |
Вступ
Як і в будь-якій іншій мові програмування, код JavaScript являє собою набір операторів, які вказують інтерпретатору інструкцій, що робити в послідовному порядку. Однак це не означає, що кожен оператор має виконуватися лише один раз або що він має виконуватися взагалі. Більшість операторів повинні виконуватися лише в разі виконання певних умов. Навіть коли сценарій запускається асинхронно незалежними подіями, йому часто доводиться перевіряти ряд керуючих змінних, щоб знайти потрібну частину коду для виконання.
Оператори If
Найпростішу структуру керування надає інструкція if
, яка виконує оператор, що записаний одразу після неї, якщо зазначена умова істинна. JavaScript вважає умови істинними, якщо оцінене значення відмінне від нуля. Усе, що знаходиться в дужках після слова if
(пробіли ігноруються) буде інтерпретовано як умова. У наступному прикладі число 1
є умовою:
if ( 1 ) console.log("1 завжди true");
Число 1
явно записано в цьому прикладі умови, тому воно розглядається як постійне значення (воно залишається незмінним протягом усього виконання сценарію), і воно завжди буде мати значення true, якщо використовується як умовний вираз. Слово true
(без подвійних лапок) також можна використовувати замість 1
, оскільки мова програмування також розглядає його як буквальне істинне значення. Інструкція console.log
друкує свої аргументи у консольному вікні браузера.
Tip
|
Консоль браузера відображає помилки, попередження та інформаційні повідомлення, надіслані інструкцією JavaScript |
Хоч це синтаксично правильно, використання константних виразів в умовах не є дуже корисним. У реальній програмі ви, ймовірно, захочете перевірити істинність змінної:
let my_number = 3;
if ( my_number ) console.log("Значенням my_number є", my_number, "і це дає результат true");
Значення, присвоєне змінній my_number
(3
), є відмінним від нуля, тому воно дає істину. Але цей приклад не часто використовується, тому що вам доволі рідко знадобиться перевіряти, чи дорівнює число нулю. Набагато частіше порівнюють одне значення з іншим і перевіряють, чи є результат істинним:
let my_number = 3;
if ( my_number == 3 ) console.log("Значенням my_number є", my_number, "насправді");
Оператор порівняння з двома знаками рівності використовується, оскільки одинарний оператор рівності вже визначено як оператор присвоювання. Значення з кожного боку оператора називається операндом. Порядок операндів не має значення, і будь-який вираз, який повертає значення, може бути операндом. Ось список інших доступних операторів порівняння:
value1 == value2
-
Істина, якщо
value1
дорівнюєvalue2
. value1 != value2
-
Істина, якщо
value1
не дорівнюєvalue2
. value1 < value2
-
Істина, якщо
value1
менше ніжvalue2
. value1 > value2
-
Істина, якщо
value1
більше ніжvalue2
. value1 <= value2
-
Істина, якщо
value1
менше ніж або дорівнюєvalue2
. value1 >= value2
-
Істина, якщо
value1
більше ніж або дорівнюєvalue2
.
Зазвичай не має значення, чи є операнд ліворуч від оператора рядком, а операнд праворуч – числом, якщо JavaScript може перетворити вираз на змістовне порівняння. Отже, рядок, що містить символ 1
, розглядатиметься як число 1 під час порівняння з числовою змінною. Щоб переконатися, що вираз дає істину, лише якщо обидва операнди мають однаковий тип і значення, слід використовувати оператор жорсткої ідентичності ===
замість ==
. Аналогічно, оператор жорсткої неідентичності !==
оцінюється як істина, якщо перший операнд не того самого типу та значення, що другий оператор.
За бажанням, структура керування if
може виконувати альтернативний оператор, коли вираз оцінюється як false:
let my_number = 4;
if ( my_number == 3 ) console.log("Значенням my_number є 3");
else console.log("Значенням my_number не є 3");
Інструкція else
має одразу слідувати за інструкцією if
. Поки що ми виконуємо лише один оператор, коли умова виконується. Щоб виконати більше одного оператора, ви повинні взяти їх у фігурні дужки:
let my_number = 4;
if ( my_number == 3 )
{
console.log("Значенням my_number є 3");
console.log("і це другий оператор в блоці");
}
else
{
console.log("Значення my_number не є 3");
console.log("і це другий лператор в блоці");
}
Група з одного або кількох операторів, оформлені парою фігурних дужок, відома як блочний оператор. Загальним підходом є використання блочних операторів, навіть якщо є лише одна інструкція для виконання, щоб зробити стиль кодування узгодженим у всьому сценарії. Більше того, JavaScript не вимагає, щоб фігурні дужки або будь-які оператори розміщувалися в окремих рядках, але це покращує читабельність і полегшує підтримку коду.
Керуючі структури можуть бути вкладені одна в одну, але важливо не плутати відкривачі і закриваючі дужки кожного блочного оператора:
let my_number = 4;
if ( my_number > 0 )
{
console.log("Значення my_number додатнє");
if ( my_number % 2 == 0 )
{
console.log("і це парне число");
}
else
{
console.log("і це непарне число");
}
} // end of if ( my_number > 0 )
else
{
console.log("Значення my_number менше ніж або дорівнює 0");
console.log("і я вирішив його ігнорувати");
}
Вирази, оцінені інструкцією if
, можуть бути більш складними, ніж прості порівняння. Як наприклад в попередньому прикладі, де арифметичний вираз my_number % 2
було використано всередині дужок у вкладеному if
. Оператор %
повертає залишок після ділення числа зліва на число справа. Арифметичні оператори, як-от %
, мають пріоритет перед такими операторами порівняння, як ==
, тому порівняння використовуватиме результат арифметичного виразу як лівий операнд.
У багатьох ситуаціях вкладені умовні структури можна об’єднати в одну структуру за допомогою логічних операторів. Якби нас цікавили лише позитивні парні числа, наприклад, можна було б використовувати одну структуру if
:
let my_number = 4;
if ( my_number > 0 && my_number % 2 == 0 )
{
console.log("Значення my_number додатнє");
console.log("і це парне число");
}
else
{
console.log("Значення my_number або дорівнює 0 чи негативне");
console.log("та/або непарне число");
}
Оператор подвійного амперсанда &&
в оцінюваному виразі є логічним оператором AND. Він оцінюється як істина, лише якщо вираз ліворуч та вираз праворуч оцінюються як істина. Якщо ви хочете знайти числа, які є додатними або парними, замість цього слід використовувати оператор ||
, що відповідає логічному оператору OR:
let my_number = -4;
if ( my_number > 0 || my_number % 2 == 0 )
{
console.log("Значення my_number додатнє");
console.log("або парне від'ємне число");
}
У цьому прикладі лише негативні непарні числа не відповідатимуть критеріям, встановленим цим складеним виразом. Якщо у вас є протилежний намір, тобто знайти лише негативні непарні числа, додайте логічний оператор NOT !
на початку виразу:
let my_number = -5;
if ( ! ( my_number > 0 || my_number % 2 == 0 ) )
{
console.log("Значення my_number є непарним від'ємним числом");
}
Додавання дужок до складеного виразу змушує спочатку оцінювати охоплений ними вираз. Без цих дужок оператор NOT застосовувався б лише до my_number > 0
, а потім обчислювався вираз OR. Оператори &&
та ||
відомі як бінарні логічні оператори, оскільки вони вимагають двох операндів. !
відомий як унарний логічний оператор, оскільки він вимагає лише одного операнда.
Switch структури
Хоча структура if
є досить універсальною та достатньою для керування ходом програми, структура керування switch
може бути більш прийнятною, коли потрібно оцінити результати, відмінні від true чи false. Наприклад, якщо ми хочемо виконати окрему дію для кожного елемента, вибраного зі списку, потрібно буде написати структуру if
для кожної оцінки:
// Доступні мови: en (English), es (Spanish), pt (Portuguese)
let language = "pt";
// Змінна для реєстрації факту, чи була мова знайдена у списку
let found = 0;
if ( language == "en" )
{
found = 1;
console.log("English");
}
if ( found == 0 && language == "es" )
{
found = 1;
console.log("Spanish");
}
if ( found == 0 && language == "pt" )
{
found = 1;
console.log("Portuguese");
}
if ( found == 0 )
{
console.log(language, " невідома мені мова");
}
У цьому прикладі допоміжна змінна found
використовується всіма структурами if
, щоб дізнатися, чи відбувся збіг. У такому випадку структура switch
виконуватиме те саме завдання, але в більш стислий манері:
switch ( language )
{
case "en":
console.log("English");
break;
case "es":
console.log("Spanish");
break;
case "pt":
console.log("Portuguese");
break;
default:
console.log(language, " не знайдено");
}
Кожен вкладений case
називається блоком. Коли блок відповідає виразу, який оцінюється, виконуються оператори після двокрапки до оператора break
. Останній блок не потребує оператора break
і часто використовується для встановлення дії за замовчуванням, коли іншиз збігів не було. Як видно з прикладу, допоміжна змінна не потрібна в структурі switch
.
Warning
|
|
Якщо більше ніж один блок ініціює одну і ту саму дію, ви можете поєднати дві або більше умов case
:
switch ( language )
{
case "en":
case "en_US":
case "en_GB":
console.log("English");
break;
case "es":
console.log("Spanish");
break;
case "pt":
case "pt_BR":
console.log("Portuguese");
break;
default:
console.log(language, " не знайдено");
}
Цикли
У попередніх прикладах структури if
і switch
добре підходили для завдань, які потрібно було виконати лише один раз після перевірки однієї або кількох умов. Однак бувають ситуації, коли завдання має виконуватися неодноразово, у так званому циклі, поки перевірка його умовного виразу продовжує давати true. Наприклад, якщо вам потрібно знати, чи є число простим, потрібно буде перевірити, чи при діленні цього числа на будь-яке ціле число, більше 1 і менше за задане число, остача дорівнює 0. Якщо так, число має цілий дільник і не є простим. (Це не строгий чи ефективний метод пошуку простих чисел, але він працює як простий приклад.) Структури керування циклом більше підходять для таких випадків, зокрема оператор while
:
// Примітивний валідатор простих чисел
// Число, яке ми хочемо оцінити
let candidate = 231;
// Допоміжна змінна
let is_prime = true;
// Перший дільник для перевірки
let factor = 2;
// Виконайте блочний оператор, якщо множник
// менший за число, яке ми тестуємо, і продовжуйте це робити,
// поки множник менший за число, яке ми тестуємо
while ( factor < candidate )
{
if ( candidate % factor == 0 )
{
// Залишок дорівнює нулю, тож задане число не є простим
is_prime = false;
break;
}
// Наступний дільник для перевірки.
// Просто збільшуємо поточний дільник на одиницю
factor++;
}
// Відображення результату у вікні консолі.
// Якщо candidate не має цілих дільників, тоді
// допоміжна змінна is_prime досі true
if ( is_prime )
{
console.log(candidate, "є простим числом");
}
else
{
console.log(candidate, "не є простим числом");
}
Оператор блоку після інструкції while
виконуватиметься неодноразово, доки умова factor < candidate
є істинною. Він виконується принаймні один раз, якщо ми ініціалізуємо змінну factor
зі значенням, меншим за candidate
. Структура if
, вкладена в структуру while
, оцінить, чи дорівнює нулю залишок від ділення candidate
на factor
. Якщо так, число-кандидат не є простим, і цикл може завершитись. Оператор break
завершить цикл, а виконання перейде до першої інструкції після блоку while
.
Зауважте, що результат умови, що використовується оператором while
, повинен змінюватися в кожному циклі, інакше оператор блоку буде виконуватись в циклі "завжди". У прикладі ми збільшуємо змінну factor
на одиницю, це наступний дільник, який ми хочемо спробувати, і це гарантує, що в якийсь момент цикл закінчиться.
Ця проста реалізація тестера простих чисел працює, як очікувалося. Проте ми знаємо, що число, яке не ділиться на два, також не ділиться ні на яке інше парне число. Тому ми можемо просто пропустити парні числа, додавши іншу інструкцію if
:
while ( factor < candidate )
{
// Пропускаємо парні дільники, більші за два
if ( factor > 2 && factor % 2 == 0 )
{
factor++;
continue;
}
if ( candidate % factor == 0 )
{
// Залишок дорівнює нулю, тому кандидат не є простим числом
is_prime = false;
break;
}
// Наступне число, на яке спробуємо ділити кандидата
factor++;
}
Оператор continue
схожий на оператор break
, але замість того, щоб завершити цю ітерацію циклу, він ігнорує решту блоку циклу та почне нову ітерацію. Зверніть увагу, що змінна factor
була змінена перед оператором continue
, інакше цикл знову мав би той самий результат на наступній ітерації. Цей приклад занадто простий, і пропуск частини циклу насправді не покращить його продуктивність, але пропуск зайвих інструкцій дуже важливий при написанні ефективних програм.
Цикли настільки широко використовуються, що існують у багатьох різних варіантах. Цикл for
спеціально підходить для перебору послідовних значень, оскільки він дає змогу нам визначити правила циклу в одному рядку:
for ( let factor = 2; factor < candidate; factor++ )
{
// Пропускаємо парні дільники більші за два
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// Залишок дорівнює нулю, тому кандидат не є простим числом
is_prime = false;
break;
}
}
Цей приклад дає той самий результат, що й попередній приклад while
, але його вираз у дужках містить три частини, розділені крапкою з комою: ініціалізацію (let factor = 2
), умову циклу (factor <application
) та кінцевий вираз, який буде оцінено в кінці кожної ітерації циклу (factor++
). Операції continue
і break
також застосовуються до циклів for
. Кінцевий вираз у дужках (factor++
) буде оцінено після оператора continue
, тому він не повинен бути всередині оператора блоку, інакше перед наступною ітерацією він буде збільшений у два рази.
У JavaScript є спеціальні типи циклів for
для роботи з об’єктами, подібними до масиву. Наприклад, ми могли б перевірити масив змінних-кандидатів замість однієї змінної:
// Примітивний валідатор простих чисел
// Масив чисел, які ми плануємо протестувати
let candidates = [111, 139, 293, 327];
// Оцінюємо кожного кандидата в масиві
for (candidate of candidates)
{
// Auxiliary variable
let is_prime = true;
for ( let factor = 2; factor < candidate; factor++ )
{
// Пропускаємо парні множники більші за два
if ( factor > 2 && factor % 2 == 0 )
{
continue;
}
if ( candidate % factor == 0 )
{
// Залишок дорівнює нулю, тому кандидат не є простим числом
is_prime = false;
break;
}
}
// Відображення результату у вікні консолі
if ( is_prime )
{
console.log(candidate, "є простим числом");
}
else
{
console.log(candidate, "не є простим числом");
}
}
Оператор for (candidate of candidates)
призначає один елемент масиву candidates
змінній candidate
і використовує його в блочному операторі, повторюючи процес для кожного елемента в масиві. Вам не потрібно оголошувати candidate
окремо, тому що цикл for
визначає його. Нарешті, той самий код з попереднього прикладу був вкладений в цей новий блоковий оператор, але цього разу тестувався кожен кандидат у масиві.
Вправи до посібника
-
Які значення змінної
my_var
відповідають умовіmy_var > 0 && my_var < 9
? -
Які значення змінної
my_var
відповідають умовіmy_var > 0 || my_var < 9
? -
Скільки разів наступний цикл
while
виконує свій блочний оператор?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Дослідницькі вправи
-
Що станеться, якщо використовувати оператор рівності
=
замість оператора порівняння==
? -
Напишіть фрагмент коду, використовуючи структуру керування
if
, де звичайне порівняння рівності повертає істину, а жорстке порівняння рівності ні. -
Перепишіть наступний оператор for, використовуючи унарний логічний оператор NOT в умові циклу. Результат умови має бути таким самим.
for ( let factor = 2; factor < candidate; factor++ )
-
На основі прикладів з цього уроку напишіть структуру керування циклом, яка виводить усі цілі дільники заданого числа.
Підсумки
Цей урок розповідає про те, як використовувати структури керування в коді JavaScript. Умовні та циклічні структури є важливими елементами будь-якої парадигми програмування, і веброзробка JavaScript не є винятком. Урок охоплює такі поняття та процедури:
-
Оператор
if
та оператори порівняння. -
Використання структури
switch
зcase
,default
таbreak
. -
Різниця між звичайним і жорстким порівнянням.
-
Структури керування циклом:
while
таfor
.
Відповіді до вправ посібника
-
Які значення змінної
my_var
відповідають умовіmy_var > 0 && my_var < 9
?Лише числа, одночасно більші за 0 і менші за 9. Логічний оператор
&&
(AND) вимагає, щоб обидва порівняння збігалися. -
Які значення змінної
my_var
відповідають умовіmy_var > 0 || my_var < 9
?Використання логічного оператора
||
(OR) призведе до збігу будь-якого числа, оскільки будь-яке число буде більше 0 або менше 9. -
Скільки разів наступний цикл
while
виконує свій блочний оператор?let i = 0; while ( 1 ) { if ( i == 10 ) { continue; } i++; }
Блочний оператор буде повторюватися необмежену кількість разів, оскільки не зазначена умова зупинки.
Відповіді до дослідницьких вправ
-
Що станеться, якщо використовувати оператор рівності
=
замість оператора порівняння==
?Значення в правій частині оператора призначається змінній зліва, а результат передається до порівняння, що може бути не бажаним.
-
Напишіть фрагмент коду, використовуючи структуру керування
if
, де звичайне порівняння рівності повертає істину, а жорстке порівняння рівності ні.let a = "1"; let b = 1; if ( a == b ) { console.log("Результат звичайного порівняння - співпадає."); } if ( a === b ) { console.log("Результат жорсткого порівняння - не співпадає."); }
-
Перепишіть наступний оператор for, використовуючи унарний логічний оператор NOT в умові циклу. Результат умови має бути таким самим.
for ( let factor = 2; factor < candidate; factor++ )
Відповідь:
for ( let factor = 2; ! (factor >= candidate); factor++ )
-
На основі прикладів з цього уроку напишіть структуру керування циклом, яка виводить усі цілі дільники заданого числа.
for ( let factor = 2; factor <= my_number; factor++ ) { if ( my_number % factor == 0 ) { console.log(factor, " є цілим дільником ", my_number); } }