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


محمد أحمد العيل

فلنفترض أنك تريد تشغيل دالة اسمها bounceBall أربع مرات. كيف يمكنك ذلك؟ هل ستختار الطريقة التالية؟:

function bounceBall() {
  // bounce the ball here
}

bounceBall()
bounceBall()
bounceBall()
bounceBall()

يمكن أن تكون الطريقة أعلاه مناسبة إذا كنت تريد تنفيذ الدالة بضع مرات. مالذي سيحدُث إن احتجت لتنفيذ الدالة bounceBall مئة مرة؟

الطريقة الأفضل في هذه الحالة هي استخدام تعليمة التكرار الحلقي for.

تعليمة التكرار الحلقي for

تنفّذ تعليمة التكرار الحلقي for كتلة من التعليمات البرمجية بعدد المرات التي تريد. في ما يلي مثال على تنفيذ الدالة bounceBall عشر مرات:

for (let i = 0; i < 10; i++) {
  bounceBall()
}

تتكوّن التعليمة for من أربعة أجزاء:

  • العبارة الابتدائية initialExpression
  • الشرط condition
  • عبارة الزيادة incrementalExpression
  • والجملة statement
for (initialExpression; condition; incrementExpression) {
  statement
}

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

تأخذ التعليمة for الصيغة التالية عند استخدام الدالة bounceBall في الجزء الخاصّ بالجملة:

for (initialExpression; condition; incrementExpression) {
  bounceBall()
}

ستحتاج كذلك إلى تعريف عبارة ابتدائية Initial expression تبدأ بها تعليمة التكرار الحلقي. هذا هو الجزء الذي تعرّف فيه متغيرا. من المتعارف عليه تسمية المتغير الابتدائي في تعليمة for بالحرف i وإعطاؤه القيمة 0.

هكذا تبدو صيغة for عند تحديد عبارتها الابتدائية:

for (let i = 0; condition; incrementExpression) {
  bounceBall()
}

نزيد قيمة المتغيّر (i في مثالنا) - أو ننقُصه - بعد تنفيذ الحلقة التكرارية لأول مرة، وذلك عن طريق عبارة الزيادة Incremental expression. لزيادة قيمة المتغير i بواحد نعيد إسناده بحيث يُصبح يساوي i + 1 أي بالعبارة i = i + 1. تُختَصر العبارة i = i + 1على ++i والتي يكثُر استخدامها في حلقات التكرار. لنقص قيمة المتغير i بواحد نعيد إسناده بحيث يُصبح يساوي i - 1، أي بالعبارة i = i - 1. تُختَصر العبارة i = i - 1 على --i.

بالعودة إلى المثال مع الدالة bounceBall فإننا زدنا المتغيّر i في كل مرة بواحد. تصبح صيغة التعليمة for على النحو التالي:

for (let i = 0; condition; i++) {
  bounceBall()
}

لكن… هل يجدُر بي زيادة قيمة المتغيّر أم النقص منها؟

توجد الإجابة في الجزء الأخير من تعليمة التكرار الحلقي for وهو الشرط. في حالة تحقّق الشرط - أي أن قيمته تساوي true - فإن الجملة الموجودة في التعليمة for تُنفَّذ وإلا فلا.

ينفّذ مفسر جافاسكريبت عبارة الزيادة incrementalExpression مباشرة بعد تنفيذ الجملة statement ثم يتحقّق مجدّدًا من أن قيمة الشرط تساوي true فإن كان الأمر كذلك نفّذ الجملة statement مرة أخرى. يعيد المفسّر الكرة إلى أن تصبح قيمة الشرط false. حينها يتجاوز الحلقة التكرارية وينفّذ الشفرة التي تليها.

إن لم تكن تريد تنفيذ الحلقة فيمكنك جعل قيمة الشرط مساوية لـ false منذ البداية:

// لن تُنفَّذ الحلقة التكرارية التالية نظرا لأن قيمة الشرط تساوي false
for (let i = 0; i < 0; i++) {
  bounceBall()
  const timesBounced = i + 1
  console.log('The ball has bounced ' + timesBounced + ' times')
}
// ستُنفّذ الشفرة التالية فقط
console.log('next line of code')

ستكون نتيجة تنفيذ الشفرة أعلاه على النحو التالي:

next line of code

عندما تريد تنفيذ الحلقة التكرارية مرتين فستحتاج إلى تغيير الشرط بحيث تكون قيمته false بعد تنفيذ عبارة الزيادة مرتين:

// ستُنفّذ الحلقة التكرارية التالية مرتين
for (let i = 0; i < 2; i++) {
  bounceBall()
  const timesBounced = i + 1
  console.log('The ball has bounced ' + timesBounced + ' times')")
}

console.log('next line of code')

النتيجة:

The ball has bounced 1 times
The ball has bounced 2 times
next line of code

أما إذا أردت تشغيل الحلقة عشر مرات فسيتوجّب عليك تغيير الشرط بحيث تصبح قيمته false بعد تنفيذ عبارة الزيادة عشر مرات.

