ما معمولا نیاز داریم که کارها رو تکرار کنیم.
برای مثال، کالاهایی را از یک لیست یکی پس از دیگری نمایش دهیم یا کد مشابهی رو برای هر عدد از 1 تا 10 اجرا کنیم.
حلقه ها راهی برای تکرار یک کد برای چندین بار هستند.
حلقه “while”
اعلانی برای خوانندههای پیشرفته.
این مقاله تنها حلقههای پایهای را پوشش میدهد: while، do..while و for(..;..;..).
اگر شما برای جستجوی انواع دیگر حلقه به این مقاله آمدهاید، اینجا اشاراتی به آنها را داریم:
- حلقه for…in را برای حلقه زدن در ویژگیهای شیء ببینید.
- حلقه for…of و iterables را برای حلقه زدن در آرایهها و شیءهای حلقهپذیر ببینید.
در غیر این صورت، لطفا خواندن را ادامه دهید.
حلقه while سینتکس زیر را دارد:
while (condition) {
// کد
// به اصطلاح "بدنه حلقه"
}
تا وقتی که condition truthy باشد، کد قسمت بدنه حلقه اجرا می شود.
برای مثال، حلقه پایین i را تا وقتی که i < 3 باشد، نمایش می دهد:
let i = 0;
while (i < 3) { // 0 را نمایش می دهد، سپس 1، سپس 2
alert( i );
i++;
}
یک بار اجرا شدن بدنه حلقه را یک تکرار می نامند. حلقه داخل مثال بالا سه تکرار می سازد.
اگر i++ از مثال بالا جا می ماند، حلقه (در تئوری) برای همیشه اجرا می شد. در عمل، مرورگر راه هایی را برای متوقف کردن چنین حلقه هایی مهیا می کند، و در جاوااسکریپت سمت سرور، ما می توانیم فرایند را نابود کنیم.
هر عبارت یا متغیری می تواند یک شرط حلقه باشد، نه فقط مقایسه ها: شرط توسط while ارزیابی می شود و به boolean تبدیل می شود.
برای مثال، یک راه کوتاه تر برای نوشتن while (i != 0) while (i) است:
let i = 3;
while (i) { // وقتی که i برابر با 0 شود، شرط falsy شده، و حلقه متوقف می شود
alert( i );
i--;
}
اگر بدنه حلقه یک دستور واحد داشته باشد، ما می توانیم آکولادها {...} را حذف کنیم:
let i = 3;
while (i) alert(i--);
حلقه “do…while”
بررسی شرط با استفاده از سینتکس do..while می تواند به پایین بدنه حلقه منتقل شود.
do {
// بدنه حلقه
} while (condition);
حلقه اول بدنه را اجرا می کند، سپس شرط را بررسی می کند، و تا وقتی که truthy باشد، دوباره و دوباره آن(بدنه) را اجرا می کند.
برای مثال:
let i = 0;
do {
alert( i );
i++;
} while (i < 3);
این شکل از سینتکس باید فقط زمانی استفاده شود که شما بخواهید بدنه حلقه جدای از اینکه شرط truthy باشد حداقل یک بار اجرا شود. معمولا، شکل دیگر ترجیح داده می شود: while(...) {...}.
حلقه “for”
حلقه for پیچیده تر است، اما این حلقه بیشترین استفاده را هم دارد.
اینطور به نظر می رسد:
for (begin; condition; step) {
// ... بدنه حلقه ...
}
بیایید معنی این قسمت ها را با مثال یاد بگیریم. حلقه زیر alert(i) را برای هر i از 0 تا 3 (خود 3 شامل نمی شود) اجرا می کند:
for (let i = 0; i < 3; i++) { // 0 را نمایش می دهد، سپس 1، سپس 2
alert(i);
}
بیایید شرح for را قسمت به قسمت بررسی کنیم:
| قسمت | ||
|---|---|---|
| begin(آغاز) | i = 0 |
به محض ورود به حلقه اجرا می شود. |
| condition(شرط) | i < 3 |
قبل از هر تکرار حلقه بررسی می شود. اگر false باشد حلقه متوقف می شود. |
| body(بدنه) | alert(i) |
تا زمانی که شرط truthy باشد همچنان اجرا می شود. |
| step(قدم) | i++ |
در هر تکرار بعد از بدنه اجرا می شود. |
الگوریتم کلی حلقه مثل قسمت پایین کار می کند:
begin را اجرا کن
→ (if condition → body را اجرا کن و step را اجرا کن)
→ (if condition → body را اجرا کن و step را اجرا کن)
→ (if condition → body را اجرا کن و step را اجرا کن)
→ ...
یعنی اینکه، begin یک بار اجرا می شود، و سپس این تکرار می شود: بعد از هر بار آزمایش condition، body و step اجرا می شوند.
اگر شما تازه با حلقه ها آشنا شدید، به مثال برگردید و مراحل اجرای آن را مرحله به مرحله روی یک کاغذ بازتولید کنید.
در مورد ما، دقیقا این اتفاق می افتد:
// for (let i = 0; i < 3; i++) alert(i)
// begin را اجرا کن
let i = 0
// if condition → body را اجرا کن و step را اجرا کن
if (i < 3) { alert(i); i++ }
// if condition → body را اجرا کن و step را اجرا کن
if (i < 3) { alert(i); i++ }
// if condition → body را اجرا کن و step را اجرا کن
if (i < 3) { alert(i); i++ }
// ...پایان، چون حالا i == 3
اینجا، متغیر “شمارنده” i دقیقا داخل حلقه تعریف شده است. این یک تعریف “درون خطی” متغیر نامیده می شود. این چنین متغیرهایی تنها داخل حلقه قابل رویت هستند.
for (let i = 0; i < 3; i++) {
alert(i); // 0, 1, 2
}
alert(i); // ارور، چنین متغیری وجود ندارد
ما می توانستیم به جای تعریف کردن یک متغیر، از یک متغیر موجود استفاده کنیم:
let i = 0;
for (i = 0; i < 3; i++) { // استفاده از یک متغیر موجود
alert(i); // 0, 1, 2
}
alert(i); // 3، قابل دیدن است، چون بیرون از حلقه تعریف شده است
قسمت های قابل جا انداختن
هر قسمت for را می توان از قلم انداخت.
برای مثال، اگر نیاز به انجام کاری در آغاز حلقه نداشته باشیم می توانیم begin را حذف کنیم.
مثل اینجا:
let i = 0; // ما i را داریم که از قبل تعریف شده و تخصیص داده شده است.
for (; i < 3; i++) { // نیازی به "begin" نیست
alert( i ); // 0, 1, 2
}
همچنین ما می توانیم قسمت step را حذف کنیم:
let i = 0;
for (; i < 3;) {
alert( i++ );
}
این کار حلقه را برابر با while (i < 3) می کند.
در واقع ما می توانیم همه چیز را حذف کنیم، یک حلقه بی نهایت بسازیم:
for (;;) {
// بدون محدودیت تکرار می شود
}
لطفا در نظر داشته باشید که هر دو نقطه ویرگول ; داخل for باید وجود داشته باشند. در غیر این صورت، یک سینتکس ارور به وجود خواهد آمد.
متوقف کردن حلقه
به طور معمول، یک حلقه زمانی که شرط آن falsy شود متوقف می شود.
اما ما می توانیم با استفاده از دستور خاص break آن را در هر لحظه مجبور به توقف کنیم.
برای مثال، حلقه زیر از کاربر یک سری عدد درخواست می کند، و زمانی که هیچ عددی وارد نشد “متوقف می شود”:
let sum = 0;
while (true) {
let value = +prompt("یک عدد وارد کنید", '');
if (!value) break; // (*)
sum += value;
}
alert( 'مجموع: ' + sum );
اگر کاربر یک خط خالی وارد کند یا ورودی را لغو کند دستور break در خط (*) فعال می شود. حلقه را بلافاصله متوقف می کند، و کنترل را به اولین خط بعد از حلقه می سپارد. یعنی، alert.
ترکیب “حلقه بی نهایت + break در صورت نیاز” برای موقعیت هایی که یک شرط حلقه نباید در آغاز یا انتهای حلقه بررسی شود، بلکه در وسط یا حتی چند جای بدنه آن بررسی شود عالی است.
ادامه دادن به تکرار بعدی
دستور continue یک “نسخه سبک تر” از break است. حلقه را متوقف نمی کند. در عوض، تکرار حال حاضر را متوقف می کند و حلقه را مجبور می کند که یک تکرار جدید را شروع کند (اگر شرط اجازه دهد).
ما می توانیم در صورتی که با تکرار حال حاضر کارمان تمام شده باشد و بخواهیم به تکرار بعدی برویم از آن استفاده کنیم.
حلقه پایین از continue فقط برای نشان دادن مقدارهای فرد استفاده می کند.
for (let i = 0; i < 10; i++) {
// اگر true باشد، قسمت باقی مانده بدنه را از قلم بنداز
if (i % 2 == 0) continue;
alert(i); // 1، سپس 9 ،7 ،5 ،3
}
برای مقدار های زوج i، دستور continue اجرا کردن بدنه را متوقف می کند و کنترل را به تکرار بعدی for می دهد (به همراه عدد بعدی). پس alert فقط برای مقدارهای فرد صدا زده می شود.
continue به کم کردن تو در تو بودن کمک می کندیک حلقه که اعداد فرد را نمایش می دهد می توانست اینطور باشد:
for (let i = 0; i < 10; i++) {
if (i % 2) {
alert( i );
}
}
از دیدگاه فنی، این شبیه مثال بالا است. مسلما، ما می توانیم کد را داخل یک بلوک if بگذاریم به جای اینکه از continue استفاده کنیم.
اما به عنوان یک عارضه جانبی، یک سطح بیشتری از تودرتویی می سازد (صدا زدن alert داخل آکولادها). اگر کد داخل if بیشتر از چند خط باشد، ممکن است خوانایی کلی را کاهش دهد.
break/continue در سمت راست ‘?’لطفا در نظر داشته باشید که ساختارهای سینتکس که عبارت نیستند نمی توانند با عملگر ternary ? استفاده شوند. به خصوص، دستورهایی مثل