تظهر أهمية لغات البرمجة في إنجاز مهام مكررة وبسرعة مثل الحسابات المتعددة، أو في الحالات التي ينبغي فيها إنجاز الكثير من اﻷعمال المتشابهة. لهذا سنخصص هذا المقال للحديث عن الحلقات في جافا سكريبت التي تعالج تلك اﻷمور. ننصحك قبل أن تبدأ العمل معنا في هذه السلسلة أن تطلع على:
- أساسيات علوم الحاسب
- أساسيات HTML
- أساسيات عمل CSS
- أساسيات لغة جافا سكريبت
ما هي فائدة الحلقات؟
تتمحور فكرة الحلقة على تكرار الشيء ذاته باستمرار. قد تختلف الشيفرة قليلًا في كل جولة أو قد تبقى الشيفرة كما هي وتتغير قيمة المتغيرات فيها.
مثال عن شيفرة تستخدم الحلقات
لنفرض أنك تريد رسم 100 دائرة عشوائية ضمن العنصر <canvas>
انقر الزر "Update" لتنفيذ الشيفرة مرة تلو اﻷخرى لترى مجموعات مختلفة من الدوائر):
إليك شيفرة جافا سكريبت التي تنفّذ المطلوب:
const btn = document.querySelector("button"); const canvas = document.querySelector("canvas"); const ctx = canvas.getContext("2d"); document.addEventListener("DOMContentLoaded", () => { canvas.width = document.documentElement.clientWidth; canvas.height = document.documentElement.clientHeight; }); function random(number) { return Math.floor(Math.random() * number); } function draw() { ctx.clearRect(0, 0, canvas.width, canvas.height); for (let i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = "rgba(255,0,0,0.5)"; ctx.arc( random(canvas.width), random(canvas.height), random(50), 0, 2 * Math.PI, ); ctx.fill(); } } btn.addEventListener("click", draw);
مع أو بدون حلقة
ليس عليك فهم الشيفرة بأكملها اﻵن، لكن ألق نظرة على الجزء الذي يرسم 100 دائرة في الشيفرة:
for (let i = 0; i < 100; i++) { ctx.beginPath(); ctx.fillStyle = "rgba(255,0,0,0.5)"; ctx.arc( random(canvas.width), random(canvas.height), random(50), 0, 2 * Math.PI, ); ctx.fill(); }
-
تُعيد الدالة
random
المعرّفة سابقًا رقمًا صحيحًا محصورًا بين الصفر و1-x
. أما الفكرة العامة فهي أننا نستخدم حلقة لتكرار الشيفرة السابقة 100 مرة، وكل مرة ترسم الشيفرة دائرة في مكان عشوائي من الصفحة. وتبقى كمية الشيفرة اللازمة لرسم الدائرة نفسها سواءً رسمنا 10 أو 100 أو 1000 دائرة، وما يتغير فقط هو عدد مرات التكرار، ولو لم نستخدم الحلقة كان لا بد من كتابة الشيفرة التالية في كل مرة نريد رسم دائرة:
ctx.beginPath(); ctx.fillStyle = "rgba(255,0,0,0.5)"; ctx.arc( random(canvas.width), random(canvas.height), random(50), 0, 2 * Math.PI, ); ctx.fill();
وسيكون الأمر مملًا وصعب التنقيح والصيانة.
استخدام الحلقات للتنقل ضمن مجموعات
غالبًا ما تستخدم الحلقة للتنقل بين مجموعة من العناصر لتنفيذ أمر ما على كل عنصر. ومن اﻷمثلة على المجموعات نجد المصفوفات، إضافة إلى بُنى أخرى في جافا سكريبت مثل المجموعات Sets و الخرائط Maps.
الحلقة for...of
تعد هذه الحلقة أساسية في النقل ضمن عناصر مجموعة:
const cats = ["Leopard", "Serval", "Jaguar", "Tiger", "Caracal", "Lion"]; for (const cat of cats) { console.log(cat); }
في مثالنا هذا، تنص العبارة البرمجية for (const cat of cats)
على ما يلي:
-
إذا كانت
cats
مجموعة من العناصر استخرج العنصر اﻷول منها. -
إسناد قيمة هذا العنصر إلى المتغير
cat
ومن ثم نفّذ الشيفرة الموجودة ضمن القوسين المعقوصين{}
. - استخراج العنصر التالي وكرر الخطوة 2 حتى تصل إلى نهاية المجموعة.
التابعين filter
و map
تقدّم جافا سكريبت حلقات مخصصة أيضًا للتنقل ضمن المجموعات، وسنشير إلى اثنتين منهما. الحلقة اﻷولى يمثلها التابع ()map
الذي ينفّذ شيئًا محددًا على كل عناصر المجموعة ويعيد مجموعة جديدة تضم العناصر المتغيرة:
function toUpper(string) { return string.toUpperCase(); } const cats = ["Leopard", "Serval", "Jaguar", "Tiger", "Caracal", "Lion"]; const upperCats = cats.map(toUpper); console.log(upperCats); // [ "LEOPARD", "SERVAL", "JAGUAR", "TIGER", "CARACAL", "LION" ]
مررنا في مثالنا السابق دالة إلى التابع ()cats.map
الذي يستدعيها مرة لكل عنصر من عناصر المصفوفة، ثم يمرر هذا العنصر إلى الدالة ويجمّع القيم العائدة عنها بعد كل استدعاء ضمن مصفوفة جديدة تحتوى عناصر المصفوفة القديمة بعد تغيير حالة أحرف هذه العناصر.
[ "LEOPARD", "SERVAL", "JAGUAR", "TIGER", "CARACAL", "LION" ]
أما الحلقة الثانية فيقدمها التابع ()filter
الذي يختبر كل عنصر من عناصر المجموعة ويعيد مصفوفة جديدة تضم العناصر التي تحقق شرطًا معينًا:
function lCat(cat) { return cat.startsWith("L"); } const cats = ["Leopard", "Serval", "Jaguar", "Tiger", "Caracal", "Lion"]; const filtered = cats.filter(lCat); console.log(filtered); // [ "Leopard", "Lion" ]
يبدو الأمر مشابهًا للتابع ()map
، ما عدا أن القيمة التي تعيدها الدالة التي نمررها هي قيمة منطقية. فإذا كانت true
يُضمّن العنصر في المصفوفة الجديدة وإلا لن يُضمَّن. أما وظيفة الدالة في هذا المثال فهي اختبار العناصر التي تبدأ بالحرف "L"، لذا ستكون النتيجة كالتالي:
[ "Leopard", "Lion" ]
ولاحظ كيف يُستخدم التابعان ()map
و ()filter
في بعض اﻷحيان مع دوال وهذا ما سندرسه لاحقًا. وباستخدام الدوال يمكن إعادة كتابة الشيفرة السابقة كالتالي:
const cats = ["Leopard", "Serval", "Jaguar", "Tiger", "Caracal", "Lion"]; const filtered = cats.filter((cat) => cat.startsWith("L")); console.log(filtered); // [ "Leopard", "Lion" ]
حلقة for
المعيارية
في مثالنا السابق الذي يدور حول رسم دوائر، لم يكن عليك التنقل بين عناصر مجموعة بل تكرار نفس الشيفرة 100 مرة. عليك في حالات كهذه استخدام الحلقة for
التي لها الصياغة التالية:
for (initializer; condition; final-expression) { // code to run }
لدينا هنا:
-
الكلمة المحجوزة
for
. -
ضمن القوسين التاليين ثلاثة عناصر تفصل بينها فاصلة:
- مهييء initializer: وهو متغيّر له قيمة عددية محددة سوف تزداد لتعدد المرات التي تثنفَّذ فيها الحلقة. ويُشار إليها أحيانًا بالعداد.
- شرط condition: ويحدد متى ستنتهي الحلقة. وهو عادة عبارة برمجية تستخدم عامل موازنة وتختبر إذا ما تحقق الشرط أم لا.
- عبارة إنهاء final-expression:وتُنفّذ أو تُقيَّّم في كل مرة تنهي الحلقة أحد التكرارات. وتُستخدم عادة لتزيد (أو تنقص) العداد لتقربه من النقطة التي لا يتحقق بعدها الشرط (العنصر الثاني).
- أقواس معقوصة تضم كتلة من الشيفرة التي تُنفَّذ في كل تكرار للحلقة.
مثال عن حلقة for: حساب مربعات أعداد
لنلق نظرة على مثال حقيقي لنتصوّر اﻷمر بوضوح أكثر:
const results = document.querySelector("#results"); function calculate() { for (let i = 1; i < 10; i++) { const newResult = `${i} x ${i} = ${i * i}`; results.textContent += `${newResult}\n`; } results.textContent += "\nFinished!"; } const calculateBtn = document.querySelector("#calculate"); const clearBtn = document.querySelector("#clear"); calculateBtn.addEventListener("click", calculate); clearBtn.addEventListener("click", () => (results.textContent = ""));
تُعطي الشيفرة السابقة الخرج التالي:
تحسب الشيفرة السابقة مربعات الأعداد من 1 إلى 9 وتطبع النتيجة، وتُستخدم الحلقة for
كأساس لإجراء الحسابات. لنحلل بشيء من التفصيل العبارة
for (let i = 1; i < 10; i++)
:
-
المهيء (
let i = 1
) يبدأ العدادi
من القيمة 1. ولاحظ ضرورة استخدام التعليمةlet
لأننا نعيد إسناد قيمة له عند كل تكرار. -
الشرط (
i < 10
) ويعني أن تستمر الحلقة في تكرار نفسها طالما أنi
أصغر من10
. -
عبارة اﻹنهاء (
++i
) وتضيف واحد إلى العداد عند إتمام كل تكرار. نحسب داخل الحلقة مربع القيمة الحالية للمتغيرi
بالشكل :i*i
، وننشئ عبارة نصية تضم العملية التي أجريناها ونتيجتها. كما نضيف السلسلةn\
إلى آخر السلسلة النصية كي تُطبع نتيجة التكرار التالي على سطر جديد. وما سيحدث اﻵن هو: -
خلال التكرار الأول ستكون
i=1
، وستكون النتيجة1x1=1
. -
خلال التكرار الثاني ستكون
i=2
، وستكون النتيجة2x2=4
. - تستمر الحلقة بهذا الشكل.
-
عندما تصبح
i=10
تتوقف الحلقة عند تنفيذ الشيفرة ما داخل القوسين المعقوصين وتنتقل إلى الشفرة التي تلي الحلقة وتطبع الرسالة!finished
على سطر جديد.
التنقل بين عناصر مجموعة باستخدام الحلقة for
بإمكانك استخدام الحلقة for
للتنقل بين عناصر مجموعة بدلًا من for...of
. لنعد إلى مثال for...of
السابق:
const cats = ["Leopard", "Serval", "Jaguar", "Tiger", "Caracal", "Lion"]; for (const cat of cats) { console.log(cat); }
سنكتب الشيفرة كالتالي:
const cats = ["Leopard", "Serval", "Jaguar", "Tiger", "Caracal", "Lion"]; for (let i = 0; i < cats.length; i++) { console.log(cats[i]); }
نبدأ هذه الحلقة عند قيمة i=0
وننهيها عندما تصل قيمة i
إلى طول المصفوفة. ونستخدم i
ضمن الحلقة للوصول إلى كل عنصر من عناصرها. ستعمل الحلقة جيدًا وقد استخدمت قبل ظهور وكانت الطريقة المعيارية للتنقل بين عناصر مصفوفة، لكن قد تزداد الفرصة عند استخدامها إلى ظهور ثغرات في الشيفرة مثل:
-
أن تبدأ
i
من القيمة1
وتنسى أن تعداد المصفوفات يبدأ من0
. -
قد تنهي الحلقة عند
i<=cats.length
وتنسى أن نآخر دليل في المصفوفة هوlength-1
. لأسباب كهذه، يُفضّل استخدامfor...of
إن استطعت ذلك، لكنك ستحتاج في بعض اﻷحيان إلىfor
عند النقل بين عناصر مصفوفة. فإن أردت مثلًا طباعة رسالة تضم قائمة بأسماء القطط باستخدام الشيفرة التالية:
const cats = ["Pete", "Biggles", "Jasmine"]; let myFavoriteCats = "My cats are called "; for (const cat of cats) { myFavoriteCats += `${cat}, `; } console.log(myFavoriteCats); // "My cats are called Pete, Biggles, Jasmine, "
لن تكون النتيجة (من ناحية تكوين الجملة في اﻹنكليزية) مصاغة بالكل الصحيح:
My cats are called Pete, Biggles, Jasmine,
لهذا يجب أن تتعامل الحلقة مع آخر اسم بشكل مختلف حتى تكون النتيجة بالشكل:
My cats are called Pete, Biggles, and Jasmine.
ولفعل ذلك، ينبغي أن نعرف دليل آخر عنصر ونحتاج عندها إلى الحلقة for
لتفحّص قيمة i
:
const cats = ["Pete", "Biggles", "Jasmine"]; let myFavoriteCats = "My cats are called "; for (let i = 0; i < cats.length; i++) { if (i === cats.length - 1) { // We are at the end of the array myFavoriteCats += `and ${cats[i]}.`; } else { myFavoriteCats += `${cats[i]}, `; } } console.log(myFavoriteCats); // "My cats are called Pete, Biggles, and Jasmine."
الخروج من الحلقة باستخدام التعليمة break
إن أردت الخروج من حلقة باكرًا قبل انتهاء جميع التكرارات، استخدم التعليمة break
التي رأيناها في مقال العبارات الشرطية عند التعامل مع البنية switch
، إذ تنهي التعليمة break
البنية switch
في الحالة case
التي تحقق تطابقًا مع الشرط. يتكرر اﻷمر ذاته مع الحلقات، إذ يمكن إنهاء الحلقة مباشرة باستخدام break
وجعل المتصفح يقفز إلى الشيفرة التي تلي الحلقة. فلو أردنا مثلًا تطبيقًا للبحث عبر مصفوفة تضم جهات اتصال وأرقام هواتف ونريد فقط رقمًا محددًا، سنحتاج إلى شيفرة HTML تضم عنصر إدخال نصي <input>
لإدخال الرقم الذي نبحث عنه وزر <button>
لتنفيذ العملية وفقرة نصية <p>
لعرض النتيجة:
<label for="search">Search by contact name: </label> <input id="search" type="text" /> <button>Search</button> <p></p>
ستكون شيفرة جافا سكريبت كالتالي:
const contacts = [ "Chris:2232322", "Sarah:3453456", "Bill:7654322", "Mary:9998769", "Dianne:9384975", ]; const para = document.querySelector("p"); const input = document.querySelector("input"); const btn = document.querySelector("button"); btn.addEventListener("click", () => { const searchName = input.value.toLowerCase(); input.value = ""; input.focus(); para.textContent = ""; for (const contact of contacts) { const splitContact = contact.split(":"); if (splitContact[0].toLowerCase() === searchName) { para.textContent = `${splitContact[0]}'s number is ${splitContact[1]}.`; break; } } if (para.textContent === "") { para.textContent = "Contact not found."; } });
-
نعرّف أولًا بعض المتغيّرات منها مصفوفة جهات الاتصال المؤلفة من عناصر نصيّة تحتوي على اسم ورقم هاتف تفصل بينهما نقطتان فوق بعضهما :
-
نربط بعدها مترصّد أحداث إلى الزر
btn
لتشغيل الشيفرة التي تنفّذ البحث وتعيد النتيجة عند النقر عليه. -
نخزّن القيم المدخلة إلى مربع اﻹدخال في المتغيّر
searchName
قبل أن نفرّغه ونعيد إليه تركيز الدخل من جديد. ولاحظ استخدام التابع()toLowerCase
كي يحول النص المدخل إلى حروف صغيرة وبالتالي لن يكون البحث حساسًا لحالة الحروف. -
نأتي إلى الجزء الذي يضم الحلقة
for...of
: -
نفصل بداية جهة الاتصال عند النقطتين المتعامدتين ونخزّن القيمتين الناتجتين عن عملية الفصل في مصفوفة تُدعى .
-
نستخدم بعد ذلك عبارة شرطية لاختبار إن كانت قيمة
splitContact[0]
(وتمثّل اسم المستخدم المحوّل إلى حروف صغيرة) متطابقة مع القيمة المخزّنة في المتغيرsearchName
فإن وجد التطابق نعرض في الفقرة النصية الرقم الموافق ثم نستخدمbreak
ﻹنهاء الحلقة. -
إن لم نجد جهة اتصال مطابقة للبحث لن تظهر أي قيمة في الفقرة النصية، لهذا نضع ضمنها النص "Contact not found." بمعني أننا لم نجد جهة الاتصال المطلوبة. ملاحظة: بإمكانك الاطلاع على الشيفرة المصدرية الكاملة لهذا المثال على جيت-هب، وتستطيع تجربته مباشرة كذلك.
تخطي أحد التكرارات باستخدام continue
تعمل التعليمة continue
بشكل مشابه للتعليمة break
لكنها تتخطى التكرار الحالي إلى التكرار التالي بدلًا من الخروج من الحلقة نهائيًا. لنلق نظرة على مثال آخر يأخذ عدة مدخلات ويعيد فقط اﻷعداد التي تمثل مرّبعات ﻷعداد صحيحة. إليك أولًا شيفرة HTML:
<label for="number">Enter number: </label> <input id="number" type="number" /> <button>Generate integer squares</button> <p>Output:</p>
وهذه شيفرة جافا سكريبت اللازمة:
const para = document.querySelector("p"); const input = document.querySelector("input"); const btn = document.querySelector("button"); btn.addEventListener("click", () => { para.textContent = "Output: "; const num = input.value; input.value = ""; input.focus(); for (let i = 1; i <= num; i++) { let sqRoot = Math.sqrt(i); if (Math.floor(sqRoot) !== sqRoot) { continue; } para.textContent += `${i} `; } });
وهذا هو خرج البرنامج:
-
يجب أن يكون الدخل في هذه الحالة عددًا (المتغير
num
)، وتبدأ الحلقة من 1 (لأن 0 لا يهمنا في هذا التطبيق). هنالك أيضًا شرط للخروج من الحلقة وهو أن يكون العداد أكبر من العدد المدخلnum
، ويزداد العداد بمقدار 1 في كل تكرار. -
نحسب الجذر التربيعي لكل عدد داخل الحلقة ياستخدام التابع
(i)Math.sqrt
ومن ثم نتحقق أنه عدد صحيح بمقارنته مع نفسه عند تقريبه إلى أصغر عدد صحيح باستخدام التابع()Math.floor
. -
إن لم يتساوى الجذر التربيعي والقيمة المقرّبة له (
==!
) فهذا يعني أن الجذر التربيعي ليس عددًا صحيحًا ولن يكون مهمًا بالنسبة لنا لهذا نستخدمcontinue
في هذه الحالة للانتقال إلى العدد التالي دون أن نسجّل هذا العدد. -
إن كان الجذر التربيعي صحيحًا نتخطى الكتلة
if
كليًا ولن تُنفَّذ التعليمةcontinue
بل نضيف قيمةi
وبعده مسافة فارغة إلى محتوى الفقرة النصية.
ملاحظة: بإمكانك الاطلاع على الشيفرة المصدرية الكاملة لهذا المثال على جيت-هب، وتستطيع تجربته مباشرة كذلك.
الحلقتين while
و do...while
إن الحلقة for
ليست الوحيدة في جافا سكريبت، وعلى الرغم أنك لن تحتاج إلى معرفة كل أنواع الحلقات حاليًا، من الجيد الاطلاع على بعضها كي تميّز وجه الشبه والاختلاف بينها. لنلق نظرة بداية على الحلقة while
التي لها الصياغة التالية:
initializer while (condition) { // code to run final-expression }
تعمل الحلقة بشكل مشابه للحلقة for
، إلا أن المهيّء يُضبط قبل الحلقة وعبارة الإنهاء موجودة ضمن الحلقة بعد الشيفرة التي تُنفَّذ عند تحقق الشرط بدلًا من وجودهما بين القوسين التاليين للتعليمة while
إلى جانب عبارة الشرط. وكما نرى، فإن العناصر الثلاث السابقة الموجودة في حلقة for
موجودة أيضًا في الحلقة while
وبنفس الترتيب لأنك تحتاج إلى المهيئ قبل أن تختبر صحة الشرط ثم تُنفَّذ عبارة اﻹنهاء عند انتهاء تنفيذ شيفرة الحلقة التي تستمر طالما أن الشرط محقق.
نحاول تاليًا إعادة كتابة شيفرة مثالنا السابق عن القطط لكن باستخدام الحلقة while
:
const cats = ["Pete", "Biggles", "Jasmine"]; let myFavoriteCats = "My cats are called "; let i = 0; while (i < cats.length) { if (i === cats.length - 1) { myFavoriteCats += `and ${cats[i]}.`; } else { myFavoriteCats += `${cats[i]}, `; } i++; } console.log(myFavoriteCats); // "My cats are called Pete, Biggles, and Jasmine."
وبالنسبة للحلقة do...while
، فهي مشابهة جدًا للحلقة while
مع بعض التغييرات في الصياغة:
initializer do { // code to run final-expression } while (condition)
نلاحظ في هذه الحالة أن المهيئ يأتي أولًا قبل بداية الحلقة ثم الكلمة المحجوزة do
يتبعها قوسين معقوصين يضمان الشيفرة التي يجب تنفيذها ثم عبارة اﻹنهاء ثم يأتي بعد القوسين المعقوصين مباشرة التعليمة while
يليها الشرط. إن الفرق الرئيسي بين الحلقتين السابقتين هو أن الشيفرة ضمن الحلقة do...while
ستُنفَّذ على اﻷقل مرة واحدة قبل اختبار صحة الشرط. إي تُنفَّذ الشيفرة وبعدها يُختبر الشرط لتحديد الحاجة إلى تنفيذ الشيفرة مجددًا. أما في while
و for
يُختبر الشرط أولًا. لنحاول تاليًا إعادة كتابة شيفرة مثالنا السابق عن القطط باستخدام الحلقة do...while
:
const cats = ["Pete", "Biggles", "Jasmine"]; let myFavoriteCats = "My cats are called "; let i = 0; do { if (i === cats.length - 1) { myFavoriteCats += `and ${cats[i]}.`; } else { myFavoriteCats += `${cats[i]}, `; } i++; } while (i < cats.length); console.log(myFavoriteCats); // "My cats are called Pete, Biggles, and Jasmine."
تحذير: يجب التأكد في حلقات while
و do...while
وجميع الحلقات اﻷخرى من زيادة أو إنقاص المهيئ تبعًا للحالة حتى يصبح الشرط في مرحلة ما غير محقق وتنتهي الحلقة وإلا ستستمر الحلقة إلى ما لا نهاية أو سيوقفها المتصفح أو ستنهار الشيفرة. تُدعى هذه الحالة -حلقة لانهائية infinite loop-.
تطبيق عملي: إبدأ العد التنازلي!
نطلب إليك في هذا التمرين طباعة عد تنازلي من 10 إلى 0، ونريد تحديدًا:
-
حلقة من 10 إلى 0، وقد زوّدناك بالمهيئ
;let i = 10
. -
إنشاء فقرة نصية جديدة في كل تكرار للحلقة وإلحاقها بعنصر الخرج
<div>
الذي نختاره باستخدام اﻷمر :
const output = document.querySelector('.output');
وقد زوّدناك في التعليقات بثلاث أسطر من الشيفرة يجب استخدامها ضمن الحلقة:
-
السطر
;const para = document.createElement('p')
الذي يُنشىء فقرة نصية جديدة. -
السطر
;output.appendChild(para)
الذي يُلحق الفقرة النصية بالعنصر<div>
. -
السطر
=para.textContent
الذي يجعل محتوى الفقرة ما تضعه من الناحية اليمنى للمساواة. -
يتطلب كل تكرار نصًا مختلفًا يوضع ضمن الفقرة النصية وفقًا للعدد الذي وصلنا إليه، لذا تحتاج عبارة شرطية وعدة عبارات
=para.textContent
: -
إن كان العدد هو 10 يجب طباعة "Countdown 10".
-
إن كان العدد هو 0 يجب طباعة "!Blast off".
-
يُطبع أي عدد آخر كما هو.
-
تذكّر أن تضيف عدادًا وانتبه إلى أننا نعد تنازليًا في تمريننا وليس تصاعديًا (لا تستخدم
++i
!).
ملاحظة: إن بدأت كتابة الحلقة على الشكل فقد يتوقف المتصفح عن التنفيذ إن لم تضع الشرط النهائي، انتبه إلى ذلك. يمكنك لتفادي اﻷمر كتابة الشيفرة ضمن تعليقات ومن ثم تزيل إشارات التعليق عندما تنتهي من كتابة الشيفرة كاملةً.
إن ارتكبت خطأً تستطيع أن تنقر على الزر "Reset" لتعود إلى الوضع الأساسي، كما يمكنك النقر على الزر "Show solution" لترى الحل.
تطبيق عملي: ملء قائمة المدعوين
نطلب منك في هذا التمرين أخذ قائمة أسماء من مصفوفة ووضعها ضمن قائمة المدعوين، لكن لا نريد دعوة "Phil" و "Lola" لأسباب خاصة.لهذا نحتاج إلى قائمة للمدعوين وأخرى لغير المدعوين. لهذا نطلب منك تحديدًا:
-
كتابة حلقة تتنقل بين عناصر المصفوفة
people
. - تتحقق في كل مرور من أن اسم الشخص ليس "Phil"أو "Lola" مستخدمًا عبارة شرطية:
-
إن كان كذلك، ألحق الاسم بنهاية المحتوى النصي
textContent
للفقرة النصيةrefused
يليه فاصلة وفراغ. -
إن لم يكن كذلك، ألحق الاسم بنهاية المحتوى النصي
textContent
للفقرة النصيةadmitted
يليه فاصلة وفراغ.
زوّدناك مسبقًا بأسطر الشيرة التالية:
-
السطر
=+refused.textContent
الذي يمثل بداية أمر ضم شيء ما إلى نهايةrefused.textContent
. -
السطر
=+admitted.textContent
الذي يمثل بداية أمر ضم شيء ما إلى نهايةadmitted.textContent
.
وإليك بطلب آخر يمنحك نقاطًا إضافية: بعد إكمالك المهمتين السابقتين بنجاح سنتركك مع قائمتين من الأسماء تفصل بينها فواصل لكنها غير مرتبة. هل تستطيع اقتطاع الفواصل ووضع نقطة آخر القائمة؟ عد إلى مقال توابع جافا سكريبت للتعامل مع النصوص إن احتجت أي مساعدة.
إن ارتكبت خطأً تستطيع أن تنقر على الزر "Reset" لتعود إلى الوضع الأساسي، كما يمكنك النقر على الزر "Show solution" لترى الحل.
ما هو نوع الحلقة التي علي استخدامها؟
إن كنت ستتنقل ضمن عناصر مصفوفة أو أي كائن يدعم ذلك ولن تحتاج إلى دليل العنصر (موقعه) في كل مرة، استخدم for...of
فهي أسهل قراءة وأقل توليدًا للأخطاء. واستخدم for
و while
و do...while
لبقية الحالات ، فجميعها تخدمك لحل نفس المسائل. أما أيها ستختار فهذا أمر شخصي وذلك وفقًا لسهولة تطبيقها أو وضوحها بالنسبة إليك. لكننا ننصحك باستخدام for
كبداية لأن ترتيب وموقع عناصرها أسهل تذكرًا (جميعها ضمن القوسين التاليين للكلمة المحجوزة for
) فلن تنسى أيًا منها.
لنلق نظرة عليها جميعًا:
-
الحلقة
for...of
:
for (const item of array) { // code to run }
-
الحلقة
for
:
for (initializer; condition; final-expression) { // code to run }
-
الحلقة
while
:
initializer while (condition) { // code to run final-expression }
-
الحلقة
do...while
:
initializer do { // code to run final-expression } while (condition)
ملاحظة: هناك حلقات أخرى لها ميزات مختلفة وفوائد في حالات محددة وخاصة لكننا لن نمر عليها في هذا المقال.
خلاصة
قدمنا لك في هذا المقال المفاهيم الأساسية والخيارات المختلفة عند تكرار تنفيذ شيفرة جافا سكريبت عبر الحلقات. وعرضنا أهمية هذا النوع من البنى البرمجية في التعامل مع الحالات التي تتكرر فيها الشيفرة نفسها وأوضحنا طريقة عملها من خلال أمثلة عدة. إن استعصى عليك فهم أية نقطة، عد إليها مجددًا أو اطرح سؤالك عبر نقاش الصفحة.
ترجمة -وبتصرف- لمقال Looping code
أفضل التعليقات
لا توجد أية تعليقات بعد
انضم إلى النقاش
يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.