21 вересня 2023 р.

Конструкція "switch"

Конструкція switch може замінити кілька if.

Вона дає можливість більш наочного способу порівняння значення відразу з кількома варіантами.

Синтаксис

Конструкція switch має один або більше case блоків та необов’язковий блок default.

Вона виглядає так:

switch(x) {
  case 'value1':  // if (x === 'value1')
    ...
    [break]

  case 'value2':  // if (x === 'value2')
    ...
    [break]

  default:
    ...
    [break]
}
  • Значення змінної x перевіряється на строгу рівність (=== ) значенню із першого блоку case (яке дорівнює value1), потім значенню із другого блоку (value2) і так далі.
  • Якщо строго рівне значення знайдено, то switch починає виконання коду із відповідного case до найближчого break або до кінця всієї конструкції switch.
  • Якщо жодне case- значення не збігається – виконується код із блоку default (якщо він присутній).

Приклад роботи

Приклад використання switch (код який буде виконаний виділено):

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Замало' );
    break;
  case 4:
    alert( 'Точнісінько!' );
    break;
  case 5:
    alert( 'Забагато' );
    break;
  default:
    alert( 'Я не знаю таких значень' );
}

Тут switch починає порівнювати a з першим варіантом із case, який дорівнює 3. Це не відповідає a.

Потім з другим, який дорівнює 4. Цей варіант відповідає a, таким чином буде виконано код з case 4 до найближчого break.

Якщо break відсутній, то буде продовжено виконання коду наступних блоків case без перевірок.

Приклад без break:

let a = 2 + 2;

switch (a) {
  case 3:
    alert( 'Замало' );
  case 4:
    alert( 'Точнісінько!' );
  case 5:
    alert( 'Забагато' );
  default:
    alert( 'Я не знаю таких значень' );
}

В прикладі вище ми бачимо послідовне виконання трьох alert:

alert( 'Точнісінько!' );
alert( 'Забагато' );
alert( 'Я не знаю таких значень' );
Any expression can be a switch/case argument

Обидва switch та case допускають будь-який вираз в якості аргументу.

Наприклад:

let a = "1";
let b = 0;

switch (+a) {
  case b + 1:
    alert("виконано це, бо +a це 1, що строго дорівнює b + 1");
    break;

  default:
    alert("це не буде виконано");
}

Тут значення виразу +a буде 1, що збігається з значенням виразу b + 1 із блоку case, таким чином код із цього блоку буде виконано.

Групування “case”

Кілька варіантів блоку case, які використовують однаковий код, можуть бути згруповані.

Наприклад, якщо ми бажаємо виконати один і той самий код для case 3 та case 5:

let a = 3;

switch (a) {
  case 4:
    alert('Вірно!');
    break;

  case 3: // (*) групуємо два блоки `case`
  case 5:
    alert('Невірно!');
    alert("Можливо вам варто відвідати урок математики?");
    break;

  default:
    alert('Результат виглядає дивно. Дійсно.');
}

Тепер обидва варіанти 3 та 5 виводять однакове повідомлення.

Можливість групування блоків case – це побічний ефект того, як switch/case працює без break. Тут виконання коду case 3 починається з рядка (*) та проходить через case 5, бо немає break.

Тип має значення

Необхідно наголосити, що перевірка відповідності є завжди строгою. Значення повинні бути однакового типу аби вони збігалися.

Наприклад, розглянемо наступний код:

let arg = prompt("Введіть значення?");
switch (arg) {
  case '0':
  case '1':
    alert( 'Один або нуль' );
    break;

  case '2':
    alert( 'Два' );
    break;

  case 3:
    alert( 'Ніколи не буде виконано!' );
    break;
  default:
    alert( 'Невідоме значення' );
}
  1. Для 0 та 1 буде виконано перший alert.
  2. Для 2 – другий alert.
  3. Але для 3: результат виконання prompt є строкове значення "3", яке строго не дорівнює === числу 3. Таким чином ми маємо “мертвий код” в блоці case 3! Буде виконано код блоку default.

Завдання

важливість: 5

Напишіть код з використанням if..else, що відповідає наступній конструкції switch:

switch (browser) {
  case 'Edge':
    alert( "You've got the Edge!" );
    break;

  case 'Chrome':
  case 'Firefox':
  case 'Safari':
  case 'Opera':
    alert( 'Ми підтримуємо і ці браузери' );
    break;

  default:
    alert( 'Маємо надію, що ця сторінка виглядає добре!' );
}

Щоб точно відповідати функціональності конструкції switch, if повинен використовувати строге порівняння '==='.

Хоча для даних рядків звичайне '==' також працює.

if(browser == 'Edge') {
  alert("You've got the Edge!");
} else if (browser == 'Chrome'
 || browser == 'Firefox'
 || browser == 'Safari'
 || browser == 'Opera') {
  alert( 'Ми підтримуємо і ці браузери' );
} else {
  alert( 'Маємо надію, що ця сторінка виглядає добре!' );
}

Зверніть увагу: конструкція browser == 'Chrome' || browser == 'Firefox' … розділена на кілька рядків для кращої читабельності.

Але конструкція switch більш чистіша та наочніша.

важливість: 4

Перепишіть код нижче використовуючи одну конструкцію switch:

let a = +prompt('a?', '');

if (a == 0) {
  alert( 0 );
}
if (a == 1) {
  alert( 1 );
}

if (a == 2 || a == 3) {
  alert( '2,3' );
}

Перші дві перевірки перетворюємо в два case. Третю перевірку розділяємо на два case:

let a = +prompt('a?', '');

switch (a) {
  case 0:
    alert( 0 );
    break;

  case 1:
    alert( 1 );
    break;

  case 2:
  case 3:
    alert( '2,3' );
    break;
}

Зверніть увагу: break знизу не обов’язковий. Але ми його вказуємо, щоб зробити наш код надійнішим за умови майбутніх змін.

У майбутньому є можливість що ми додамо ще один блок case, наприклад case 4. В разі якщо ми забудемо додати break перед ним наприкінці коду з case 3, – ми отримаємо помилку у логіці роботи нашого коду. Таким чином це своєрідне самострахування.

Навчальна карта