Галоўная / Артыкулы

Асаліны цыклаў у TypeScript: while, do-while, for, break і continue

Дазвольце дазнацься, як цыклы while, do-while і for у TypeScript ацэнююць свае умовы, чаму змена дыямэнту зменны ў цыкле паўтарае рэзультаты, і як ключавыя словы break і continue зменяюць тэкстуру виконання коду.

Выдавец: REACTAPP.TOP9 хв чытання1983 слоў

Крыніцы: Mastering Loops in TypeScript: while, do-while, for, break & continue

Ціклы дазваляюць запускаць той самы блак ад коду парадозна, калі выплывае паводлівасць, замест таго каб перакладаць адзін за адным выказванні. Яны здаюцца простымі, але большасць бягоў у ціклах вынікае з трох пунктав: калі перакладваецца паводлівасць, дзе знаходзіцца зменная цікла і дзе ў тэле цікла распаложыцца break або continue. У гідзе прадстаўлены ціклы TypeScript while, do-while і for з малымі прыкладамі, выход якіх можна спакульгаваць па лініях, тады вы зможаце чытаць і пісаць код для ітерацый без неспадзянак.

Чаму ітерацыя кращая за парадоз

Для выведзення цифр з 1 да 10 без цікла патрабуецца дзесяць вызоваў console.log. З ціклам вы описваеце задачу адназначна, а система яе парадозна, і размах коду застаецца тым жа, незалежна ад таго, чырэз дзесяць чы ў дзесяць тысяч разоў трэба яго запускаць.

Цікл while: спачатку перакладванне, потым запуск

Цыкл while мае найпростейшую структуру з усіх:

while (condition) {
  // statements
}

Умова ацэнаваная до кожнага проходжэння цыклу. Калі яна true, выпаняецца тэла цыклу; калі становіцца false, цыкл завершаецца. Для правяльнага while-циклу патрэбны тры элементы:

  • пачатковая значэнне для зменнай, ад кой караецца умова;
  • сама умова;
  • элемент у тэле цыклу, який спрыяе таму, каб умова стала false.

Якщо прыняць трэці элемент, цыкл ніколі не завершыцца, што ўзьятае пад увагу нижэй.

Працаванне ад 1 да 10

Тут видны всі тры элементы: i пачынаецца з 1, цыкл працюе, паколькі i <= 10, а i++ паднімае його значэнне пасля кожнага проходжэння:

let i: number = 1; // initialization
while (i <= 10) {
  console.log(i);
  i++;
}

Фільтрацыя чэснага лічб

Ёнколі хочаце выдрукуваць толькі чысла з парных числаў у гэтым дзіапазоне, трэба продовжваць пераглядаць кожную значэнне, але дадаць перакананне ў самым кодзе. Аператар модуля % вяртае залишок ад дзелення, таму i % 2 == 0 ўсё правда тады, калі i яе парнае:

let i: number = 1;
while (i <= 10) {
  if (i % 2 == 0) {
    console.log(i);
  }
  i++;
}

Існуе простыяй спосаб разлічвання да падобнага рэзультата: не трэба выканання пераканання ўзагалі, а трэба кожны раз прыбавляць 2. Заўважыце, што гэты варіянт пачынаецца з 0, таму ў яго выходзе таксама будзе 0:

let i: number = 0;
while (i <= 10) {
  console.log(i);
  i = i + 2;
}

Выход: 0, 2, 4, 6, 8, 10

Фільтраўанне нечыслаў

Якша змяніць умову на != 0, тады будуць выбраны нечыслаў. Пачатак з 0 тут нешкодны, таму што 0 яе парнае і ёй будзе фільтраванаць:

let i: number = 0;
while (i <= 10) {
  if (i % 2 != 0) {
    console.log(i);
  }
  i++;
}

Выход: 1, 3, 5, 7, 9

У гэтых прыкладах выкарыстоўваюцца == і !; строгія формы === і !== зазвычай ўжываюцца, таму што яны ніколі не ператвараюць типы, хоця для двух числаў рэзультат застаецца ідэнтычным.

Абліквач

Ёсць калькуляваць у спад, трэба пачаць з вялікага значэння і зменшваць яго, пакуль яго значэнне будзе прынямнае, тое ўсё 1:

let i: number = 10;
while (i >= 1) {
  console.log(i);
  i--;
}

Бесканечныя цыклы і прычыны ўтварэння іх

Умова while — гэта проста выраз, які дае булева значэння, таму while (true) ўсё абсалютна дазволены. Цыкл нижчэй будзе выдаваць данні вечна, таму што нічога не можа яго завершыць:

let i: number = 1;
while (true) {
  console.log(i);
  i++;
  // no break, no exit condition this runs forever
}

