حلقهی For یکی از پرکاربردترین دستورها برای اجرای مکرر یک منطق است.
در JavaScript، این حلقه از کلیدواژهی for، یک سرآیند که درون پرانتز قرار میگیرد و یک بلوک کد که بدنهی حلقه را در بر میگیرد و درون آکولاد میآید، تشکیل شده است.
for (initialization; condition; step) {
// code that is executed repeatedly as long as the condition is
// true
}
مقداردهی اولیه معمولاً یک متغیر شمارنده را آماده میکند، شرط بررسی میکند که آیا حلقه باید ادامه یابد یا متوقف شود و گام، شمارنده را در پایان هر تکرار یک واحد افزایش میدهد. بخشهای جداگانهی سرآیند با نقطهویرگول از هم جدا میشوند.
const list = ['a', 'b', 'c'];
for (let i = 0; i < list.length; i++) {
// code that should be executed for each item in the array
}
هر سه بخش سرآیند اختیاریاند. این ویژگی در عمل بهندرت به کار میرود. میتوانید دربارهی آن بیشتر در مستندات MDN بخوانید.
حلقههای For را میتوان تودرتو کرد، مثلاً برای پیمایش آرایههای تودرتو (چندبعدی). دقت کنید که برای هر حلقه یک متغیر شمارندهی متفاوت در نظر بگیرید.
const coords = [
[1, 2],
[4, 7],
[10, -3],
];
for (let i = 0; i < coords.length; i++) {
for (let j = 0; j < coords[i].length; j++) {
// do something with coords[i][j]
}
}
break، continue و برچسبهادرون بدنهی حلقه میتوانید از کلیدواژهی break استفاده کنید تا اجرای حلقه را بهطور کامل متوقف کنید.
در مقابل، کلیدواژهی continue فقط اجرای تکرار جاری را متوقف میکند و با تکرار بعدی ادامه میدهد.
هنگام کار با حلقههای تودرتو، break و continue بهطور پیشفرض همیشه به درونیترین حلقه اعمال میشوند.
میتوانید با برچسبها این رفتار را تغییر دهید.
برچسب یک اسم شناسه است که پس از آن یک دونقطه میآید.
برچسب پیش از حلقه (یا بالای آن) قرار میگیرد.
سپس میتوان چنین برچسبی را با break یا continue ترکیب کرد تا مشخص شود دستور به کدام حلقه اعمال میشود.
outer: for (let i = 0; i < 10; i++) {
for (let j = 0; j < 10; j++) {
// ...
if (j > 5) {
continue outer;
}
// ...
}
}
هنگام کار با کد غیرهمزمان باید دقت کنید که متغیر شمارنده را درست تعریف کنید.
بیایید به مثالی نگاه کنیم که در آن متغیر شمارنده را بهصورت غیرهمزمان با setTimeout و پس از انتظار ۱ ثانیه جمع میزنیم.
اگر شمارنده را با var یا با let اما بیرون از سرآیند تعریف کنید، کد نتیجهی مورد انتظار را نمیدهد.
let sum = 0;
for (var i = 1; i < 4; i++) {
setTimeout(function () { sum += i; }, 1000);
}
// eventually sum will be 12 instead of 6 (1+2+3)
let sum = 0;
let i;
for (i = 1; i < 4; i++) {
setTimeout(function () { sum += i; }, 1000);
}
// same here, eventually sum will be 12 instead of 6 (1+2+3)
در این دو حالت، i به یک تکرار مشخص از حلقه محدود نمیشود.
زمانی که مجموع محاسبه میشود، i پیشتر به مقدار نهایی خود یعنی 4 رسیده است و همین باعث میشود مجموع برابر 4 + 4 + 4 = 12 شود.
میتوان با تعریف شمارنده با let درون سرآیند از این مشکل جلوگیری کرد.
این کار این اثر ویژه را دارد که هر تکرار، متغیر مخصوص به خود یعنی let i را میگیرد که دقیقاً به همان یک بار اجرای بدنهی حلقه محدود است.
بنابراین وقتی مجموع بعداً محاسبه میشود، هر تابع کالبک به متغیر i خودش ارجاع میدهد که هنوز مقدار درست را نگه داشته است.
let sum = 0;
for (let i = 1; i < 4; i++) {
setTimeout(function () { sum += i; }, 1000);
}
// eventually sum will be 6 (1+2+3) as expected