We are still cooking the magic in the way!
التحكم في التدفق: if و else if و else
ما هو التحكم في التدفق؟
كل برنامج تكتبه ينفذ الكود من الاعلى الى الاسفل، سطرا بسطر. لكن التطبيقات الحقيقية تحتاج الى اتخاذ قرارات -- هل يجب ان نعرض رسالة ترحيب او رسالة خطا؟ هل يجب ان نمنح الوصول او نرفضه؟ هل يجب ان نطبق خصما او نفرض السعر الكامل؟ التحكم في التدفق هو الآلية التي تتيح لبرنامجك ان يقرر اي كود يشغله بناء على الشروط. بدون التحكم في التدفق، كل برنامج سيفعل نفس الشيء بالضبط في كل مرة يعمل فيها، مما سيجعل البرامج عديمة الفائدة تماما للمهام الواقعية.
في JavaScript، الادوات الرئيسية للتحكم في التدفق هي عبارات if و else if و else. هذه هي اللبنات الاساسية لاتخاذ القرارات في الكود. كل مطور JavaScript يستخدمها مئات المرات يوميا، لذلك اتقانها بشكل شامل ضروري قبل الانتقال الى مواضيع اكثر تقدما.
عبارة if: قرارك الاول
عبارة if هي ابسط شكل من المنطق الشرطي. تقيم شرطا داخل الاقواس، واذا كان ذلك الشرط صحيحا (truthy)، تنفذ كتلة الكود داخل الاقواس المعقوفة. اذا كان الشرط خاطئا (falsy)، يتم تخطي كتلة الكود بالكامل.
مثال: صيغة عبارة if الاساسية
if (condition) {
// هذا الكود يعمل فقط اذا كان الشرط صحيحا
}
// مثال مع شرط حقيقي
let temperature = 35;
if (temperature > 30) {
console.log('الجو حار بالخارج! حافظ على ترطيبك.');
}
// المخرجات: "الجو حار بالخارج! حافظ على ترطيبك."
دعنا نحلل تشريح عبارة if قطعة بقطعة. الكلمة المفتاحية if تخبر JavaScript انك على وشك اتخاذ قرار. الاقواس () تحتوي الشرط -- اي تعبير سيقيمه JavaScript الى قيمة صحيحة او خاطئة. الاقواس المعقوفة {} تحتوي كتلة الكود التي تعمل عندما يكون الشرط صحيحا. الكود داخل الكتلة يمكن ان يكون سطرا واحدا او مئات الاسطر.
مثال: عبارة if مع شروط مختلفة
let age = 25;
let hasLicense = true;
let accountBalance = 1500;
// مقارنة الارقام
if (age >= 18) {
console.log('انت شخص بالغ.');
}
// فحص القيم المنطقية
if (hasLicense) {
console.log('يمكنك القيادة.');
}
// المقارنة مع حد ادنى
if (accountBalance > 1000) {
console.log('انت مؤهل لحساب متميز.');
}
{} حتى عندما تحتوي كتلة if على سطر واحد فقط. بينما يسمح لك JavaScript بحذف الاقواس للكتل ذات السطر الواحد، هذا مصدر شائع للاخطاء. عندما تضيف لاحقا سطرا ثانيا، لن يكون جزءا من كتلة if، مما يؤدي الى سلوك غير متوقع. استخدام الاقواس باستمرار يجعل الكود اكثر امانا وقابلية للقراءة.شرط else: التعامل مع الحالة الاخرى
عبارة if وحدها تتعامل فقط مع سيناريو واحد -- عندما يكون الشرط صحيحا. لكن ماذا عندما يكون الشرط خاطئا؟ شرط else يوفر كتلة كود احتياطية تعمل عندما يقيم شرط if الى خاطئ. معا، if...else يتيح لك التعامل مع كلتا النتيجتين المحتملتين لشرط.
مثال: عبارة if...else
let userAge = 16;
if (userAge >= 18) {
console.log('مرحبا! لديك وصول كامل.');
} else {
console.log('عذرا، يجب ان يكون عمرك 18 عاما او اكثر للوصول لهذا المحتوى.');
}
// المخرجات: "عذرا، يجب ان يكون عمرك 18 عاما او اكثر للوصول لهذا المحتوى."
// مثال آخر: التحقق اذا كان رقم زوجيا او فرديا
let number = 7;
if (number % 2 === 0) {
console.log(number + ' هو عدد زوجي.');
} else {
console.log(number + ' هو عدد فردي.');
}
// المخرجات: "7 هو عدد فردي."
شرط else ليس لديه شرطه الخاص -- انه يلتقط كل شيء لم يلتقطه شرط if. فكر فيه كشبكة امان. اذا كان شرط if صحيحا، يتم تجاهل كتلة else بالكامل. اذا كان شرط if خاطئا، يتم تجاهل كتلة if بالكامل وتعمل كتلة else بدلا منها. واحدة فقط من الكتلتين ستنفذ -- ابدا ليس كلتاهما.
شرط else if: شروط متعددة
التطبيقات الحقيقية نادرا ما يكون لديها نتيجتان محتملتان فقط. ماذا لو احتجت للتحقق من ثلاثة او اربعة او حتى عشرة شروط مختلفة؟ شرط else if يتيح لك ربط شروط متعددة معا. JavaScript يقيم كل شرط بالترتيب من الاعلى الى الاسفل وينفذ اول كتلة يكون شرطها صحيحا. بمجرد العثور على تطابق، يتم تخطي جميع الشروط المتبقية.
مثال: سلسلة else if
let score = 78;
if (score >= 90) {
console.log('الدرجة: A -- ممتاز!');
} else if (score >= 80) {
console.log('الدرجة: B -- عمل جيد!');
} else if (score >= 70) {
console.log('الدرجة: C -- مرض.');
} else if (score >= 60) {
console.log('الدرجة: D -- يحتاج تحسين.');
} else {
console.log('الدرجة: F -- راسب. يرجى اعادة المادة.');
}
// المخرجات: "الدرجة: C -- مرض."
لاحظ ان الترتيب مهم بشكل كبير. اذا تحققنا من score >= 60 اولا، طالب بدرجة 95 سيحصل على "D" لان 95 ايضا اكبر من او يساوي 60. رتب دائما شروطك من الاكثر تحديدا (او الاكثر تقييدا) الى الاقل تحديدا. else النهائي يعمل كشبكة امان لاي قيمة لا تتطابق مع الشروط السابقة.
مثال: نظام تنبيهات الطقس
let windSpeed = 45; // بالكيلومتر/الساعة
if (windSpeed >= 120) {
console.log('تحذير اعصار: ابحث عن ملجا فورا!');
} else if (windSpeed >= 90) {
console.log('تحذير عاصفة: تجنب الانشطة الخارجية.');
} else if (windSpeed >= 60) {
console.log('تنبيه رياح شديدة: قم بتامين الاشياء السائبة.');
} else if (windSpeed >= 30) {
console.log('نسيم: الظروف عاصفة لكنها آمنة.');
} else {
console.log('هدوء: استمتع بالطقس اللطيف.');
}
// المخرجات: "نسيم: الظروف عاصفة لكنها آمنة."
else if، لكن اذا وجدت نفسك تكتب اكثر من خمسة او ستة، فكر ما اذا كانت عبارة switch (التي سنغطيها في الدرس التالي) او كائن بحث سيكون حلا انظف. سلاسل else if الطويلة يمكن ان تصبح صعبة القراءة والصيانة.الشروط المتداخلة: قرارات داخل قرارات
احيانا مستوى واحد من if...else لا يكفي. قد تحتاج للتحقق من شرط، ثم داخل تلك الكتلة، التحقق من شرط آخر. هذا يسمى التداخل. بينما التداخل ضروري احيانا، التداخل العميق (ثلاثة مستويات او اكثر) يجعل الكود صعب القراءة جدا وغالبا ما يكون علامة على ان المنطق يجب اعادة هيكلته.
مثال: عبارات if متداخلة
let isLoggedIn = true;
let userRole = 'admin';
let hasPermission = true;
if (isLoggedIn) {
if (userRole === 'admin') {
if (hasPermission) {
console.log('تم منح الوصول: لوحة الادارة الكاملة.');
} else {
console.log('تم رفض الوصول: تم سحب صلاحية المسؤول.');
}
} else if (userRole === 'editor') {
console.log('تم منح الوصول: لوحة تحكم المحرر.');
} else {
console.log('تم منح الوصول: لوحة تحكم المستخدم.');
}
} else {
console.log('يرجى تسجيل الدخول للمتابعة.');
}
// المخرجات: "تم منح الوصول: لوحة الادارة الكاملة."
كما ترى، التداخل بثلاثة مستويات يجعل الكود بالفعل اصعب في المتابعة. كل مستوى من المسافة البادئة يمثل سياق قرار جديد، والقارئ يجب ان يتتبع جميع الشروط الخارجية لفهم متى يعمل الكود الداخلي. لاحقا في هذا الدرس، سنتعلم عن شروط الحماية (Guard Clauses) -- تقنية لتسطيح الشروط المتداخلة وجعل الكود اكثر قابلية للقراءة.
القيم الصحيحة والخاطئة في الشروط
شروط JavaScript لا تتطلب قيما منطقية. اي قيمة يمكن استخدامها كشرط لان JavaScript يحول تلقائيا (او "يفرض") القيم الى قيم منطقية عند تقييم الشروط. فهم اي القيم صحيحة (truthy) واي منها خاطئة (falsy) امر حاسم لكتابة منطق شرطي صحيح.
هناك بالضبط ثماني قيم خاطئة في JavaScript. كل قيمة اخرى هي صحيحة.
مثال: القيم الخاطئة الثمانية
// كل هذه خاطئة -- كتلة if لن تنفذ
if (false) { console.log('هذا لن يعمل'); }
if (0) { console.log('هذا لن يعمل'); }
if (-0) { console.log('هذا لن يعمل'); }
if (0n) { console.log('هذا لن يعمل'); } // BigInt صفر
if ('') { console.log('هذا لن يعمل'); } // سلسلة فارغة
if (null) { console.log('هذا لن يعمل'); }
if (undefined) { console.log('هذا لن يعمل'); }
if (NaN) { console.log('هذا لن يعمل'); }
// كل هذه صحيحة -- كتلة if ستنفذ
if (true) { console.log('صحيح!'); }
if (1) { console.log('صحيح!'); }
if (-1) { console.log('صحيح!'); }
if ('hello') { console.log('صحيح!'); }
if ('0') { console.log('صحيح! السلسلة "0" ليست فارغة'); }
if ('false') { console.log('صحيح! السلسلة "false" ليست فارغة'); }
if ([]) { console.log('صحيح! المصفوفة الفارغة صحيحة'); }
if ({}) { console.log('صحيح! الكائن الفارغ صحيح'); }
if (function(){}) { console.log('صحيح! الدوال صحيحة'); }
[] والكائنات الفارغة {} هي صحيحة! هذا يفاجئ كثير من المبتدئين. اذا اردت التحقق اذا كانت المصفوفة فارغة، استخدم if (myArray.length === 0). اذا اردت التحقق اذا كان الكائن ليس لديه خصائص، استخدم if (Object.keys(myObject).length === 0).مثال: استخدام الصحيح/الخاطئ في كود حقيقي
// التحقق اذا قدم المستخدم اسمه
let userName = '';
if (userName) {
console.log('مرحبا، ' + userName + '!');
} else {
console.log('مرحبا، ضيف!');
}
// المخرجات: "مرحبا، ضيف!" (لان السلسلة الفارغة خاطئة)
// التحقق اذا تم تحميل البيانات
let userData = null;
if (userData) {
console.log('بيانات المستخدم: ' + userData.name);
} else {
console.log('لا توجد بيانات مستخدم متاحة.');
}
// المخرجات: "لا توجد بيانات مستخدم متاحة." (لان null خاطئ)
// التحقق اذا كانت القائمة تحتوي عناصر
let notifications = ['رسالة جديدة', 'تحديث متاح'];
if (notifications.length) {
console.log('لديك ' + notifications.length + ' اشعارات.');
} else {
console.log('لا توجد اشعارات جديدة.');
}
// المخرجات: "لديك 2 اشعارات."
الشروط المتعددة مع العوامل المنطقية: && و ||
غالبا ما تحتاج للتحقق من اكثر من شرط في نفس الوقت. JavaScript يوفر عاملين منطقيين رئيسيين لدمج الشروط: عامل AND && وعامل OR ||. هذه العوامل تتيح لك بناء شروط معقدة بدون تداخل عبارات if متعددة.
عامل AND (&&)
عامل && يرجع صحيح فقط عندما يكون كلا الشرطين على جانبيه صحيحا. اذا كان الشرط الاول خاطئا، JavaScript لا يقيم حتى الشرط الثاني (هذا يسمى تقييم الدائرة القصيرة). هذا مفيد للاداء ولمنع الاخطاء عندما يعتمد الشرط الثاني على ان الاول يكون صحيحا.
مثال: عامل AND (&&)
let age = 25;
let hasID = true;
// كلا الشرطين يجب ان يكونا صحيحين
if (age >= 18 && hasID) {
console.log('يمكنك الدخول الى المكان.');
} else {
console.log('تم رفض الدخول.');
}
// المخرجات: "يمكنك الدخول الى المكان."
// تقييم الدائرة القصيرة في العمل
let user = null;
// بدون الدائرة القصيرة، هذا سيسبب خطا:
// if (user.name === 'Admin') -- خطا: لا يمكن قراءة خاصية null
// مع &&، الجزء الثاني لا يتم تقييمه ابدا:
if (user && user.name === 'Admin') {
console.log('مرحبا يا مسؤول!');
} else {
console.log('لم يتم العثور على المستخدم.');
}
// المخرجات: "لم يتم العثور على المستخدم." (user خاطئ، لذلك user.name لا يتم الوصول اليه)
عامل OR (||)
عامل || يرجع صحيح عندما يكون واحد على الاقل من الشروط صحيحا. اذا كان الشرط الاول صحيحا، JavaScript لا يقيم الشرط الثاني (الدائرة القصيرة). هذا مفيد لتوفير قيم افتراضية او التحقق من قيم مقبولة متعددة.
مثال: عامل OR (||)
let day = 'Saturday';
if (day === 'Saturday' || day === 'Sunday') {
console.log('انها عطلة نهاية الاسبوع! وقت الاسترخاء.');
} else {
console.log('انه يوم عمل. وقت العمل.');
}
// المخرجات: "انها عطلة نهاية الاسبوع! وقت الاسترخاء."
// دمج && و || مع الاقواس للوضوح
let userRole = 'editor';
let isActive = true;
let isSuperAdmin = false;
if ((userRole === 'admin' || userRole === 'editor') && isActive) {
console.log('يمكنك تعديل المحتوى.');
} else if (isSuperAdmin) {
console.log('تم منح وصول المسؤول الاعلى.');
} else {
console.log('وصول للقراءة فقط.');
}
// المخرجات: "يمكنك تعديل المحتوى."
&& و || في نفس الشرط، استخدم دائما الاقواس لجعل التجميع واضحا. بينما JavaScript لديه قواعد اسبقية العوامل (&& يتم تقييمه قبل ||)، الاعتماد على الاسبقية بدون اقواس يجعل الكود مربكا. الاقواس الصريحة تزيل الغموض وتجعل نيتك واضحة لاي شخص يقرا الكود.عامل NOT (!)
عامل ! يعكس القيمة المنطقية -- يحول القيم الصحيحة الى false والقيم الخاطئة الى true. يستخدم عادة للتحقق اذا كان شيء ما ليس صحيحا او لعكس شرط.
مثال: عامل NOT (!)
let isLoggedIn = false;
if (!isLoggedIn) {
console.log('يرجى تسجيل الدخول للمتابعة.');
}
// المخرجات: "يرجى تسجيل الدخول للمتابعة."
// NOT المزدوج (!!) يحول اي قيمة الى مكافئها المنطقي
let name = 'Alice';
console.log(!!name); // true (لان "Alice" صحيحة)
let emptyName = '';
console.log(!!emptyName); // false (لان "" خاطئة)
شروط الحماية والخروج المبكر
شروط الحماية (Guard Clauses) هي واحدة من اقوى التقنيات لكتابة منطق شرطي نظيف. بدلا من تداخل الشروط بشكل اعمق واعمق، تتحقق من الشروط غير الصالحة او حالات الحافة اولا وتخرج (تعود) مبكرا. هذا يبقي المنطق الرئيسي لدالتك في المستوى الاعلى، مما يجعله اسهل بكثير في القراءة والفهم.
مثال: بدون شروط الحماية (تداخل عميق)
function processOrder(order) {
if (order) {
if (order.items.length > 0) {
if (order.paymentMethod) {
if (order.shippingAddress) {
// المنطق الرئيسي مدفون عميقا داخل التداخل
let total = 0;
for (let i = 0; i < order.items.length; i++) {
total += order.items[i].price;
}
console.log('تمت معالجة الطلب! المجموع: $' + total);
return total;
} else {
console.log('خطا: لا يوجد عنوان شحن.');
return null;
}
} else {
console.log('خطا: لا توجد طريقة دفع.');
return null;
}
} else {
console.log('خطا: السلة فارغة.');
return null;
}
} else {
console.log('خطا: لم يتم تقديم طلب.');
return null;
}
}
مثال: مع شروط الحماية (مسطح ونظيف)
function processOrder(order) {
// شرط حماية 1: التحقق من وجود الطلب
if (!order) {
console.log('خطا: لم يتم تقديم طلب.');
return null;
}
// شرط حماية 2: التحقق من ان السلة تحتوي عناصر
if (order.items.length === 0) {
console.log('خطا: السلة فارغة.');
return null;
}
// شرط حماية 3: التحقق من طريقة الدفع
if (!order.paymentMethod) {
console.log('خطا: لا توجد طريقة دفع.');
return null;
}
// شرط حماية 4: التحقق من عنوان الشحن
if (!order.shippingAddress) {
console.log('خطا: لا يوجد عنوان شحن.');
return null;
}
// المنطق الرئيسي الآن في المستوى الاعلى -- سهل القراءة!
let total = 0;
for (let i = 0; i < order.items.length; i++) {
total += order.items[i].price;
}
console.log('تمت معالجة الطلب! المجموع: $' + total);
return total;
}
كلا الإصدارين يفعلان نفس الشيء بالضبط، لكن إصدار شروط الحماية اسهل بشكل كبير في القراءة. كل شرط حماية يتعامل مع حالة خطا محددة واحدة ويخرج مبكرا. بحلول الوقت الذي تصل فيه الى المنطق الرئيسي، تعرف ان جميع المتطلبات المسبقة قد تحققت. هذا النمط يستخدم على نطاق واسع في قواعد الكود المهنية لانه يقلل الحمل المعرفي -- القارئ لا يحتاج لتتبع سياقات متداخلة.
return للخروج مبكرا. في الحلقات، يمكنك استخدام continue للانتقال الى التكرار التالي او break للخروج من الحلقة. المبدا الاساسي هو نفسه -- تعامل مع حالة الحافة واخرج، حتى يبقى المنطق الرئيسي في المستوى الاعلى.العامل الثلاثي: الشروط المضمنة
العامل الثلاثي (Ternary) هو اختصار لعبارات if...else البسيطة. هو العامل الوحيد في JavaScript الذي ياخذ ثلاثة معاملات، لهذا يسمى "ثلاثي". الصيغة هي: الشرط ? القيمة_اذا_صحيح : القيمة_اذا_خاطئ. يفضل استخدامه للتعيينات البسيطة او قيم الارجاع، وليس للمنطق المعقد ذو الآثار الجانبية.
مثال: العامل الثلاثي
// بدلا من هذا:
let age = 20;
let status;
if (age >= 18) {
status = 'بالغ';
} else {
status = 'قاصر';
}
// يمكنك كتابة هذا:
let status2 = age >= 18 ? 'بالغ' : 'قاصر';
console.log(status2); // "بالغ"
// العامل الثلاثي في ربط السلاسل
let score = 85;
console.log('النتيجة: ' + (score >= 70 ? 'ناجح' : 'راسب'));
// المخرجات: "النتيجة: ناجح"
// العامل الثلاثي في وسائط الدوال
let items = ['تفاحة', 'موزة'];
console.log('لديك ' + items.length + (items.length === 1 ? ' عنصر' : ' عناصر'));
// المخرجات: "لديك 2 عناصر"
a ? b ? c : d : e ? f : g صعبة للغاية في القراءة والفهم. اذا احتجت شروطا متعددة، استخدم سلسلة if...else if...else مناسبة بدلا من ذلك. قابلية قراءة الكود دائما اهم من الاختصار.انماط التعيين الشرطي
JavaScript يقدم عدة انماط لتعيين القيم بناء على الشروط. هذه شائعة للغاية في الكود الحقيقي وتستحق الحفظ.
مثال: القيم الافتراضية مع OR (||)
// عامل || يرجع اول قيمة صحيحة
let userInput = '';
let displayName = userInput || 'مجهول';
console.log(displayName); // "مجهول" (لان "" خاطئة)
let configPort = 0;
let port = configPort || 3000;
console.log(port); // 3000 (لان 0 خاطئ -- هذا فخ!)
// عامل الدمج اللاغي (??) اكثر امانا للقيم الافتراضية
// يعامل فقط null و undefined كـ "مفقودة"
let configPort2 = 0;
let port2 = configPort2 ?? 3000;
console.log(port2); // 0 (لان 0 ليس null او undefined)
مثال: التعيين الشرطي مع AND (&&)
// عامل && يرجع اول قيمة خاطئة، او القيمة الاخيرة اذا كانت جميعها صحيحة
let user = { name: 'Alice', settings: { theme: 'dark' } };
// الوصول الآمن للخصائص باستخدام &&
let theme = user && user.settings && user.settings.theme;
console.log(theme); // "dark"
// البديل الحديث: التسلسل الاختياري (?.)
let theme2 = user?.settings?.theme;
console.log(theme2); // "dark"
// دمج التسلسل الاختياري مع الدمج اللاغي
let fontSize = user?.settings?.fontSize ?? 16;
console.log(fontSize); // 16 (لان fontSize غير معرف)
مثال واقعي: التحقق من صحة النماذج
التحقق من صحة النماذج هو واحد من اكثر الاستخدامات شيوعا للمنطق الشرطي في تطوير الويب. قبل ارسال البيانات الى الخادم، تحتاج للتحقق من ان المستخدم قدم مدخلات صالحة. اليك مثال شامل يتحقق من صحة نموذج تسجيل.
مثال: التحقق من صحة نموذج التسجيل
function validateRegistrationForm(formData) {
let errors = [];
// التحقق من اسم المستخدم
if (!formData.username) {
errors.push('اسم المستخدم مطلوب.');
} else if (formData.username.length < 3) {
errors.push('اسم المستخدم يجب ان يكون 3 احرف على الاقل.');
} else if (formData.username.length > 20) {
errors.push('اسم المستخدم يجب ان يكون 20 حرفا او اقل.');
} else if (!/^[a-zA-Z0-9_]+$/.test(formData.username)) {
errors.push('اسم المستخدم يمكن ان يحتوي فقط على احرف وارقام وشرطات سفلية.');
}
// التحقق من البريد الالكتروني
if (!formData.email) {
errors.push('البريد الالكتروني مطلوب.');
} else if (!formData.email.includes('@')) {
errors.push('يرجى ادخال عنوان بريد الكتروني صالح.');
}
// التحقق من كلمة المرور
if (!formData.password) {
errors.push('كلمة المرور مطلوبة.');
} else if (formData.password.length < 8) {
errors.push('كلمة المرور يجب ان تكون 8 احرف على الاقل.');
} else {
if (!/[A-Z]/.test(formData.password)) {
errors.push('كلمة المرور يجب ان تحتوي على حرف كبير واحد على الاقل.');
}
if (!/[0-9]/.test(formData.password)) {
errors.push('كلمة المرور يجب ان تحتوي على رقم واحد على الاقل.');
}
}
// التحقق من تاكيد كلمة المرور
if (formData.password && formData.password !== formData.confirmPassword) {
errors.push('كلمتا المرور غير متطابقتين.');
}
// التحقق من العمر
if (formData.age && formData.age < 13) {
errors.push('يجب ان يكون عمرك 13 عاما على الاقل للتسجيل.');
} else if (formData.age && formData.age < 18 && !formData.parentalConsent) {
errors.push('المستخدمون تحت 18 يحتاجون موافقة الوالدين.');
}
// ارجاع النتيجة
if (errors.length === 0) {
console.log('النموذج صالح! جاري الارسال...');
return { valid: true, errors: [] };
} else {
console.log('النموذج يحتوي ' + errors.length + ' خطا/اخطاء:');
for (let i = 0; i < errors.length; i++) {
console.log(' - ' + errors[i]);
}
return { valid: false, errors: errors };
}
}
// الاختبار ببيانات غير صالحة
validateRegistrationForm({
username: 'ab',
email: 'غير صالح',
password: 'قصيرة',
confirmPassword: 'مختلفة',
age: 10
});
مثال واقعي: فحوصات الصلاحيات
التحكم في الوصول هو حالة استخدام اخرى شائعة جدا للمنطق الشرطي. التطبيقات تحتاج للتحقق من ان المستخدمين لديهم الصلاحيات الصحيحة قبل السماح لهم بتنفيذ اجراءات. اليك دالة فحص صلاحيات توضح طبقات متعددة من المنطق الشرطي.
مثال: نظام صلاحيات قائم على الادوار
function checkPermission(user, action, resource) {
// شرط حماية: يجب ان يوجد المستخدم ويكون نشطا
if (!user) {
return { allowed: false, reason: 'لم يتم تقديم مستخدم.' };
}
if (!user.isActive) {
return { allowed: false, reason: 'الحساب معطل.' };
}
// المسؤولون الاعلى يمكنهم فعل اي شيء
if (user.role === 'superadmin') {
return { allowed: true, reason: 'وصول المسؤول الاعلى.' };
}
// التحقق من الصلاحيات المحددة بناء على الدور والاجراء
if (action === 'read') {
if (resource.isPublic) {
return { allowed: true, reason: 'مورد عام.' };
}
if (user.role === 'admin' || user.role === 'editor') {
return { allowed: true, reason: 'وصول قراءة قائم على الدور.' };
}
if (resource.ownerId === user.id) {
return { allowed: true, reason: 'وصول المالك.' };
}
return { allowed: false, reason: 'ليس لديك صلاحية لقراءة هذا المورد.' };
}
if (action === 'edit') {
if (user.role === 'admin' || user.role === 'editor') {
return { allowed: true, reason: 'وصول تعديل قائم على الدور.' };
}
if (resource.ownerId === user.id) {
return { allowed: true, reason: 'المالك يمكنه تعديل مورده.' };
}
return { allowed: false, reason: 'ليس لديك صلاحية لتعديل هذا المورد.' };
}
if (action === 'delete') {
if (user.role === 'admin') {
return { allowed: true, reason: 'وصول حذف المسؤول.' };
}
if (resource.ownerId === user.id && !resource.isProtected) {
return { allowed: true, reason: 'المالك يمكنه حذف الموارد غير المحمية.' };
}
return { allowed: false, reason: 'ليس لديك صلاحية لحذف هذا المورد.' };
}
return { allowed: false, reason: 'اجراء غير معروف: ' + action };
}
// مثال على الاستخدام
let currentUser = { id: 42, role: 'editor', isActive: true };
let article = { id: 101, ownerId: 42, isPublic: true, isProtected: false };
console.log(checkPermission(currentUser, 'edit', article));
// { allowed: true, reason: "وصول تعديل قائم على الدور." }
مثال واقعي: التحقق من العمر
التحقق من العمر مطلوب في كثير من التطبيقات -- من تقييد المحتوى الى الامتثال القانوني. اليك دالة تحقق من العمر قوية تتعامل مع حالات الحافة المختلفة.
مثال: نظام التحقق من العمر
function verifyAge(birthDateString, requiredAge, currentDate) {
// شرط حماية: التحقق من صحة المدخل
if (!birthDateString) {
return { verified: false, message: 'تاريخ الميلاد مطلوب.' };
}
let birthDate = new Date(birthDateString);
// شرط حماية: التحقق من صلاحية التاريخ
if (isNaN(birthDate.getTime())) {
return { verified: false, message: 'صيغة تاريخ غير صالحة.' };
}
// استخدام التاريخ الحالي اذا لم يتم تقديمه
let today = currentDate || new Date();
// شرط حماية: تاريخ الميلاد لا يمكن ان يكون في المستقبل
if (birthDate > today) {
return { verified: false, message: 'تاريخ الميلاد لا يمكن ان يكون في المستقبل.' };
}
// حساب العمر
let age = today.getFullYear() - birthDate.getFullYear();
let monthDiff = today.getMonth() - birthDate.getMonth();
// تعديل العمر اذا لم يحدث عيد الميلاد بعد هذا العام
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
age--;
}
// المقارنة مع العمر المطلوب
if (age >= requiredAge) {
return {
verified: true,
age: age,
message: 'تم التحقق من العمر. المستخدم عمره ' + age + ' عاما.'
};
} else {
let yearsUntilEligible = requiredAge - age;
return {
verified: false,
age: age,
message: 'المستخدم عمره ' + age + ' عاما. يجب ان يكون ' + requiredAge +
'. مؤهل خلال ' + yearsUntilEligible + ' سنة/سنوات.'
};
}
}
// الاختبار
console.log(verifyAge('2006-05-15', 18));
console.log(verifyAge('1990-01-01', 21));
console.log(verifyAge('', 18));
console.log(verifyAge('2030-01-01', 18));
مرجع عوامل المقارنة
لكتابة شروط فعالة، تحتاج لفهم جميع عوامل المقارنة في JavaScript. اليك مرجع كامل مع امثلة توضح المزالق الشائعة.
مثال: عوامل المقارنة
// المساواة الصارمة (===) -- تتحقق من القيمة والنوع (موصى بها)
console.log(5 === 5); // true
console.log(5 === '5'); // false (انواع مختلفة)
console.log(true === 1); // false (انواع مختلفة)
// المساواة المتساهلة (==) -- تتحقق من القيمة فقط، تجري تحويل النوع (تجنبها)
console.log(5 == '5'); // true (السلسلة "5" تحول الى الرقم 5)
console.log(true == 1); // true (true يحول الى 1)
console.log(null == undefined); // true (حالة خاصة)
console.log('' == 0); // true (السلسلة الفارغة تحول الى 0)
// عدم المساواة الصارمة (!==) -- عكس ===
console.log(5 !== '5'); // true
console.log(5 !== 5); // false
// اكبر من، اصغر من، اكبر من او يساوي، اصغر من او يساوي
console.log(10 > 5); // true
console.log(10 < 5); // false
console.log(10 >= 10); // true
console.log(10 <= 9); // false
// مقارنة السلاسل (ترتيب معجمي / ابجدي)
console.log('apple' < 'banana'); // true
console.log('A' < 'a'); // true (الاحرف الكبيرة تاتي اولا)
console.log('10' < '9'); // true (تقارن كسلاسل وليس كارقام!)
=== وعدم المساواة الصارمة !== بدلا من المساواة المتساهلة == وعدم المساواة المتساهلة !=. المساواة المتساهلة تجري تحويل النوع، مما يؤدي الى نتائج غير متوقعة ومربكة. الاستثناء الوحيد هو التحقق من null او undefined حيث value == null هو نمط شائع يتحقق من كل من null و undefined في مقارنة واحدة.افضل الممارسات للمنطق الشرطي
كتابة منطق شرطي فعال ليست فقط عن معرفة الصيغة -- انها عن كتابة شروط واضحة وقابلة للصيانة وخالية من الاخطاء. اليك اهم افضل الممارسات التي يجب اتباعها.
مثال: افضل الممارسات
// 1. استخدم اسماء متغيرات وصفية للشروط
// سيء:
if (u && u.a > 18 && u.r === 'a') { /* ... */ }
// جيد:
let isAdult = user.age > 18;
let isAdmin = user.role === 'admin';
if (user && isAdult && isAdmin) { /* ... */ }
// 2. تجنب الشروط السلبية عندما يكون ذلك ممكنا
// اصعب في القراءة:
if (!isNotLoggedIn) {
console.log('مرحبا!');
}
// اسهل في القراءة:
if (isLoggedIn) {
console.log('مرحبا!');
}
// 3. ضع الشرط الاكثر احتمالا اولا في سلاسل else if
if (status === 'active') {
// الحالة الاكثر شيوعا -- يتم فحصها اولا
} else if (status === 'pending') {
// ثاني اكثر شيوعا
} else if (status === 'suspended') {
// حالة نادرة
} else {
// حالة غير معروفة
}
// 4. استخرج الشروط المعقدة الى متغيرات مسماة
// صعب القراءة:
if (user.age >= 18 && user.country === 'US' && user.hasVerifiedEmail &&
(user.subscriptionType === 'premium' || user.trialDaysRemaining > 0)) {
// ...
}
// اكثر نظافة بكثير:
let isEligibleAge = user.age >= 18;
let isUSBased = user.country === 'US';
let isVerified = user.hasVerifiedEmail;
let hasActiveSubscription = user.subscriptionType === 'premium' ||
user.trialDaysRemaining > 0;
if (isEligibleAge && isUSBased && isVerified && hasActiveSubscription) {
// الآن الشرط يقرا كالانجليزية
}
// 5. استخدم شروط الحماية لتقليل التداخل
// انظر القسم التفصيلي اعلاه عن شروط الحماية
if (isLoggedIn && isAdmin && hasPermission) يقرا بشكل طبيعي كـ "اذا كان المستخدم مسجل الدخول ومسؤول ولديه صلاحية."التمرين 1: محول درجات الحرارة مع نصائح
اكتب دالة تسمى temperatureAdvice تاخذ درجة حرارة بالسلسيوس وترجع كائنا يحتوي درجة الحرارة بالفهرنهايت ونصيحة مناسبة. استخدم if و else if و else لتصنيف درجة الحرارة: اقل من 0 يجب ان تقول "تجمد! ارتد طبقات ثقيلة وابق في الداخل اذا امكن." بين 0 و 15 يجب ان تقول "بارد. ارتد سترة دافئة." بين 16 و 25 يجب ان تقول "مريح. الطبقات الخفيفة كافية." بين 26 و 35 يجب ان تقول "دافئ. حافظ على الترطيب وضع واقي شمس." فوق 35 يجب ان تقول "حرارة شديدة! تجنب الانشطة الخارجية." اختبر دالتك بخمس درجات حرارة مختلفة على الاقل.
التمرين 2: محاكاة نظام تسجيل الدخول
انشئ دالة تسمى attemptLogin تاخذ اسم مستخدم وكلمة مرور ومصفوفة من المستخدمين الحاليين (كل مستخدم لديه خصائص username و password و isActive و failedAttempts). يجب على الدالة: (1) التحقق اذا كان اسم المستخدم موجودا. (2) اذا كان الحساب مقفلا (failedAttempts >= 5)، ارجع رسالة قفل. (3) اذا كان الحساب معطلا، ارجع رسالة تعطيل. (4) اذا كانت كلمة المرور خاطئة، زد عداد المحاولات الفاشلة وحذر المستخدم بعدد المحاولات المتبقية. (5) اذا كان كل شيء صحيحا، اعد تعيين failedAttempts الى 0 وارجع رسالة نجاح. استخدم شروط الحماية لهيكل مسطح.
التمرين 3: حاسبة اسعار التذاكر
ابن دالة تسمى calculateTicketPrice تاخذ كائنا بالخصائص التالية: age (رقم)، isStudent (منطقي)، isMilitary (منطقي)، dayOfWeek (سلسلة)، و showTime (سلسلة مثل "14:00" او "20:00"). السعر الاساسي هو $15. طبق القواعد التالية باستخدام منطق if/else: الاطفال تحت 5 سنوات مجانا، الاطفال 5-12 يحصلون على خصم 50%، كبار السن 65+ يحصلون على خصم 30%، الطلاب يحصلون على خصم 20%، العسكريون يحصلون على خصم 25% (استخدم اعلى خصم اذا تعدد، لا تجمعها). العروض الصباحية (قبل 17:00) تحصل على خصم $3 اضافي. الثلاثاء هو يوم الخصم -- طبق خصم 10% اضافي على السعر النهائي. ارجع كائنا يحتوي السعر الاصلي ومبلغ الخصم والسعر النهائي ووصف جميع الخصومات المطبقة.