// ستُنفّذ الحلقة التكرارية التالية عشر مرات
for (let i = 0; i < 10; i++) {
  bounceBall()
  const timesBounced = i + 1
  console.log('The ball has bounced ' + timesBounced + ' times')")
}

console.log('next line of code')

النتيجة:

01_ten-times.png

الحلقات غير المحدودة Infinite loops

نجد أنفسنا أمام حلقات غير محدودة عندما تكون قيمة الشرط في الحلقة التكرارية for مساوية دائما لـtrue، ممّا يتسبّب في تجمّد التبويب أو المتصفّح ونحتاج بالتالي لإغلاقه وإعادة تشغيله.

استخدام الحلقات التكرارية مع المصفوفات Arrays

في الواقع لن تحتاج كثيرا لاستخدام الحلقات التكرارية لتنفيذ دالة عشر مرات كما فعلنا مع الدالة bounceBall السابقة. أغلب استخدامات الحلقات التكرارية هو مع المصفوفات أو الكائنات Objects.

يتمثّل التكرار عبر المصفوفة في المرور مرة واحدة على كل عنصُر في المصفوفة. بالإمكان استخدام طول المصفوفة (التابع length) في الجزء الخاص بالشرط من تعليمة التكرار.

const fruitBasket = ['موزة', 'تفاحة', 'إجاصة']

// fruitBasket.length is 3
for (let i = 0; i < fruitBasket.length; i++) {
  console.log("توجد " + fruitBasket[i] + " في السلة")
}

النتيجة:

توجد موزة في السلة
توجد تفاحة في السلة
توجد إجاصة في السلة

هناك طريقة بديلة وهي استخدام عبارة نقص بدلًا من عبارة الزيادة، وذلك بالبدء من نهاية المصفوفة في العبارة الابتدائية ضمن تعليمة التكرار:

for (let i = fruitBasket.length - 1; i >= 0; i--) {
  console.log("توجد " + fruitBasket[i] + " في السلة")
}

النتيجة (لاحظ الفرق):

توجد إجاصة في السلة
توجد تفاحة في السلة
توجد موزة في السلة

المرور على المصفوفات بالحلقة for of

هناك طريقة ثالثة - أفضل بكثير - للمرور عبر مصفوفة، وهي استخدام تعليمة التكرار الحلقي for...of وهي تعليمة جديدة من إضافات المعيار ES6. تُكتَب التعليمة بالصيغة التالية

const fruitBasket = ['موزة', 'تفاحة', 'إجاصة']
for (let fruit of fruitBasket) {
  console.log("توجد " + fruit + " في السلة")
}

النتيجة:

توجد موزة في السلة
توجد تفاحة في السلة
توجد إجاصة في السلة

يُفضَّل استخدام التعليمة for ...of بدلا من الطريقة التقليدية لاستخدام تعليمة التكرار الحلقي for عند التعامل مع المصفوفات فهي تمرّ على المصفوفة لمرة واحدة فقط، كما لا تحتاج إلى طول المصفوفة؛ ممّا يجعل قراءة الشفرة وصيانتها أيسر بكثير.

يمكن استخدام التعليمة for ...of مع أي كائن لديه الخاصيّة Symbol.iterator. إن طبعت مصفوفة فارغة باستخدام التعليمة console.log فسترى أن لديها خاصيّة باسم Synmbol.iterator (ضمن المفتاح _proto_).

02_Iterator.png

العمليات المنطقية في الحلقات التكرارية

يمكنك استخدام if/else أو أي عمليات منطقية أخرى داخلة حلقة for التكرارية.

فلنفترض مثلا أن لديك مصفوفة بمجموعة من الأعداد وتريد إنشاء مصفوفة ثانية تتضمّن أعداد المصفوفة الأولى التي تصغُر 20.

حتى تصل إلى هدفك فيجب أن تمرّ أولا على عناصر المصفوفة الأولى بحلقة for:

const numbers = [25, 22, 12, 56, 8, 18, 34];

for (let num of numbers) {
  // سنكمل التعليمات بعد قليل
}

ثم نتحقّق ما إذا كان العنصُر الذي نمرّ عليه يقل عن 20. تصبح الشفرة كالتالي:

const numbers = [25, 22, 12, 56, 8, 18, 34];

for (let num of numbers) {
  if (num < 20) {
    // نكمل بعد قليل
  }
}

إذا كان العنصُر أصغر من 20 نضيفه إلى مصفوفة أخرى. نستعمل التابع push لهذا الغرض. تصبح الشفرة كالتالي (smallerThan20 هو اسم المصفوفة الثانية):

const numbers = [25, 22, 12, 56, 8, 18, 34];
let smallerThan20 = []

for (let num of numbers) {
  if (num < 20) {
    smallerThan20.push(num)
  }
}

ترجمة - بتصرّف - للمقال Understanding for loops لصاحبه Zell Liew.





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن