Оператор label
Оператор label (мітка) дає ім'я блоку коду або циклу, щоб потім керувати виконанням через break чи continue, вказуючи, який саме цикл перервати або продовжити. Це рідкісний і маловживаний інструмент JavaScript, який має сенс майже виключно у вкладених циклах.
Теорія
TL;DR
- Мітка це ім'я, яке ставлять перед блоком або циклом:
outer: for (...) { ... }. break outerперериває позначений цикл цілком, а не лише внутрішній.continue outerпропускає поточну ітерацію позначеного зовнішнього циклу.- Мітки не створюють нової області видимості і не є аналогом
goto. - Код з мітками зазвичай гірше читається, тому їх беруть лише тоді, коли інакше вийти з вкладених циклів незручно.
Швидкий приклад
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) break outer;
console.log(`i = ${i}, j = ${j}`);
}
}Результат:
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 1, j = 0Синтаксис
Мітку можна поставити перед звичайним блоком:
labelName: {
// інструкції
}Але найчастіше її ставлять перед циклом:
labelName:
for (let i = 0; i < 5; i++) {
// тіло циклу
}Ім'я мітки це звичайний ідентифікатор, після нього йде двокрапка. Мітка і цикл можуть стояти на одному рядку або на різних, це справа стилю.
Навіщо потрібна мітка: вихід із вкладених циклів
Зазвичай мітку беруть тоді, коли є вкладені цикли і треба вийти не лише з внутрішнього, а одразу з зовнішнього. Без міток break і continue впливають тільки на найближчий цикл.
Приклад без мітки:
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) break;
console.log(`i = ${i}, j = ${j}`);
}
}Результат:
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 1, j = 0
i = 2, j = 0
i = 2, j = 1
i = 2, j = 2Тут break зупиняє лише внутрішній цикл, а зовнішній (i) спокійно йде далі, до i = 2.
Приклад з міткою:
outerLoop: // мітка для зовнішнього циклу
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (i === 1 && j === 1) break outerLoop;
console.log(`i = ${i}, j = ${j}`);
}
}Результат:
i = 0, j = 0
i = 0, j = 1
i = 0, j = 2
i = 1, j = 0Тепер break outerLoop перериває весь зовнішній цикл, а не лише внутрішній.
continue з міткою
Так само можна пропустити ітерацію зовнішнього циклу, якщо виконується умова:
outer: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 2) continue outer; // пропускає поточний i
console.log(`i = ${i}, j = ${j}`);
}
}Результат:
i = 0, j = 0
i = 0, j = 1
i = 1, j = 0
i = 1, j = 1
i = 2, j = 0
i = 2, j = 1Щойно j доходить до 2, керування переходить до наступної ітерації зовнішнього циклу.
Що важливо пам'ятати
| Що робить | Приклад |
|---|---|
| Дає ім'я циклу або блоку | outer: for (...) { ... } |
| Дозволяє вийти з зовнішнього циклу | break outer; |
| Дозволяє пропустити ітерацію зовнішнього циклу | continue outer; |
| Створює нову область видимості | Ні |
| Використовувати часто? | Ні, лише за потреби |
Додатково:
- Мітки не створюють нових областей видимості, це просто імена, до яких звертаються
breakіcontinue. - Мітку не можна використати для довільних переходів, як
gotoв інших мовах (наприклад, у C). continueз міткою працює тільки з циклами, тоді якbreakз міткою працює і з міченим блоком.
Типові помилки
- Сприймати мітку як
goto. Стрибнути вперед або назад у довільне місце не можна: дозволено лише вийти з поміченої конструкції або перейти до її наступної ітерації. - Ставити
continueз міткою на звичайному блоці. Це синтаксична помилка,continueвимагає, щоб мітка стояла на циклі. - Використовувати мітку там, де достатньо функції. Часто винесення вкладених циклів в окрему функцію і звичайний
returnчитається краще, ніжbreak outer. - Плутати мітку з оголошенням змінної.
outer:це не змінна, звертатися до неї як до значення не можна. - Зловживати мітками. Вони рідкісні саме тому, що ускладнюють читання; беріть їх лише тоді, коли альтернатива виходить громіздкою.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.