Menu
العربية

حلقة for في JavaScript: الصيغة، break و continue

شرح عملي لحلقة for في JavaScript: الصيغة المكوّنة من ثلاثة أجزاء، المرور على المصفوفات، استخدام break و continue، الحلقات المتداخلة، وأشهر الأخطاء التي يقع فيها المبتدئون.

حلقة for الكلاسيكية في جافا سكريبت

لمّا تكون عارف عدد المرات اللي تحتاج تكرّر فيها شيء معيّن، حلقة for هي الأداة المناسبة. فهي تجمع الأجزاء الثلاثة لأي حلقة معدودة — نقطة البداية، شرط التوقف، ومقدار الزيادة — في سطر واحد بالأعلى.

index.js
Output
Click Run to see the output here.

خمس تكرارات، خمسة أسطر في المخرجات. هيّا نقرأ ترويسة الحلقة:

  • let i = 0 يُنفَّذ مرة واحدة فقط قبل بدء الحلقة، ومهمته تهيئة العدّاد.
  • i < 5 هو الشرط الذي يُفحص قبل كل تكرار؛ فإن كان true نُفِّذ جسم الحلقة، وإن كان false انتهت الحلقة.
  • i++ يُنفَّذ بعد كل تكرار، وقبل إعادة فحص الشرط مباشرةً.

لاحظ أن الأجزاء الثلاثة مفصولة بفواصل منقوطة (;) لا بفواصل عادية. ورغم أن كلًّا منها اختياري، إلا أنه من النادر حذفها؛ فلو احتجت ذلك ستلجأ عادةً إلى while بدلًا من for.

كيف تتكامل هذه الأجزاء معًا

لتثبيت ترتيب التنفيذ في ذهنك، لا شيء أفضل من تتبّع حلقة واحدة يدويًا خطوة بخطوة:

index.js
Output
Click Run to see the output here.

خطوة بخطوة:

  1. let i = 1 — يتم إنشاء العدّاد وتعيين قيمته إلى 1.
  2. نتحقق من i <= 3 — الشرط صحيح، إذن ننفّذ جسم الحلقة. نطبع 1.
  3. نُنفّذ i++ — تصبح قيمة i تساوي 2.
  4. نتحقق من i <= 3 — صحيح. نطبع 2.
  5. نُنفّذ i++ — تصبح i تساوي 3.
  6. نتحقق من i <= 3 — صحيح. نطبع 3.
  7. نُنفّذ i++ — تصبح i تساوي 4.
  8. نتحقق من i <= 3 — خطأ. نخرج من الحلقة.

لاحظ أن خطوة التحديث تنفَّذ بعد جسم الحلقة وليس قبله، وهذه هي النقطة التي يقع فيها الكثيرون في الالتباس.

المرور على مصفوفة بالفهرس في جافا سكريبت

أكثر استخدام شائع لحلقة for في جافا سكريبت هو المرور على عناصر المصفوفة، حيث يقوم العدّاد بدور الفهرس في الوقت نفسه:

index.js
Output
Click Run to see the output here.

بعض النقاط المهمة التي يجدر الانتباه إليها:

  • المصفوفات في جافا سكريبت تبدأ فهرستها من الصفر. أول عنصر موجود عند الفهرس 0، وآخر عنصر عند length - 1.
  • الشرط هنا هو i < fruits.length وليس i <= fruits.length. لو استخدمت <= فستتجاوز نهاية المصفوفة بخطوة واحدة وستطبع undefined.
  • عرّفنا i باستخدام let، وبالتالي نطاقه محصور داخل الحلقة فقط. خارج الحلقة لن يكون له وجود.

إذا كنت تحتاج إلى القيم فقط دون الفهرس، فإن for...of أقصر وأوضح — وسنتناولها بالتفصيل في درس مستقل.

break: الخروج المبكر من الحلقة

تُخرجك break من الحلقة فوراً. وهي مفيدة عندما تعثر على ما تبحث عنه ولا حاجة لمواصلة التكرار:

index.js
Output
Click Run to see the output here.

بمجرد تنفيذ break، ينتقل التحكم مباشرة إلى ما بعد القوس المغلق للحلقة. خطوة التحديث لا تُنفَّذ، والشرط لا يُفحص مرة أخرى — الحلقة ببساطة انتهت.

continue: تخطّي هذه التكرارة

الكلمة continue تتجاهل بقية التكرارة الحالية وتنتقل مباشرة إلى خطوة التحديث. الحلقة تستمر في العمل، لكنها لا تُكمل الدورة الحالية.

index.js
Output
Click Run to see the output here.

الأرقام الزوجية تصل إلى continue فتتخطى console.log، ولا تُطبع سوى الأرقام الفردية. تفيدك continue عندما تريد استبعاد تكرارات معيّنة دون أن تُغلّف بقية جسم الحلقة داخل if.

خطوات غير الزيادة بواحد

خطوة التحديث ما هي إلا تعبير عادي، وليس شرطًا أن تكون i++. لنَعُدّ مثلًا اثنين اثنين:

index.js
Output
Click Run to see the output here.

Count down:

index.js
Output
Click Run to see the output here.

المرور على المصفوفة بشكل عكسي — مفيد أحياناً لما تكون بتحذف عناصر أثناء المرور:

index.js
Output
Click Run to see the output here.

