الوحدة 2 · المنطق والدوال
حلقات التكرار: for وfor…of وwhile
16 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
تكرّر العمل باستخدام for…of وحلقة for العدّادة وwhile، وتتوقّف مبكرًا بـ break وcontinue، وتستخدم نمط المُراكِم (accumulator) لحساب مجموع قائمة مصاريف.
- 1قائمة نمرّ عليها
- 2for…of: افعل هذا لكل عنصر
- 3حلقة for العدّادة
- 4while: كرّر حتى يتغيّر شيء ما
- 5break وcontinue
- 6أن ترى ما تفعله الحلقة
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
حتى الآن، كل مثال في Pocket جمع عددًا ثابتًا من المصاريف: coffee + lunch + bus. لكن الإنفاق الحقيقي قائمة تكبر كل يوم، ولا يمكنك كتابة + لعناصر لم تصلك بعد. تحتاج إلى طريقة تقول بها “افعل هذا لكل واحد منها”، وهذه هي حلقة التكرار (loop).
قائمة نمرّ عليها
للقوائم درس كامل في القسم 3، لكنك تحتاج أساسياتها الآن. قائمة القيم بين أقواس مربّعة اسمها مصفوفة (array):
const amounts = [450, 1220, 270, 899];
console.log(amounts.length); // how many items
console.log(amounts[0]); // the first item: positions start at 0for…of: افعل هذا لكل عنصر
تنفّذ for...of كتلتها مرة لكل عنصر، مع اسم تختاره أنت يشير إلى العنصر الحالي:
const amounts = [450, 1220, 270, 899];
let total = 0;
for (const amount of amounts) {
total += amount;
}
console.log(total);تتبّعها خطوة بخطوة كما يفعل المحرّك. يبدأ total من 0. الدورة الأولى: amount تساوي 450، فيصبح total يساوي 450. الدورة الثانية: amount تساوي 1220، فيصبح total يساوي 1670. ثم 1940، ثم 2839. لم يتبقَّ أي عنصر، فتنتهي الحلقة ويطبع السطر التالي المجموع.
يُسمّى هذا الشكل نمط المُراكِم (accumulator pattern): صرّح بنتيجة قبل الحلقة، وحدّثها داخلها، واستخدمها بعدها. وهو وراء المجاميع والأعداد والقيم القصوى ومعظم الملخّصات التي ستكتبها. واستخدام const amount سليم مع أنها تتغيّر في كل دورة: فكل دورة تُنشئ amount جديدة، ولا يُعاد إسنادها أبدًا.
وتعمل for...of أيضًا مع النصوص، حرفًا حرفًا: for (const ch of "Pocket").
حلقة for العدّادة
أحيانًا تحتاج إلى الموضع إلى جانب العنصر، مثلًا لتطبع “1. Coffee”. لحلقة for الكلاسيكية ثلاثة أجزاء بين قوسيها:
const labels = ["Coffee", "Lunch", "Bus"];
for (let i = 0; i < labels.length; i++) {
console.log(`${i + 1}. ${labels[i]}`);
}جزء البداية، let i = 0، يُنفَّذ مرة واحدة. ثم قبل كل دورة يُفحص الشرط i < labels.length؛ فإن كان صحيحًا نُفّذ الجسم، ثم يضيف التحديث i++ واحدًا إلى i. وحين يصبح الشرط خاطئًا تنتهي الحلقة. مع ثلاث تسميات، تأخذ i القيم 0 و1 و2، وهي الفهارس الصالحة بالضبط.
while: كرّر حتى يتغيّر شيء ما
حلقة while ليس فيها إلا شرط. إنها للحالات التي تعرف فيها متى تتوقّف، لكن لا تعرف كم دورة سيستغرق ذلك. كم يومًا تستطيع أن تشتري قهوة بـ 4.50 دولار بميزانية قدرها 20 دولارًا؟
let balance = 2000;
const coffee = 450;
let days = 0;
while (balance >= coffee) {
balance -= coffee;
days++;
}
console.log(`${days} coffees, ${balance} cents left`);كل دورة تُنقص balance، فيصبح الشرط خاطئًا في النهاية. ولو لم يكن في الجسم ما يقترب من المخرج، كأن تنسى balance -= coffee، لبقي الشرط صحيحًا إلى الأبد. وهذه حلقة لا نهائية (infinite loop): تتجمّد الصفحة، ويعرض عليك المتصفّح في النهاية إيقاف السكربت. وحين يتجمّد تبويب أثناء تدرّبك، ابحث عن حلقة لا يتغيّر شرطها أبدًا.
break وcontinue
كلمتان مفتاحيتان تغيّران مسار الحلقة من داخلها:
breakتُنهي الحلقة فورًا.continueتتخطّى باقي هذه الدورة وتنتقل إلى التالية.
const amounts = [450, -300, 1220, 270, 899];
const budget = 2000;
let running = 0;
for (const amount of amounts) {
if (amount < 0) {
continue; // a refund: not spending, skip it
}
running += amount;
if (running > budget) {
console.log(`Budget passed at an expense of ${amount}`);
break; // no need to look further
}
}
console.log(running);تتبّعها: يُضاف 450، ثم يُتخطّى -300، ثم يرفع 1220 المجموع إلى 1670، ثم يرفعه 270 إلى 1940، ثم يدفعه 899 إلى 2839، وهذا يتجاوز الميزانية، فتُطبع الرسالة وتتوقّف الحلقة.
أن ترى ما تفعله الحلقة
الحلقات هي المكان الذي يفقد فيه المبتدئون أثر ما يفعله البرنامج أكثر من أي مكان آخر، لأن الأسطر نفسها تُنفَّذ مرات كثيرة بقيم مختلفة. والعلاج أن تجعل الحلقة تُريك. ضع console.log في أول الجسم يطبع كل متغيّر له علاقة:
const amounts = [450, 1220, 270];
let total = 0;
for (let i = 0; i < amounts.length; i++) {
console.log({ i, amount: amounts[i], totalBefore: total });
total += amounts[i];
}
console.log("final", total);كل دورة تطبع سطرًا واحدًا، فتستطيع أن تقارن ما حدث فعلًا بما توقّعته، وتجد أول دورة يختلفان فيها. تلك الدورة هي مكان الخطأ. ووضع القيم داخل { } يطبعها مع أسمائها، فلا تحتاج إلى تخمين أيّ رقم هو أيّ متغيّر. المطوّرون المحترفون يفعلون هذا بالضبط كل يوم؛ وفي القسم 5 ستتعلّم فعله أيضًا باستخدام مصحّح الأخطاء (debugger) في DevTools.
الحلقات والشروط معًا تتيح لك كتابة منطق حقيقي من الآن. ولكي تعيد استخدام هذا المنطق بدلًا من نسخه، تحتاج إلى دوالّك الخاصة، وهذا موضوع الدرس التالي.
أهم النقاط
for...ofتمرّ على كل عنصر في القائمة بالترتيب، وهي حلقة التكرار الافتراضية لـ “افعل هذا لكل مصروف”.- حلقة
forالعدّادة تعطيك فهرسًا، وتحتاجه حين يهمّ الموضع؛ والفهارس الصالحة تمتد من 0 إلىlength - 1. whileتكرّر ما دام الشرط صحيحًا، لذلك يجب أن يجعله شيء داخل الحلقة خاطئًا في النهاية.- نمط المُراكِم (ابدأ من 0، وأضف داخل الحلقة، واستخدم الناتج بعدها) يحوّل قائمة إلى مجموع واحد.