التكرار (loop) في JavaScript
يعتبر التكرار (Loop) من المفاهيم الأساسية في JavaScript، إذ يوفّر آلية لتنفيذ مجموعة من الأوامر بشكل متكرر وفق شرط محدد، بدلاً من إعادة كتابة الكود يدوياً…. هذا المفهوم لا يقتصر على تقليل حجم الكود فحسب، بل يُسهم أيضاً في تحسين قابليته للقراءة والصيانة، كما يُعد جزءاً محورياً في بناء الخوارزميات ومعالجة البيانات…
في هذا المقال سيتم تناول جُمل التكرار في JavaScript من منظور عملي وتحليلي، مع توضيح متى ولماذا يُستخدم كل نوع من أنواع الحلقات. سنبدأ باستعراض الفكرة العامة لجُمل التكرار، ثم ننتقل إلى شرح جمل التكرار المتوفرة في جافا سكريبت مثل while و for. كما سنستعرض آليات التحكم في التكرار باستخدام break و continue، وصولاً إلى مناقشة التكرارات المتداخلة (Nested Loops) .. لنبدأ
نتعرف في هذا المقال على :
- جُمل التكرار (Loops) في JavaScript.
- جُمل while فى JavaScript.
- جُمل for في JavaScript.
- التحكم بالتكرار بواسطة break و continue.
- التكرارات المتداخلة Nested loop في JavaScript.
جُمل التكرار (Loops) في JavaScript
جملة التكرار في البرمجة هي أحد جُمل التحكم التي تُتيح تنفيذ كتلة من التعليمات البرمجية بشكل متكرر بناءً على شرط مُحدد. وهذا يسمح بالتكرار الفعال على هياكل البيانات أو بتنفيذ الإجراءات عدة مرات. ولهذا قد نشير لها بمسمى حلقة ( Loop) او حلقة التكرار. وتختلف جُمل التكرار من لغة برمجية الى اخرى بناء على قواعد اللغة نفسها. فيما يلي مخطط الانسيابي يوضح طريقة تدفق التعليمات في حلقة التكرار:
JavaScript أحد لغات البرمجة التي توفر أشكال متعددة من جُمل التكرار أو حلقات التكرار التي يمكن تصنيفها في المجمل إلى الى فئتين رئيسيتين هما:
- جُمل while.
- جٌمل for.
في هذا المقال نستعرض طريقة بناء كل من جُمل while وجُمل for في لغة JavaScript والأشكال المتنوعة لجُمل التكرار المرتبطة بهما… ففهم الفروق بين حلقات while و for، ومعرفة متى يكون استخدام إحداها أنسب من الأخرى، ينعكس مباشرة على وضوح الكود وكفاءته.
جملة While فى JavaScript
جملة while فى JavaScript يمكن أن تُستخدم عندما يكون عدد مرات التكرار غير محدد مسبقاً، ويعتمد استمرار التنفيذ على تحقق شرط منطقي معيّن. هذا النوع من الحلقات يُعد مناسباً للحالات التي يكون فيها التكرار مرتبطاً بتغيّر حالة أو نتيجة عملية ما أثناء التنفيذ. في هذا الجزء سنوضح آلية عمل عبارتي while و do...while، مع بيان الفرق الجوهري بينهما …
حلقة التكرار while في جافا سكريبت
أبسط أنواع حلقات التكرار في جافا سكريبت هي حلقة التكرار while فهي حلقة تكرار تعتمد على مدخلات محددة. تتمثل وظيفة حلقة التكرار while في تنفيذ عبارة أو كتلة برمجية بشكل متكرر طالما أن شرطًا ما صحيح (True) . بمجرد أن يصبح الشرط خاطئًا (False) ، تنتهي الحلقة. حيث تكون الصيغة العامة للحلقة while على الشكل التالي:
while (expression) {
Instructions to be executed if the expression is true
}
لتوضيح اكثر لطريقة بناء حلقة التكرار while فى JavaScript دعونا نأخذ مثال. في المثال سنقوم بطباعة كلمة رقم (Number ) وعدة مرات بحث يظهر بجانبها رقم التكرار لنرى:
let count = 1
while (count <= 5){
console.log("Number " + count)
count++;
}
من المخاطر المحتملة الوقوع في حلقات لا نهائية عند سوء ضبط الشرط مع قيمة العداد. لابد أن نؤكد هنا على حتمية سلامة الشرط مع القيمة المتغيرة قد تؤدي الصياغة غير الصحية الى تنفيذ غير منتهي على سبيل المثال للمثال السابق جرب:
وضع القيمة الابتدائية للقيمة المتغير count = 10.
اعكس الشرط بحيث تكون count اكبر من أو يساوي 5 .
فمع الزيادة للقيمة مستحيل ان يكون القمية أقل من أو تساوي 5 ستؤدي هذه الاجراءات الى تكرار لانهائي… سلامة الشروط مهمة جداً جميع جُمل التكرار.
حلقة التكرار do…while في جافا سكريبت
حلقة do...while تشبه حلقة while باستثناء أن التحقق من الشرط يتم في نهاية الحلقة. هذا يعني أن الحلقة ستُنفذ دائمًا مرة واحدة على الأقل، حتى لو كان الشرط خاطئًا (False). هذا لأن الشرط يكون في نهاية جملة do…while حيث تكون الصيغة العامة للحلقة do…while على الشكل التالي:
do {
Instructions to be executed;
} while (expression);
لتوضيح اكثر لطريقة بناء حلقة التكرار do…while فى JavaScript دعونا نطبق على المثال السابق المثال سنقوم بطباعة كلمة رقم (Number) عدة مرات بحيث يظهر بجانبها رقم التكرار ولكن سنقوم بتعديل على الشرط حيث يعطي نتيجة خاطئة ونرى كيف يمكن التنفيذ لمرة واحدة ( لاحظ يمكن تعديل الشرط ليكون صحيح وستكون النتيجة مطابقة للمثال السابق) لنرى :
let count = 1
do{
console.log("Number " + count);
count++
} while (count > 5);
إذن في JavaScript تستخدم العبارتان while و do...while لإنشاء حلقات تكرارية (Loops)، ولكن يكمن الفرق الأساسي في توقيت التحقق من الشرط. فيما يلي أهم الفروق بينهما :
| وجهة الاختلاف | while Loop (الحلقة الشرطية) | do...while Loop (الحلقة المسبقة التنفيذ) |
|---|---|---|
| توقيت التحقق | قبل تنفيذ الكود الخاص بالتكرار (Pre-test loop). | بعد تنفيذ الكود الخاص بالتكرار لأول مرة (Post-test loop). |
| التنفيذ الأدنى | قد لا تُنفذ أبداً (صفر مرة). | تُنفذ مرة واحدة على الأقل. |
| الاستخدام الشائع | عندما لا تكون متأكداً من أن الشرط سيتحقق على الإطلاق. | عندما يجب تنفيذ الكود لمرة واحدة على الأقل قبل التحقق من الحاجة إلى التكرار. |
في جافا سكريبت توفّر عبارتا while و do...while مرونة عالية في تنفيذ التكرار المعتمد على الشروط. الاختيار بينهما يعتمد على ما إذا كان تنفيذ كتلة التعليمات للحلقة يجب أن تحدث مرة واحدة على الأقل أم لا، وهو ما يؤثر مباشرة على منطق البرنامج وسلامة تدفقه.
جُمل for في JavaScript
في جافا سكريبت تُستخدم عبارة for لإنشاء كتلة من التعليمات البرمجية التي تكرر حتى يتحقق شرط معين. ويمكن استخدامها للتكرار إذا كان عدد مرات التكرار ثابتًا ومعروفًا. وتعتبر أكثر أشكال التكرار اختصارًا توفر JavaScript ثلاث أشكال من for وهي:
- جملة for.
- جملة for…in.
- جملة for…of.
جملة for في JavaScript
جملة for هي الشكل الأساسي لجملة التكرار for في JavaScript وتتضمن الأجزاء الثلاثة المهمة التالية:
- التهيئة (Initialization) : في عبارة تهيئة الحلقة، نُهيئ العداد (متغير) بقيمة ابتدائية. لابد أن تُنفذ عبارة التهيئة قبل الشرط.
- الشرط (Condition): عبارة الشرط التي تختبر صحة شرط معين. إذا كان الشرط صحيحًا، فسيتم تنفيذ التعليمات البرمجية الموجودة داخل الحلقة. وإلا، فسيتم الخروج من الحلقة.
- التكرار (Iteration) : في عبارة التكرار، يمكنك زيادة أو إنقاص العداد.
ويتم وضع الأجزاء الثلاثة في سطر واحد مع الفصل بينها بفواصل منقوطة (;) . حيث تكون الصيغة العامة لحقة for على الشكل التالي:
for (initialization; condition; iteration) {
Instructions to be executed if the expression is true
}
فيما يلي تطبيق استخدام for في JavaScript لإنشاء حلقة تكرار :
for (let count = 1; count <= 5; count++){
console.log("Number " + count);
}
نرى في المثال استخدام الشكل الأساسي للصيغة العامة، حيث تم تعريف متغير العداد ضمن حلقة for ، بجانب هذه الصيغة تتيح JavaScript استخدامات اكثر مرونة للـ for مثل تعريف وتهيئة متغير العداد خارج for واستخدام ميزة طول الـ object كحد أعلى لقيمة العداد ( يكون الـ object على سبيل المثال مصفوفة Array أو نص String) . كما يتضح معنا في المثال التالي:
let i =0;
let str = 'Hello';
for( ; i <= str.length-1; i++){
console.log(i +'-' + str[i]);
}
بعد استيعاب البنية الأساسية لجملة for وآلية عملها، يصبح من الضروري الانتقال إلى صيغ أكثر تخصصاً للتكرار. في هذا السياق، تأتي عبارات for...in وfor...of لتوفير أساليب مختلفة لاستعراض البيانات، حيث يركّز كل منهما على نوع محدد من البنى البرمجية وطريقة مختلفة في الوصول إلى عناصرها.
جملة for...in في JavaScript
أحد أنواع حلقة for في جافا سكريبت و تُستخدم حلقة for...in في جافا سكريبت للتكرار عبر خصائص الـ Object. لا يُمكن استخدام حلقة for للتكرار عبر خصائص الكائن (object)، لذا تمّ استخدام حلقة for...in للتكرار عبر جميع خصائص الكائن.
يُمكن أيضًا استخدام حلقة for...in في جافا سكريبت للتكرار عبر عناصر المصفوفة. مع ذلك، لا يُنصح بذلك لأنها أقل كفاءة من استخدام حلقة for...of. وتكون الصيغة العامة للـ for..in على الشكل التالي:
for (variableName in object) {
Instructions to be executed
}
في كل تكرار، تُسند خاصية واحدة من الكائن إلى variableName، وتستمر هذه الحلقة حتى يتم استعراض جميع خصائص الكائن. حيث يكون :
- variableName - هو اسم خاصية (مفتاح - key) للكائن.
- in - هو معامل التشغيل in في جافا سكريبت.
- object - هو الكائن المراد استعراضه.
يوضح المثال التالي استخدام حلقة for…in في JavaScript:
let str = 'Hello';
for(i in str){
console.log(i +'-' + str[i]);
}
الـ Output للمثال:
0-H 1-e 2-l 3-l 4-o
جملة for...of في JavaScript
تُستخدم حلقة for...of في جافا سكريبت للتنقل بين عناصر الكائن القابل للتكرار. في كل تكرار، تُعيد عنصرًا من عناصر الكائن القابل للتكرار. تشمل الكائنات القابلة للتكرار المصفوفات (arrays)، النصوص (string) والمجموعات (sets) غيرها.وتُعدّ حلقة for...of في جافا سكريبت طريقةً أكثر كفاءةً للتنقل بين عناصر الكائنات القابلة للتكرار مقارنةً بحلقة for...in. تتنقل حلقة for...of بين قيم الخاصية، بينما تُستخدم حلقة for...in للتنقل بين مفاتيح (أسماء الخصائص) الكائن. ولتكون الصيغة العامة للـ for…of كتالي :
for (i of iterable) {
Instructions to be executed
}
- i - هو العنصر الحالي في الكائن القابل للتكرار.
- of - هو معامل تشغيل في جافا سكريبت.
- iterable- هو كائن قابل للتكرار مثل مصفوفة array، أو نص string .
ويكون استخدام حلقة for…of في JavaScript على النحو التالي:
let i =0;
let str = 'Hello';
for(i of str){
console.log(i);
}
الـ Output للمثال:
H e l l o
فيما يلي ملخص لأهم الفروق بين حلقتي التكرار for..in و for…of في JavaScript:
| وجهة المقارنة | for...in | for...of |
|---|---|---|
| ماذا يكرر؟ | يكرر أسماء الخصائص (Keys) الخاصة بالكائن. | يكرر قيم العناصر (Values) الخاصة بالكائن القابل للتكرار (Iterable). |
| أفضل استخدام | للتكرار على خصائص (Properties ) الكائنات (Objects). | للتكرار على عناصر المصفوفات (Arrays)، السلاسل النصية (Strings)، الخرائط (Maps)، المجموعات (Sets)، وغيرها من الـ Iterables. |
| القيم المسترجعة | الفهارس (Indexes) أو نصوص (String) تمثل اسم الخاصية | قيمة العنصر الفعلي في التكرار الحالي. |
تعتبر جملة for في JavaScript من أكثر أدوات التكرار استخداماً لما توفره من تحكم واضح في عدد مرات التنفيذ. كما أن التمييز بين for...in وfor...of يُعد أمراً ضرورياً لاختيار الأسلوب المناسب، إذ تُستخدم الأولى لاستعراض الخصائص أو الفهارس، بينما تُستخدم الثانية للتعامل المباشر مع القيم القابلة للتكرار. هذا الفهم يساهم في كتابة كود أدق وأكثر توافقاً مع طبيعة البيانات المستخدمة.
في التكرار ( Loop Control) في جافا سكريبت
توفر جافا سكريبت تحكمًا كاملًا في التعامل مع الحلقات (loops) وعبارات switch. قد تحتاج أحيانًا إلى الخروج من حلقة دون الوصول إلى نهايتها، أو تخطي جزء من كتلة التعليمات البرمجية وبدء التكرار التالي. لحل هذه المشكلات، توفر جافا سكريبت عبارات break و continue والتي يكون على الشكل التالي:
- break تُستخدم الكلمة المفتاحية break للخروج من الحلقة.
- continue تُستخدم الكلمة المفتاحية continue لتخطي التكرار الحالي للحلقة.
لنرى طريقة الاستخدام عبر الأمثلة:
مثال على استخدام break مع التكرار في JavaScript
تُستخدم عبارة break في JavaScript، والتي تم تقديمها في مقال سابق عن عبارة switch، للخروج من الحلقة مبكرًا، والخروج من الأقواس المعقوفة المحيطة. لنرى المثال التالي :
let count = 1
while (count <= 10){
if ( count == 5){
break;
}
console.log("Number " + count)
count++
}
في المثال نرى ان break أوقفت الـ loop عند count =5
الـ Output للمثال:
Number 1 Number 2 Number 3 Number 4
مثال على استخدام continue مع التكرار في JavaScript
يبدأ التكرار بشكل طبيعي وعند مصادفة عبارة continue، ينتقل مسار البرنامج مباشرةً إلى تعبير التحقق من الحلقة، وإذا ظل الشرط صحيحًا، يتخطى تنفيذ الحالقة الحالية الى الحلقة التالية .لاحظ المثال التالي :
let count = 0
while (count < 10){
count++;
if ( count == 5){
continue;
}
console.log("Number " + count);
}
الـ Output للمثال:
Number 1 Number 2 Number 3 Number 4 Number 6 Number 7 Number 8 Number 9 Number 10
في المثال نرى أن continue أدت تخطي التنفيذ عند count =5 ثم أكملت تنفيذ التكرار.
أن التحكم في التكرار باستخدام break و continue يمنح المطوّر قدرة أدق على إدارة مسار التنفيذ داخل الحلقة، وهو أمر ضروري عند التعامل مع حالات شرطية معقدة. كما أن الفهم الصحيح لهاتين العبارتين يساعد على كتابة كود أوضح وأكثر كفاءة، ويقلل من التعقيد المنطقي داخل الحلقات.
التكرارات المتداخلة Nested loop في JavaScript
التكرار المتداخل هو عبارة عن حلقة تكرارية داخل حلقة تكرارية أخرى. تُسمى الحلقة الخارجية بالحلقة الأم، والحلقة الداخلية بالحلقة الابنة. والقاعدة الأساسية هي أن لكل تكرار كامل واحد للحلقة الخارجية، يتم تنفيذ الحلقة الداخلية بالكامل. حيث تبدأ الحلقة الخارجية في تكرارها الأول. توضيح الخطوات التالية آلية عمل التكرارات المتداخلة Nested loop في JavaScript:
- تبدأ الحلقة الداخلية في العمل.
- تُنفَّذ الحلقة الداخلية بالكامل (من بدايتها إلى نهايتها) عدة مرات.
- تنتقل الحلقة الخارجية إلى تكرارها الثاني.
- تُنفَّذ الحلقة الداخلية مرة أخرى بالكامل.
- تستمر هذه العملية حتى تكتمل الحلقة الخارجية جميع تكراراتها المحددة.
أمثلة لاستخدام التكرارات المتداخلة Nested loop في JavaScript :
تُستخدم التكرارات المتداخلة لحل مشكلات تتطلب معالجة بيانات في بُعدين أو أكثر.
1. طباعة الأنماط (Patterns)
يُستخدم التكرار المتداخل بشكل شائع لطباعة الأنماط الهندسية أو الأشكال (مثل النجوم، أو الأرقام) التي تتكون من صفوف وأعمدة.
- الحلقة الخارجية: تتحكم في الصفوف (Rows).
- الحلقة الداخلية: تتحكم في الأعمدة (Columns) أو العناصر داخل الصف الواحد.
2. معالجة المصفوفات ثنائية الأبعاد (2D Arrays)
المصفوفات ثنائية الأبعاد (مثل جداول البيانات أو خرائط الألعاب) هي مصفوفة من المصفوفات.
- الحلقة الخارجية: تكرر على المصفوفات الخارجية (الصفوف).
- الحلقة الداخلية: تكرر على العناصر داخل كل مصفوفة داخلية (الأعمدة).
3. عمليات المقارنة/البحث المعقدة
تُستخدم التكرارات المتداخلة في خوارزميات مثل:
- الفرز الفقاعي (Bubble Sort): لمقارنة كل عنصر بكل العناصر الأخرى في القائمة.
- البحث عن التكرارات: للبحث عن جميع أزواج العناصر المتطابقة في مصفوفة.
الأداء (Performance)
من المهم جداً أن نكون حذرين عند استخدام التكرارات المتداخلة، خاصةً عندما تكون مجموعات البيانات كبيرة لعدة اسباب :
- التعقيد الزمني (Time Complexity): إذا كانت لديك حلقتان متداخلتان، ولكل حلقة N من التكرارات، فإن إجمالي عدد العمليات يكون تقريباً O(N2).
- التكلفة: كلما زاد عدد التكرارات في الحلقات، زادت التكلفة بشكل كبير. على سبيل المثال، إذا كانت لديك 3 حلقات متداخلة، يكون التعقيد O(N3)، وهو مكلف جداً للمصفوفات الكبيرة.لذلك، يجب محاولة إيجاد حلول بديلة ذات تعقيد زمني أقل (مثل O(N) أو O(N log N)) عند الإمكان.
للمزيد انظر المقالات أداء الخوارزميات و كفاءة الخوارزميات.
مثال تطبيقي :
التكرارات المتداخلة تستخدم لإنشاء الأنماط. سنستخدم التكرارات المتداخلة لطباعة مثلث قائم الزاوية من النجوم، حيث عدد النجوم في كل صف يساوي رقم الصف الحالي (يبدأ من 1). لطباعة مثلث قائم الزاوية سنفترض أننا نريد طباعة مثلث مكون من 5 صفوف سيكون الكود كتالي:
const height = 5;
//1- outer loop control the rows
for (let i = 1; i <= height; i++) {
// A variable to save the current row
let row = "";
// 2- inner loop to control the columns (stars)
// This will be executed by the current i value's
for (let j = 1; j <= i; j++) {
row += "*"; // Add a star to the row
}
// print the row and move to the next one
console.log(row);
}
يمكن التحكم بالتكرارات الداخلية والخارجية بواسطة العبارات break و continue ويتم هذا بشكل أبسط مع استعمال التسمية label حيث يتم إعطاء التكرار اسم يشار الية في الكود . لا توجد كلمة مفتاحية لإنشاء اسم ولكن يمكنك استخدام أي مُعرِّف متبوع بنقطتين رأسيتين (:) لإعطاء تسمية للتكرار. انظر المثال التالي:
const height = 10;
//lable the outer loop
outerloop:
for (let i = 1; i <= height; i++) {
let row = "";
//label the inner loop
innerloop:
for (let j = 1; j <= i; j++) {
if (i >= 7) break outerloop; // Quit the outer loop
row += "*";
}
console.log(row);
}
في المثال رأينا كيف توقفت الحلقة الخارجية عند الرقم 7 ، و بهذا أوضحنا كيف تم استخدام التسمية لاستهداف الحلقة المحددة.
إن التكرارات المتداخلة في JavaScript تُعد أداة فعّالة عند التعامل مع هياكل بيانات متعددة المستويات، مثل المصفوفات ثنائية الأبعاد أو الجداول، حيث يتيح هذا الأسلوب المرور المنهجي على العناصر وفق تسلسل منطقي واضح. في المقابل، يبرز تأثير التكرارات المتداخلة على أداء البرنامج بوصفه عاملاً حاسماً في اتخاذ قرار استخدامها. فكل مستوى إضافي من التداخل يزيد عدد مرات التنفيذ بشكل ملحوظ، وقد يؤدي إلى تراجع الأداء عند معالجة كميات كبيرة من البيانات إذا لم يُستخدم بحذر. لذلك، يُنصح دائماً بتحليل الحاجة الفعلية للتداخل، وتقليل عدد الحلقات قدر الإمكان، أو استبدالها بأساليب أكثر كفاءة عند توفرها.
الأمثلة لهذا المقال متوفرة على الرابط.
في ختام هذا المقال، يتضح أن جمل التكرار في JavaScript ليست مجرد وسيلة لتنفيذ الأوامر بشكل متكرر، بل أداة أساسية للتحكم في تدفق البرنامج وبناء منطق برمجي منظم وقابل للتوسع. فهم الفروق بين حلقات while و for، ومعرفة متى يكون استخدام إحداها أنسب من الأخرى، ينعكس مباشرة على وضوح الكود وكفاءتها. وبناءً على ذلك، يمكن القول إن إتقان حلقات التكرار في JavaScript يُعد خطوة أساسية نحو كتابة كود أكثر احترافية، ويشكّل قاعدة مهمة لفهم هياكل برمجية أكثر تقدماً، مثل معالجة المصفوفات، و الخوارزميات، وهياكل البيانات المختلفة.

