We are still cooking the magic in the way!
الحلقات التكرارية: for و while و do-while
لماذا نحتاج الحلقات التكرارية؟
تخيل انك تحتاج لطباعة الارقام من 1 الى 1000، او معالجة كل عنصر في سلة تسوق، او فحص كل بكسل في صورة. كتابة تعليمات فردية لكل تكرار ستكون غير عملية وصعبة الصيانة. الحلقات التكرارية هي واحدة من اهم البنى الاساسية في البرمجة لانها تسمح لك بتنفيذ كتلة من الكود بشكل متكرر بناء على شرط معين. بدلا من كتابة نفس الكود مئات او الاف المرات، تكتبه مرة واحدة وتترك الحلقة تتعامل مع التكرار. كل تطبيق JavaScript جدي يعتمد بشكل كبير على الحلقات لمهام مثل المرور على البيانات ومعالجة مدخلات المستخدم وعرض قوائم العناصر والتعامل مع العمليات غير المتزامنة.
حلقة for
حلقة for هي الحلقة الاكثر استخداما في JavaScript. وهي مثالية عندما تعرف مسبقا كم مرة تريد تكرار عملية ما. حلقة for تجمع ثلاثة تعبيرات في سطر واحد: التهيئة والشرط والتحديث. هذه الصيغة المضغوطة تسهل رؤية منطق الحلقة بالكامل في نظرة واحدة.
تشريح حلقة for
تتكون حلقة for من ثلاثة اجزاء مفصولة بفواصل منقوطة داخل اقواس، متبوعة بكتلة كود بين اقواس معقوفة:
مثال: الاجزاء الثلاثة لحلقة for
// الصيغة:
// for (تهيئة; شرط; تحديث) {
// الكود المراد تنفيذه في كل تكرار
// }
for (let i = 0; i < 5; i++) {
console.log('رقم التكرار: ' + i);
}
// المخرجات:
// رقم التكرار: 0
// رقم التكرار: 1
// رقم التكرار: 2
// رقم التكرار: 3
// رقم التكرار: 4
اليك ما يحدث بالضبط خطوة بخطوة: اولا، التهيئة (let i = 0) تعمل مرة واحدة قبل بداية الحلقة. تنشئ متغير عداد. ثانيا، الشرط (i < 5) يتم فحصه قبل كل تكرار. اذا كانت النتيجة true، ينفذ جسم الحلقة. اذا كانت false، تنتهي الحلقة فورا. ثالثا، التحديث (i++) يعمل بعد كل تكرار، وعادة يزيد او ينقص العداد. ثم يتم فحص الشرط مرة اخرى وتستمر الدورة.
مثال: العد التنازلي باستخدام حلقة for
for (let i = 10; i >= 1; i--) {
console.log('العد التنازلي: ' + i);
}
console.log('انطلاق!');
// المخرجات:
// العد التنازلي: 10
// العد التنازلي: 9
// ... (يستمر)
// العد التنازلي: 1
// انطلاق!
مثال: التقدم بخطوتين
// طباعة الارقام الزوجية من 0 الى 20
for (let i = 0; i <= 20; i += 2) {
console.log(i);
}
// المخرجات: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20
let بدلا من var لمتغير العداد في الحلقة. مع let، يكون المتغير محدود النطاق بكتلة الحلقة، مما يمنع السلوك غير المتوقع خاصة في الكود غير المتزامن والاغلاقات.المرور على المصفوفات
من اكثر الاستخدامات شيوعا لحلقة for هو المرور على المصفوفات. تستخدم خاصية length للمصفوفة كشرط لضمان زيارة كل عنصر دون تجاوز الحدود.
مثال: المرور على مصفوفة
let fruits = ['تفاح', 'موز', 'كرز', 'تمر', 'توت'];
for (let i = 0; i < fruits.length; i++) {
console.log('الفاكهة ' + (i + 1) + ': ' + fruits[i]);
}
// المخرجات:
// الفاكهة 1: تفاح
// الفاكهة 2: موز
// الفاكهة 3: كرز
// الفاكهة 4: تمر
// الفاكهة 5: توت
مثال: جمع قيم المصفوفة
let prices = [29.99, 9.99, 49.99, 14.99, 39.99];
let total = 0;
for (let i = 0; i < prices.length; i++) {
total += prices[i];
}
console.log('المجموع: $' + total.toFixed(2));
// المخرجات: المجموع: $144.95
for (let i = 0, len = arr.length; i < len; i++). في محركات JavaScript الحديثة يتم هذا التحسين تلقائيا غالبا، لكنه لا يزال عادة جيدة للوضوح ويظهر نيتك.حلقة while
تستخدم حلقة while عندما لا تعرف مسبقا كم عدد التكرارات المطلوبة. تستمر في العمل طالما ان الشرط يبقى true. يتم تقييم الشرط قبل كل تكرار، مما يعني ان جسم الحلقة قد لا ينفذ ابدا اذا كان الشرط false من البداية.
مثال: حلقة while اساسية
let count = 1;
while (count <= 5) {
console.log('العدد هو: ' + count);
count++;
}
// المخرجات:
// العدد هو: 1
// العدد هو: 2
// العدد هو: 3
// العدد هو: 4
// العدد هو: 5
مثال: محاكاة معالجة البيانات مع while
// محاكاة سيناريو حيث نعالج البيانات حتى يتحقق شرط معين
let data = [3, 7, 2, 8, 1, 9, 4, 6];
let index = 0;
let sum = 0;
// الاستمرار في اضافة الارقام حتى يتجاوز المجموع 15
while (sum <= 15 && index < data.length) {
sum += data[index];
console.log('اضيف ' + data[index] + '، المجموع الجاري: ' + sum);
index++;
}
console.log('المجموع النهائي: ' + sum + ' بعد ' + index + ' عمليات اضافة');
مثال: البحث عن عنصر باستخدام while
let names = ['اليس', 'بوب', 'تشارلي', 'ديانا', 'ايف'];
let searchFor = 'تشارلي';
let position = 0;
while (position < names.length && names[position] !== searchFor) {
position++;
}
if (position < names.length) {
console.log('وجدنا ' + searchFor + ' في الموضع ' + position);
} else {
console.log(searchFor + ' لم يتم العثور عليه');
}
// المخرجات: وجدنا تشارلي في الموضع 2
حلقة do-while
حلقة do-while مشابهة لحلقة while، لكن مع فرق جوهري واحد: تنفذ جسم الحلقة مرة واحدة على الاقل دائما لان الشرط يتم فحصه بعد كل تكرار وليس قبله. هذا يجعلها مثالية للحالات التي تحتاج فيها لتنفيذ الكود مرة واحدة على الاقل بغض النظر عن الشرط، مثل عرض قائمة او طلب مدخلات.
مثال: حلقة do-while اساسية
let number = 1;
do {
console.log('الرقم: ' + number);
number++;
} while (number <= 5);
// المخرجات:
// الرقم: 1
// الرقم: 2
// الرقم: 3
// الرقم: 4
// الرقم: 5
مثال: do-while تنفذ مرة واحدة على الاقل
let value = 100;
// حتى لو كان الشرط خاطئا، الجسم ينفذ مرة واحدة
do {
console.log('هذا سيطبع مرة واحدة! القيمة: ' + value);
value++;
} while (value < 5);
// المخرجات: هذا سيطبع مرة واحدة! القيمة: 100
// مقارنة مع while:
value = 100;
while (value < 5) {
console.log('هذا لن يطبع ابدا');
value++;
}
// لا مخرجات من حلقة while
مثال: نظام قائمة باستخدام do-while
let menuOptions = ['عرض الملف الشخصي', 'تعديل الاعدادات', 'فحص الرسائل', 'تسجيل الخروج'];
let choice = 0;
let attempts = 0;
do {
console.log('\n--- القائمة الرئيسية ---');
for (let i = 0; i < menuOptions.length; i++) {
console.log((i + 1) + '. ' + menuOptions[i]);
}
// محاكاة اختيار المستخدم للخيار 4 (تسجيل الخروج) في المحاولة الثالثة
attempts++;
choice = attempts === 3 ? 4 : attempts;
console.log('المستخدم اختار الخيار: ' + choice);
} while (choice !== 4);
console.log('مع السلامة!');
while في حلقة do-while مطلوبة. نسيانها خطا شائع في الصيغة. الصيغة هي: do { ... } while (condition);عبارتا break و continue
عبارة break تنهي الحلقة فورا بالكامل، وتنقل التحكم الى اول عبارة بعد الحلقة. عبارة continue تتخطى بقية التكرار الحالي وتنتقل الى التكرار التالي. هذه العبارات تمنحك تحكما دقيقا في تنفيذ الحلقة.
مثال: استخدام break للخروج مبكرا
let scores = [85, 92, 78, 95, 60, 45, 88, 73];
// البحث عن اول درجة راسبة (اقل من 50)
for (let i = 0; i < scores.length; i++) {
if (scores[i] < 50) {
console.log('اول درجة راسبة: ' + scores[i] + ' في الموضع ' + i);
break; // التوقف عن البحث بعد ايجاد اول درجة راسبة
}
console.log('الدرجة ' + scores[i] + ' ناجحة');
}
// المخرجات:
// الدرجة 85 ناجحة
// الدرجة 92 ناجحة
// الدرجة 78 ناجحة
// الدرجة 95 ناجحة
// الدرجة 60 ناجحة
// اول درجة راسبة: 45 في الموضع 5
مثال: استخدام continue لتخطي التكرارات
let numbers = [1, -2, 3, -4, 5, -6, 7, -8, 9, -10];
let positiveSum = 0;
for (let i = 0; i < numbers.length; i++) {
if (numbers[i] < 0) {
continue; // تخطي الارقام السالبة
}
positiveSum += numbers[i];
console.log('اضيف ' + numbers[i] + '، المجموع: ' + positiveSum);
}
console.log('مجموع الارقام الموجبة: ' + positiveSum);
// المخرجات:
// اضيف 1، المجموع: 1
// اضيف 3، المجموع: 4
// اضيف 5، المجموع: 9
// اضيف 7، المجموع: 16
// اضيف 9، المجموع: 25
// مجموع الارقام الموجبة: 25
continue داخل حلقة while. اذا كان تعبير التحديث (مثل i++) يأتي بعد عبارة continue، سيتم تخطيه مما قد يسبب حلقة لا نهائية. تأكد دائما من تحديث عداد الحلقة قبل عبارة continue في حلقات while.الحلقات المتداخلة
يمكنك وضع حلقة داخل حلقة اخرى للتعامل مع هياكل البيانات متعددة الابعاد او توليد التركيبات. الحلقة الداخلية تكمل جميع تكراراتها لكل تكرار واحد من الحلقة الخارجية. الحلقات المتداخلة شائعة عند العمل مع الشبكات والجداول والمصفوفات او عند مقارنة العناصر في قائمة مع بعضها البعض.
مثال: جدول الضرب باستخدام حلقات متداخلة
// توليد جدول ضرب 5x5
for (let row = 1; row <= 5; row++) {
let line = '';
for (let col = 1; col <= 5; col++) {
let product = row * col;
line += product + '\t';
}
console.log(line);
}
// المخرجات:
// 1 2 3 4 5
// 2 4 6 8 10
// 3 6 9 12 15
// 4 8 12 16 20
// 5 10 15 20 25
مثال: ايجاد الازواج التي مجموعها يساوي هدفا معينا
let values = [2, 7, 11, 15, 3, 6];
let target = 9;
console.log('الازواج التي مجموعها ' + target + ':');
for (let i = 0; i < values.length; i++) {
for (let j = i + 1; j < values.length; j++) {
if (values[i] + values[j] === target) {
console.log(values[i] + ' + ' + values[j] + ' = ' + target);
}
}
}
// المخرجات:
// الازواج التي مجموعها 9:
// 2 + 7 = 9
// 3 + 6 = 9
مثال: معالجة شبكة ثنائية الابعاد
let grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
let gridTotal = 0;
for (let row = 0; row < grid.length; row++) {
for (let col = 0; col < grid[row].length; col++) {
gridTotal += grid[row][col];
console.log('grid[' + row + '][' + col + '] = ' + grid[row][col]);
}
}
console.log('مجموع الشبكة: ' + gridTotal);
// المخرجات: مجموع الشبكة: 45
حلقة for...in
حلقة for...in مصممة خصيصا للمرور على الخصائص القابلة للتعداد (المفاتيح) في كائن. تمنحك الوصول الى اسم كل خاصية، والذي يمكنك استخدامه للوصول الى القيمة المقابلة. رغم انه يمكن استخدامها تقنيا على المصفوفات، فمن الافضل حصرها على الكائنات لانها تمر على جميع الخصائص القابلة للتعداد بما في ذلك الموروثة، مما قد يؤدي لنتائج غير متوقعة مع المصفوفات.
مثال: المرور على خصائص كائن
let student = {
name: 'اليس',
age: 22,
major: 'علوم الحاسوب',
gpa: 3.8,
graduated: false
};
for (let key in student) {
console.log(key + ': ' + student[key]);
}
// المخرجات:
// name: اليس
// age: 22
// major: علوم الحاسوب
// gpa: 3.8
// graduated: false
مثال: استخدام hasOwnProperty للامان
let car = {
make: 'Toyota',
model: 'Camry',
year: 2023,
color: 'Silver'
};
for (let prop in car) {
if (car.hasOwnProperty(prop)) {
console.log(prop + ' = ' + car[prop]);
}
}
// هذا يضمن اننا نصل فقط الى خصائص الكائن الخاصة،
// وليس الموروثة من سلسلة النماذج الاولية
for...in للمرور على المصفوفات. فهي تمر على اسماء الخصائص (وهي فهارس نصية للمصفوفات) وليس القيم. كما تشمل الخصائص الموروثة القابلة للتعداد ولا تضمن الترتيب. استخدم حلقة for القياسية او for...of للمصفوفات بدلا من ذلك.حلقة for...of
حلقة for...of تم تقديمها في ES6 وهي مصممة للمرور على الكائنات القابلة للتكرار مثل المصفوفات والسلاسل النصية و Maps و Sets و NodeLists. على عكس for...in التي تعطيك المفاتيح، for...of تعطيك القيم مباشرة. انها الطريقة الانظف والاكثر قراءة للمرور على عناصر المصفوفة واحرف السلسلة النصية.
مثال: المرور على مصفوفة باستخدام for...of
let colors = ['احمر', 'اخضر', 'ازرق', 'اصفر', 'بنفسجي'];
for (let color of colors) {
console.log('اللون: ' + color);
}
// المخرجات:
// اللون: احمر
// اللون: اخضر
// اللون: ازرق
// اللون: اصفر
// اللون: بنفسجي
المرور على السلاسل النصية
السلاسل النصية قابلة للتكرار في JavaScript، مما يعني انه يمكنك المرور عليها حرفا بحرف باستخدام حلقة for القياسية وحلقة for...of. هذا مفيد لمهام مثل عد الاحرف وعكس السلاسل والتحقق من التناظر والتحقق من المدخلات.
مثال: عد حروف العلة في سلسلة نصية
let text = 'JavaScript is an amazing programming language';
let vowels = 'aeiouAEIOU';
let vowelCount = 0;
for (let char of text) {
if (vowels.includes(char)) {
vowelCount++;
}
}
console.log('عدد حروف العلة: ' + vowelCount);
// المخرجات: عدد حروف العلة: 16
مثال: عكس سلسلة نصية باستخدام حلقة for
let original = 'Hello World';
let reversed = '';
for (let i = original.length - 1; i >= 0; i--) {
reversed += original[i];
}
console.log('الاصلي: ' + original);
console.log('المعكوس: ' + reversed);
// المخرجات:
// الاصلي: Hello World
// المعكوس: dlroW olleH
مخاطر الحلقات اللانهائية
الحلقة اللانهائية تحدث عندما لا يصبح شرط الحلقة ابدا false. هذا يسبب عمل الحلقة للابد مما يجمد تبويب المتصفح او يتسبب في تعطل عملية Node.js. الحلقات اللانهائية هي واحدة من اكثر الاخطاء شيوعا للمبتدئين ويمكن ان تحدث مع اي نوع من الحلقات. فهم كيفية حدوثها امر ضروري لتجنبها.
مثال: اخطاء شائعة تسبب حلقات لا نهائية
// خطر: لا تشغل هذه الامثلة -- ستجمد متصفحك!
// الخطا 1: نسيان تحديث العداد
// let i = 0;
// while (i < 10) {
// console.log(i);
// // i++ مفقود -- i سيبقى دائما 0!
// }
// الخطا 2: شرط لا يمكن ان يصبح خاطئا ابدا
// for (let i = 1; i > 0; i++) {
// console.log(i);
// // i يستمر في النمو، دائما اكبر من 0
// }
// الخطا 3: تحديث المتغير الخطا
// let x = 0;
// let y = 0;
// while (x < 10) {
// y++; // x لا يتغير ابدا -- يجب ان يكون x++
// }
// نمط آمن: دائما حدد شرط خروج واضح
let safeCounter = 0;
let maxIterations = 1000;
while (safeCounter < maxIterations) {
// قم بالعمل هنا
safeCounter++;
}
console.log('اكتملت الحلقة بامان بعد ' + safeCounter + ' تكرار');
اعتبارات اداء الحلقات
ليست كل الحلقات متساوية في الاداء. عند التعامل مع مجموعات بيانات كبيرة، يمكن لاختيار الحلقة وطريقة هيكلتها ان يكون له تاثير ملموس على وقت التنفيذ. اليك بعض نصائح وانماط الاداء العملية التي يجب اتباعها.
مثال: تخزين الطول للاداء
let largeArray = new Array(1000000).fill(0).map((_, i) => i);
// اقل كفاءة: يتم الوصول للطول في كل تكرار
// for (let i = 0; i < largeArray.length; i++) { ... }
// اكثر كفاءة: الطول مخزن مؤقتا
let len = largeArray.length;
for (let i = 0; i < len; i++) {
// معالجة largeArray[i]
}
// كفؤ ايضا: التخزين في عبارة for
for (let i = 0, n = largeArray.length; i < n; i++) {
// معالجة largeArray[i]
}
مثال: تجنب العمليات المكلفة داخل الحلقات
let items = ['apple', 'banana', 'cherry', 'date', 'elderberry'];
// سيئ: انشاء regex جديد في كل تكرار
// for (let i = 0; i < items.length; i++) {
// if (new RegExp('an').test(items[i])) { ... }
// }
// جيد: انشاء regex مرة واحدة خارج الحلقة
let pattern = new RegExp('an');
for (let i = 0; i < items.length; i++) {
if (pattern.test(items[i])) {
console.log(items[i] + ' يحتوي على "an"');
}
}
// المخرجات:
// banana يحتوي على "an"
العبارات المسماة (Labels)
التسميات تسمح لك بتسمية حلقة ثم استخدام break او continue مع تلك التسمية للتحكم في الحلقة المتاثرة. هذا مفيد بشكل خاص مع الحلقات المتداخلة عندما تريد الخروج من حلقة خارجية من داخل حلقة داخلية. بدون التسميات، break و continue تؤثران فقط على الحلقة الاعمق.
مثال: الخروج من حلقات متداخلة باستخدام التسميات
let matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
let searchTarget = 5;
let found = false;
outerLoop: for (let row = 0; row < matrix.length; row++) {
for (let col = 0; col < matrix[row].length; col++) {
if (matrix[row][col] === searchTarget) {
console.log('وجدنا ' + searchTarget + ' في الموضع [' + row + '][' + col + ']');
found = true;
break outerLoop; // الخروج من كلتا الحلقتين
}
}
}
// المخرجات: وجدنا 5 في الموضع [1][1]
مثال: استخدام continue مع التسميات
outerLoop: for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
if (j === 1) {
continue outerLoop; // الانتقال الى التكرار التالي من الحلقة الخارجية
}
console.log('i = ' + i + ', j = ' + j);
}
}
// المخرجات:
// i = 0, j = 0
// i = 1, j = 0
// i = 2, j = 0
// لاحظ: j = 1 و j = 2 لا تطبعان ابدا
return للخروج مبكرا، وهو غالبا انظف من breaks المسماة.مثال عملي: ترقيم الصفحات
ترقيم الصفحات هو نمط شائع في تطبيقات الويب حيث تعرض البيانات في صفحات بدلا من عرضها دفعة واحدة. الحلقات ضرورية لحساب العناصر التي يجب عرضها في الصفحة الحالية وتوليد ارقام الصفحات وتقطيع مصفوفات البيانات.
مثال: تنفيذ منطق ترقيم الصفحات
let allProducts = [];
for (let i = 1; i <= 47; i++) {
allProducts.push('المنتج ' + i);
}
let itemsPerPage = 10;
let currentPage = 3;
let totalPages = Math.ceil(allProducts.length / itemsPerPage);
// حساب فهارس البداية والنهاية للصفحة الحالية
let startIndex = (currentPage - 1) * itemsPerPage;
let endIndex = Math.min(startIndex + itemsPerPage, allProducts.length);
console.log('الصفحة ' + currentPage + ' من ' + totalPages);
console.log('عرض العناصر ' + (startIndex + 1) + ' الى ' + endIndex + ':');
for (let i = startIndex; i < endIndex; i++) {
console.log(' ' + allProducts[i]);
}
// توليد تنقل الصفحات
let pageNav = 'الصفحات: ';
for (let p = 1; p <= totalPages; p++) {
if (p === currentPage) {
pageNav += '[' + p + '] ';
} else {
pageNav += p + ' ';
}
}
console.log(pageNav);
// المخرجات:
// الصفحة 3 من 5
// عرض العناصر 21 الى 30:
// المنتج 21
// المنتج 22
// ... (وهكذا)
// الصفحات: 1 2 [3] 4 5
مثال عملي: معالجة البيانات والتصفية
الحلقات هي العمود الفقري لمعالجة البيانات. في التطبيقات الحقيقية، تحتاج بشكل متكرر لتصفية البيانات وتحويلها وتجميعها. اليك مثال شامل يوضح انماط حلقات متعددة تعمل معا لمعالجة مجموعة بيانات سجلات الموظفين.
مثال: معالجة بيانات الموظفين
let employees = [
{ name: 'اليس', department: 'الهندسة', salary: 85000, active: true },
{ name: 'بوب', department: 'التسويق', salary: 62000, active: true },
{ name: 'تشارلي', department: 'الهندسة', salary: 92000, active: false },
{ name: 'ديانا', department: 'المبيعات', salary: 71000, active: true },
{ name: 'ايف', department: 'الهندسة', salary: 88000, active: true },
{ name: 'فرانك', department: 'التسويق', salary: 58000, active: true },
{ name: 'غريس', department: 'المبيعات', salary: 67000, active: false },
{ name: 'هنري', department: 'الهندسة', salary: 95000, active: true }
];
// المهمة 1: ايجاد جميع المهندسين النشطين
let activeEngineers = [];
for (let i = 0; i < employees.length; i++) {
if (employees[i].department === 'الهندسة' && employees[i].active) {
activeEngineers.push(employees[i].name);
}
}
console.log('المهندسون النشطون: ' + activeEngineers.join('، '));
// المخرجات: المهندسون النشطون: اليس، ايف، هنري
// المهمة 2: حساب متوسط الراتب حسب القسم
let departments = {};
for (let i = 0; i < employees.length; i++) {
let dept = employees[i].department;
if (!departments[dept]) {
departments[dept] = { total: 0, count: 0 };
}
departments[dept].total += employees[i].salary;
departments[dept].count++;
}
for (let dept in departments) {
let avg = (departments[dept].total / departments[dept].count).toFixed(2);
console.log(dept + ' متوسط الراتب: $' + avg);
}
// المهمة 3: ايجاد الموظف النشط الاعلى راتبا
let highestPaid = null;
for (let i = 0; i < employees.length; i++) {
if (employees[i].active) {
if (highestPaid === null || employees[i].salary > highestPaid.salary) {
highestPaid = employees[i];
}
}
}
console.log('الموظف النشط الاعلى راتبا: ' + highestPaid.name + ' ($' + highestPaid.salary + ')');
// المخرجات: الموظف النشط الاعلى راتبا: هنري ($95000)
مثال عملي: بناء بحث بسيط
وظيفة البحث هي جوهر معظم تطبيقات الويب. اليك كيف يمكنك تنفيذ بحث اساسي يفحص مصفوفة من المنتجات باستخدام الحلقات.
مثال: البحث في المنتجات
let products = [
{ id: 1, name: 'سماعات بلوتوث لاسلكية', price: 59.99, category: 'الكترونيات' },
{ id: 2, name: 'شاي اخضر عضوي', price: 12.99, category: 'طعام' },
{ id: 3, name: 'حذاء جري', price: 89.99, category: 'رياضة' },
{ id: 4, name: 'مكبر صوت بلوتوث', price: 39.99, category: 'الكترونيات' },
{ id: 5, name: 'سجادة يوغا', price: 24.99, category: 'رياضة' },
{ id: 6, name: 'كابل شحن USB-C', price: 9.99, category: 'الكترونيات' }
];
let searchTerm = 'بلوتوث';
let results = [];
for (let i = 0; i < products.length; i++) {
let productName = products[i].name.toLowerCase();
if (productName.indexOf(searchTerm.toLowerCase()) !== -1) {
results.push(products[i]);
}
}
console.log('نتائج البحث عن "' + searchTerm + '": ' + results.length + ' نتيجة');
for (let i = 0; i < results.length; i++) {
console.log(' - ' + results[i].name + ' ($' + results[i].price + ')');
}
// المخرجات:
// نتائج البحث عن "بلوتوث": 2 نتيجة
// - سماعات بلوتوث لاسلكية ($59.99)
// - مكبر صوت بلوتوث ($39.99)
اختيار الحلقة المناسبة
كل نوع من الحلقات يخدم غرضا محددا. اختيار الحلقة المناسبة يجعل كودك اوضح واقل عرضة للاخطاء:
- for -- استخدمها عندما تعرف بالضبط كم عدد التكرارات المطلوبة، او عندما تحتاج الفهرس. الافضل للمصفوفات عندما تحتاج الفهرس.
- while -- استخدمها عندما يعتمد عدد التكرارات على شرط يتغير اثناء التنفيذ. الافضل للتكرار المبني على الاحداث او الشروط.
- do-while -- استخدمها عندما يجب تنفيذ جسم الحلقة مرة واحدة على الاقل قبل فحص الشرط. الافضل للقوائم والتحقق من المدخلات ومنطق اعادة المحاولة.
- for...in -- استخدمها حصريا للمرور على خصائص الكائنات (المفاتيح). لا تستخدمها ابدا للمصفوفات.
- for...of -- استخدمها للمرور على قيم العناصر القابلة للتكرار (المصفوفات والسلاسل النصية و Maps و Sets). الصيغة الانظف للمرور على المصفوفات عندما لا تحتاج الفهرس.
تمرين عملي
اكمل هذه التحديات الاربعة لتعزيز فهمك لحلقات JavaScript:
التحدي 1: FizzBuzz. اكتب حلقة تطبع الارقام من 1 الى 100. لمضاعفات 3 اطبع "Fizz" بدلا من الرقم. لمضاعفات 5 اطبع "Buzz". لمضاعفات كل من 3 و 5 اطبع "FizzBuzz".
التحدي 2: طابع الانماط. استخدم حلقات متداخلة لطباعة نمط مثلث بالنجوم: السطر 1 يحتوي على نجمة واحدة والسطر 2 يحتوي على 2 وهكذا حتى السطر 7.
التحدي 3: ازالة التكرار من المصفوفة. بالنظر الى المصفوفة [1, 3, 5, 3, 7, 1, 9, 5, 7, 2]، استخدم حلقة لانشاء مصفوفة جديدة تحتوي فقط على القيم الفريدة. لا تستخدم Set او اي دوال مدمجة غير push و includes.
التحدي 4: احصائيات الكائن. بالنظر الى كائن يمثل درجات الحرارة اليومية مثل { Mon: 72, Tue: 68, Wed: 75, Thu: 80, Fri: 69, Sat: 77, Sun: 74 }، استخدم حلقة for...in لايجاد وطباعة اليوم الاكثر حرارة واليوم الابرد ومتوسط الحرارة للاسبوع.