أيًا كان اختيارك، القاعدة نفسها: الشرط والتحديث لازم يشتغلا معًا بحيث يصبح الشرط false في النهاية. لو ما حصل هذا، ستعمل الحلقة إلى ما لا نهاية. مثلًا for (let i = 0; i < 10; i--) هي حلقة لا نهائية في جافا سكريبت، لأن i يتحرك في الاتجاه الخطأ.

الحلقات المتداخلة في جافا سكريبت

تقدر تضع حلقة for داخل حلقة for أخرى. الحلقة الداخلية تكمل دورتها بالكامل مع كل تكرار من الحلقة الخارجية.

index.js
Output
Click Run to see the output here.

تسعة أسطر في المخرجات: ثلاث تكرارات للحلقة الخارجية، وثلاث للداخلية مع كل واحدة منها. أعطِ كل عدّاد اسماً واضحاً مثل row/col أو i/j بدلاً من إعادة استخدام نفس المتغير.

انتبه لنقطة مهمة: break و continue يؤثران فقط على الحلقة الأقرب (الداخلية). الخروج من الحلقة الداخلية بـ break لا يوقف الخارجية. إذا احتجت إلى ذلك، استخدم متغيراً كـ"علامة" (flag) وافحصه في الحلقة الخارجية، أو انقل الكود المتداخل إلى دالة مستقلة واستخدم return للخروج منها.

أخطاء شائعة في حلقة for

هناك بعض الأخطاء التي يقع فيها المبتدئون كثيراً:

أخطاء الفرق بواحد (Off-by-one). كتابة i <= arr.length تجعل الحلقة تدور خطوة زائدة، بينما i < arr.length - 1 توقفها قبل النهاية بخطوة. الصيغة المعتمدة دائماً هي i < arr.length.

نسيان تحديث العدّاد. إذا أغفلت i++ أو ما يعادلها، فلن تتغير قيمة العدّاد أبداً وستحصل على حلقة لا نهائية تدور بلا توقف:

for (let i = 0; i < 10; ) {
    console.log(i); // لا ينتهي أبدًا
}

استخدام var مع العدّاد. الكلمة var نطاقها الدالة بأكملها، لذا يتسرّب العدّاد خارج الحلقة ويسبب مفاجآت غير متوقعة داخل الإغلاقات (closures). التزم بـ let.

تعديل المصفوفة أثناء المرور عليها. حذف العناصر يُزحزح الفهارس فتتخطى عناصر دون قصد. إذا احتجت للحذف، مُرّ على المصفوفة بشكل عكسي، أو ابنِ مصفوفة جديدة باستخدام filter.

متى تستخدم بديلاً عن حلقة for؟

حلقة for الكلاسيكية متاحة دائمًا، لكن جافا سكريبت تقدّم خيارات أقصر للحالات الشائعة:

  • المرور على قيم مصفوفة: for (const item of array) أنظف وأوضح.
  • تحويل مصفوفة: array.map(fn) تُرجع مصفوفة جديدة.
  • التصفية: array.filter(fn).
  • الجمع أو الاختزال: array.reduce(fn, start).
  • تنفيذ شيء ما لكل عنصر فقط: array.forEach(fn).

ارجع إلى حلقة for الكلاسيكية حين تحتاج فعلاً إلى الفهرس، أو حين تريد التخطي أو الخروج في المنتصف عبر break وcontinue، أو حين تحتاج خطوات غير قياسية مثل العدّ التنازلي (حلقة for عكسية) أو القفز باثنين.

التالي: حلقات while

حلقة for تتألّق حين تعرف المدى مسبقًا. أمّا حين لا تعرفه — حين تريد الاستمرار حتى يتغيّر شرط ما — فإن while وdo...while هما الأنسب. وهذا ما سنتناوله في الصفحة التالية.

الأسئلة الشائعة

ما هي صيغة حلقة for في JavaScript؟

تتكوّن من ثلاثة أجزاء يفصل بينها فاصلة منقوطة داخل الأقواس: for (init; condition; update) { ... }. جزء init ينفّذ مرة واحدة في البداية، وcondition يُفحص قبل كل دورة، وupdate ينفّذ بعد نهاية كل دورة. المثال الكلاسيكي: for (let i = 0; i < 10; i++) { ... }.

كيف أمرّ على عناصر مصفوفة باستخدام حلقة for؟

تقدر تستخدم حلقة for تقليدية مع مؤشر: for (let i = 0; i < arr.length; i++) { console.log(arr[i]); }. إذا ما كنت محتاج رقم العنصر، فحلقة for...of أنظف بكثير: for (const item of arr) { ... }. أما إذا كان هدفك تحويل العناصر أو فلترتها، فالأفضل استخدام دوال المصفوفات مثل map و filter.

كيف تعمل كلمتا break و continue داخل حلقة for؟

break تخرج من الحلقة فوراً وتنتقل للكود الذي يليها. أما continue فتتخطى باقي الدورة الحالية فقط، وتنتقل مباشرة إلى خطوة update ثم تعيد فحص الشرط. كلاهما يؤثر على الحلقة الداخلية الأقرب فقط، إلا إذا استخدمت التسميات (labels).

لماذا تعمل حلقة for عندي بشكل لا نهائي؟

في الغالب لأن خطوة update لا تقرّب الشرط من false أبداً. مثلاً for (let i = 0; i < 10; i--) ستعمل إلى ما لا نهاية، لأن i تبدأ من 0 وتصبح أصغر في كل دورة. راجع الشرط وخطوة التحديث، ولازم تكون متوافقة بحيث يصبح الشرط false في لحظة ما.

تعلّم البرمجة مع Coddy

ابدأ الآن