Часта прычына бесканцэнтных цыклаў — адпаведная зменная ніколі не абнавляецца чы працюе неправильна. Такі цыкл блакуе ўсё іншае на сваймай гілцы, таму вікна браузера чы процесы Node.js здаюцца застойванымі. Намерны while (true) ўсё ж дапускаецца, якщо ён супакоўваецца за дапамогою чыстае выходу, зазвычай break (пераказана нижэй), напрыклад у логіцы «прабаваць па-новай, пакуль не будзе успеху».

Цыкл do-while: выконваецца адной раз, потым пераказваецца

У цыкле do-while умова пераказваецца толькі ў канцы:

do {
  // statements
} while (condition);

Паколькі пераказваўце выконванняяецца пасля тэлы, тэла завжды выконваецца прынеймна адной раз, незалежна ад таго, якая ўмова. На протыяжэнні, звычны while можа не выконвацца жаданы раз.

Калі умова спачатку ў значэнні true, do-while паводзіцца так сама, як і while:

let i: number = 1;
do {
  console.log(i);
  i++;
} while (i <= 5);

Разлік стае пометным, калі умова з самага пачатку ў спрэчы:

let i: number = 10;
do {
  console.log(i);
  i++;
} while (i <= 5);

Расход: 10

Корпус ціклу выконваецца без умов, выдрукуючы 10 і паднімаючы i да 11. Лявае тады выконвуецца i <= 5; яго рэзультат — false, таму цікл завершаецца пасля аднай ітерацыі. Цікл while (i <= 5), які пачынаецца з 10, нічога не выдрукуе. Выкорыстоўваюце do-while, калі неабходна прынеймней адна першая ітерацыя, напрыклад, каб хоць раз паказаць запит.

Цікл for: усё ў аднай заголовцы

Цікл for — гэты той, які вы будете викорыстоўваць найчащэй, особліва калі заздалегідь ведаеце, сколькі разоў трэба павтарыць або на сколькі должна змяніцца лічылка. Ён аб’еднвае ініцыялізацыю, умову і апдэйт у адну заголовцы, што робіць яго болей компактным чым адпаведны while:

for (initialization; condition; increment/decrement) {
  // statements
}

Порядак, у якому выконваюцца этыя часты, варта запам’ятаваць:

  1. Ініцыялізацыя выконваецца адна раз, перш чым працюе ўсё інше (на прыклад let i = 1).
  2. Оцэнюецца умова. Якщо яна true, выконваецца тэла циклу; якщо false, цикл завершаецца.
  3. Пасля тэла выконваецца выраз для апдэйта (на прыклад i++).
  4. Контроль вяртаецца да пункту 2, і цикл павтараецца, пакуль умова не стане false.

Іншымі словамі, ініцыялізацыя выконваецца толькі адна раз, тады як умова і апдэйт выконваюцца ў кожны цикл.

Праляганне ад 1 да 10

for (let i = 1; i <= 10; i++) {
  console.log(i);
}

Два спосабы отрымання чэтных чисоў

Як і у while, можна пралягаць па два елементы:

for (let i = 2; i <= 10; i += 2) {
  console.log(i);
}

альбо пераглядаць кожную значэнне і фільтруваць яе ў тэле циклу:

for (let i = 2; i <= 10; i++) {
  if (i % 2 == 0) {
    console.log(i);
  }
}

Оба спосабы выдрукваюць тую ж самую последовальнасць:

2
4
6
8
10

Метод «Stepping» выкарыстоўвае меншае количество операцый, таму што ён пераглядае толькі чэсныя значэння; фільтрацыя є болей гнучкай, калі правіла не являюцца фіксаваным крокам, напрыклад «дзелімы на 3 або 7».

Скарчванне

Апдэйт зі зменшэнням значэння запускае цыкл у зворачным напрамку:

for (let i = 10; i >= 1; i--) {
  console.log(i);
}

Рэзультат: 10, 9, 8, 7, 6, 5, 4, 3, 2, 1

Чаму зменная цыклу становіцца 6 пасля завершэння цыклу

Месца, дзе вы працэўваеце зменную цыклу, вялічыць тое, што застаноўся пасля ёй. У гэтым прыкладзе i працэўваецца перад цыклам, а блок for толькі прызначае ёй значэння:

let i: number;
for (i = 1; i <= 5; i++) {
  console.log(i);
}
console.log(i);

Рэзультат: 1, 2, 3, 4, 5, 6

Паколькі i знаходзіцца ў зовнішнем прыметку, выкананне console.log(i) у канцы все ж такі можа даўжыну яго значэння, якое засталося пасля ціклу. Гэта 6, а не 5, з-за прабегу аперацый: пад час последнага пройшчы i равнае 5, код выведае яго, а пасля актуалізацыі його значэнне становіцца 6, і толькі тады умова 6 <= 5 не выпалюеся і цікл завершаецца.

Больш распашчытаны стыль, for (let i = 1; i <= 5; i++), стварае прыметку i у блакучым прыметку, якая дзейсніца толькі пад час ціклу, таму пасля яго ёй вяршыцца. Апіл да яе пасля ціклу ў TypeScript вызывае памылку часу компілявання (“Cannot find name 'i'”), а ў звычным JavaScript вызываецца ReferenceError часу выканання. Яшчэ краща яе задаць у заголовку; вярхнюе заданне трэба выкарыстоўваць толькі тады, калі патрэбна фінальная значэнне.

Змена прабегу ціклу за дапамой break і continue

Две заповедзі ўскоку дазваюць змяніць нормальны ход цыклу заўтрачэння ў яго тэле:

  • break негайна завершае цыкл, незалежна ад таго, сколькі ітерацый засталаеся.
  • continue прыпіняе толькі текущую ітерацыю і пераходзіць да наступной; цыкл продовжвае працаваць.

У цыкле for заповедзь continue все равно выконвае выраз апдэйта прытым, як прабуецца зноў пераканацца у выпалоўваючай умове, таму лічылка продовжвае растаць.

break: важна пазіцыя ў тэле

Ёсць прыклад, калі перакананне break выконваецца раней за выведэнне:

let i: number;
for (i = 1; i <= 10; i++) {
  if (i == 5) {
    break;
  }
  console.log(i);
}

Раслідаванне: 1, 2, 3, 4

Калі i досягае 5, цыкл завершваецца раней, чым console.log мае можлівасць выконацца, таму 5 ніколі не праказваецца.

Якшчы перасунуць выведэнне раней за перакананне, рысунок змініцца:

let i: number;
for (i = 1; i <= 10; i++) {
  console.log(i);
  if (i == 5) {
    break;
  }
}

Рэзультат: 1, 2, 3, 4, 5

Условіе застаўляецца незменным, пры тым 5 тепер апісваецца, таму што вывод практыкуецца раней за пераконтроўкай. Каля break і continue аднойчы, порядак запаведзей у тэле вяліканае значэнне для рэзультата.

continue: прыпусканне адной значэння

Замена break на continue ператварае "зупінка на 5" у "прыпусканне 5">:

let i: number;
for (i = 1; i <= 10; i++) {
  if (i == 5) {
    continue;
  }
  console.log(i);
}

Рэзультат: 1, 2, 3, 4, 6, 7, 8, 9, 10

Цикл продовжваецца; ён проста не выводзіць даныя для той адной ітерацыі.

Прыпусканне кожнага нечыёвага числа

У поўнанні з фільтрам, continue направляе кожная нечыёвае значэнне безпосередзьва да наступной ітерацыі:

let i: number;
for (i = 0; i <= 10; i++) {
  if (i % 2 != 0) {
    continue;
  }
  console.log(i);
}

Рэзультат: 0, 2, 4, 6, 8, 10

Прыпусканне спецыяльных значэнняў з ліста

Умова можа быць настолькі складной, насколькі вы хачаце. За дапамою логічнага аператара OR || гэты цыкл прыходзіць за 3, 5 і 7:

let i: number;
for (i = 0; i <= 10; i++) {
  if (i == 3 || i == 5 || i == 7) {
    continue;
  }
  console.log(i);
}

Рэзультат: 0, 1, 2, 4, 6, 8, 9, 10

Для дыявольскай лісты прыхоўдзеньня [3, 5, 7].includes(i) або Set ўжываюцца лепей.

Ключовыя моманты

  • while пераказвае сваяю умову пры кожным цікле і можа не выконвацца ні разу; do-while пераказвае яе пасля і завжды выконваецца прынеймна раз.
  • Кожны цыкл патрэбуе апдэйта, який зрэшты зробіць умову няправдзівай; інакш будзе бесканцовы цыкл, який заблокуе адэнт.
  • У цыкле for ініцыялізацыя выконваецца адна раз, тады як умова і апдэйт — пры кожным цікле, таму лічыльнік заканчваецца на адны крок пасля ліміту.
  • Акларацыя лічыльніка за дапамою let у пачатку ціклу дзеўае яму межы ціклу; акларацыя яго за межамі ціклу дазволяе яго заканчоўнай значэнню застацца.
  • break завершае цікл, а continue прыпускае адна ітерацыя; месца ўстановкі гэтых каманд у адносе да іншых запаведзей вплывае на рэзультат.
  • Умовныя операторы выбіраюць, калі выконваецца код; ціклы выбіраюць, як часта. Яе разам вони пакрываюць большую частку потока керавання, які вы будете пісаць.