١٥ ديسمبر ٢٠٢١

العوامل المنطقية

يوجد اربعة عوامل منطقية في جافا سكريبت: || (OR), && (AND), ! (NOT), ?? (Nullish Coalescing). هنا سوف نقوم بشرح الثلاثة الأولى, و المعامل ?? فى الفصل القادم.

بالرغم من أن اسمهم عوامل منطقية إلا أنه يمكنك تطبيقهم على أي نوع من البيانات وليس فقط البيانات المنطقية. كما أنه يمكنهم إنتاج أي قيمة.

لنرى ذلك بالتفصيل.

|| (OR)

عامل “OR” رمزه هو خطين أفقيين:

result = a || b;

إذا كان أي من القيم الممررة له trueيكون الناتج true وغير ذلك يرجع false.

في جافا سكريبت فهو مخادع أكثر وأقوى. ولكن دعنا أولًا نرى ماذا يحدث مع القيم المنطقية.

هناك أربع إحتمالات:

alert(true || true); // true
alert(false || true); // true
alert(true || false); // true
alert(false || false); // false

يمكننا أن نرى أن النتيجة دائما true ما عدا في حالة عندما تكون كلتا القيمتين false.

إذا كانت القيم غير منطقية يتم تحويلها إلى قيم منطقية.

مثلًا الرقم 1 يعامل مثل true, الرقم 0 مثل false:

if (1 || 0) {
    // تعمل مثل ( true || false )
    alert("truthy!");
}

في معظم الأوقات يتم استخدام OR || مع if لإختبار إذا كان أي من الشروط المكتوبة تحقق true.

على سبيل المثال:

let hour = 9;

if (hour < 10 || hour > 18) {
  alert( 'المكتب مغلق.' );
}

يمكن تمرير شروط أكثر:

let hour = 12;
let isWeekend = true;

if (hour < 10 || hour > 18 || isWeekend) {
    alert("المكتب مغلق."); // إنها عطلة
}

OR "||" إيجاد أول قيمة truthy

ما تم وصفه بالأعلى هو الأمر التقليدي. الآن دعنا نرى ما أضافته جافا سكريبت.

الخوارزمية المضافة تعمل كالتالي.

يعطى العديد من القيم بينهم OR:

result = value1 || value2 || value3;

العامل OR || يفعل الآتي:

  • تنفيذ العمليات من اليسار لليمين.
  • تحويل كل عملية إلى قيمة منطقية وإذا كان الناتج true يتوقف وينتج القيمة الأصلية لهذه العملية.
  • إذا تم تنفيذ كل العمليات (مثلًا كلهم false) يرجع آخر عملية.

يتم إرجاع القيمة بصيغتها الأصلية دون تحويل.

بصيغة أخرى فإن مجموعة OR "||" ترجع أول قيمة truthy value أو آخر قيمة إذا لم تجد أي قيمة truthy.

مثلًا:

alert(1 || 0); // 1 (1 is truthy)

alert(null || 1); // 1 (1 هو أول قيمة truthy)
alert(null || 0 || 1); // 1 (أول قيمة truthy)

alert(undefined || null || 0); // 0 (الكل falsy, ترجع آخر قيمة)

هذا يوصل إلى بعض الاستخدامات الشيقة مقارنةً بالاستخدام التقليدي.

  1. الحصول على أول قيمة truthy من مبين مجموعة متغيرات أو تعبيرات.

    مثلًا لدينا firstName, lastName و nickName متغيرات, كلها إختياريه (مثال. يمكن ان تكون undefined او لديها قيم falsy).

    هيا نستخدم OR || لاختيار الذي لديه قيمة ونعرضه (أو نعرض "Anonymous" إذا لم يحدد أي أحد):

    let firstName = "";
    let lastName = "";
    let nickName = "SuperCoder";
    
    alert( firstName || lastName || nickName || "Anonymous"); // SuperCoder

    إذا كانت كل المتغيرات falsy, Anonymous سيتم عرض.

  2. Short-circuit evaluation.

    ميزة أخرى للعامل OR || تسمى “short-circuit” evaluation.

    ويعني أن || ينفذ العمليات الممررة له حتى أول قيمة truthy وبعد ذلك يتم إرجاع القيمة مباشرة بدون لمس باقي العمليات.

    أهمية هذه الميزة تصبح ملحوظة إذا كانت القيمة الممررة عبارة عن عملية لها آثار جانبية مثل تخصيص قيمة متغير أو استدعاء دالة

    في هذا المثال سيتم طباعة الرسالة الأولى ولن يتم طباعة الثانية:

    true || alert("not printed");
    false || alert("printed");

    في السطر الثاني يتوقف العامل OR || مباشرة عند الوصول إلى true لذلك فإن alert لا ينفذ.

    أحيانًا يستخدم الناس هذه الخاصية لتنفيذ أوامر فقط إذا كان الجزء الأيسر زائف.

&& (AND)

العامل AND يكتب بعلامتين عطف &&:

result = a && b;

في البرمجة التقليدية فإن العامل AND ينتج true إذا كان كلتا القيمتان truthy وغير ذلك يرجع false:

alert(true && true); // true
alert(false && true); // false
alert(true && false); // false
alert(false && false); // false

مثال باستخدام if:

let hour = 12;
let minute = 30;

if (hour == 12 && minute == 30) {
    alert("The time is 12:30");
}

يمكن استخدام أي قيمة مع AND:

if (1 && 0) {
    // تنفذ مثل true && false
    alert("لن يعمل لأن النتيجة falsy");
}

AND “&&” إيجاد أول قيمة falsy

يعطى العديد من القيم بينهم AND:

result = value1 && value2 && value3;

العامل AND && يفعل الآتي:

  • تنفيذ العمليات من اليسار إلى اليمين.
  • كل عملية تحول إلى قيمة منطقية. إذا كانت النتيجة false يتوقف ويرجع القيمة الأصلية لهذه العملية.
  • إذا تم تنفيذ كل العمليات (يعنى أن كلهم were truthy) يرجع آخر قيمة

بكلمات أخرى فإن AND ترجع أول قيمة falsy أو آخر قيمة.

هذا مشابه ل OR. الاختلاف هو أن AND ترجع أول قيمة falsy بينما OR ترجع أول قيمة truthy.

Examples:

// إذا كانت أول قيمة truthy,
// AND ترجع ثاني قيمة:
alert(1 && 0); // 0
alert(1 && 5); // 5

// إذا كانت أول قيمة falsy,
// AND ترجعها وتتجاهل القيمة الثانية
alert(null && 5); // null
alert(0 && "no matter what"); // 0

يمكننا أيضًا تمرير العديد من القيم وسيتم إرجاع أول قيمة falsy:

alert(1 && 2 && null && 3); // null

إذا كانت كل القيم truthy يتم إرجاع آخر قيمة:

alert(1 && 2 && 3); // 3, آخر قيمة
أولوية العامل AND && أعلى من OR ||

أولوية العامل AND && أعلى من OR ||.

لذلك فإن a && b || c && d كأنك وضعت && بين أقواس: (a && b) || (c && d).

لا تستبدل if ب || أو &&

بعض الناس يستخدمون AND && كإختصار ل if.

مثلًا:

let x = 1;

(x > 0) && alert( 'Greater than zero!' );

سيتم تنفيذ الجزء الأيمن من && إذا كان (x > 0) يساوي true.

لذلك فهو يطابق:

let x = 1;

if (x > 0) alert( 'Greater than zero!' );

بالرغم من أن && يبدو مختصرًا إلا أن if أفذل ومقروءة أكثر. لذلك ننصح باستخدام كل تعبير في مكانه: نستخدم if إذا أردنا if ونستخدم && إذا أردنا AND.

! (NOT)

العامل NOT يتم تمثيله بعلامة تعجب !.

طريقة الكتابة بسيطة:

result = !value;

يقبل قيمة واحدة ويفعل الآتي:

  1. تحويل القيمة إلى قيمة منطقية: true/false.
  2. يرجع القيمة العكسية.

مثلًا:

alert(!true); // false
alert(!0); // true

أحيانًا يتم استخدام علامتين NOT !! للتحويل إلى قيمة منطقية:

alert(!!"non-empty string"); // true
alert(!!null); // false

أول NOT تحول إلى قيمة منطقية وترجع القيمة العكسية والثانية تعكسها مجددًا وفي النهاية نحصل على تحويل القيمة إلى قيمة منطقية.

وهناك طرق أخرى لعمل نفس الشئ – مثل دالة Boolean المدمجة في اللغة:

alert(Boolean("non-empty string")); // true
alert(Boolean(null)); // false

أولوية NOT ! هي الأعلى في كل العوامل المنطقية لذلك تنفذ أولًا دائمًا قبل && أو ||.

مهمه

ما خرج الأمر التالي ؟

alert( null || 2 || undefined );

الإجابة هي 2 لأنها أول قيمة truthy.

alert( null || 2 || undefined );

ما خرج الكود التالي ؟

alert( alert(1) || 2 || alert(3) );

الإجابة: أولًا 1 ثم 2.

alert( alert(1) || 2 || alert(3) );

استدعائ alert لا يرجع أي قيمة أو بمعنى آخر يرجع undefined.

  1. أول OR || تنفذ العملية على يسارها alert(1). وهذا يعرض أول رسالة 1.
  2. إن alert ترجع undefined لذلك تنتقل OR للعملية الثانية بحثًا عن قيمة truthy.
  3. القيمة الثانية 2 هي truthy لذلك يتوقف التنفيذ وترجع 2 ويتم عرضها.

لن يتم عرض 3 لأن التنفيذ لم يصل إلى alert(3).

ما خرج الكود التالي ؟

alert( 1 && null && 2 );

الإجابة: null لأنها أول قيمة falsy في القائمة.

alert( 1 && null && 2 );
الأهمية: 3

ما خرج الكود التالي ؟

alert( alert(1) && alert(2) );

الإجابة: 1 ثم undefined.

alert( alert(1) && alert(2) );

استدعاء alert يرجع undefined (إنها تعرض رسالة لذلك لا يوجد معنى لإرجاع قيمة).

وبسبب هذا تقوم && بتنفيذ العملية على اليسار (تعرض 1) وتتوقف لأن undefined تعتبر قيمة falsy. And && تبحث عن قيمة falsy وترجعها.

ما ناتج تنفيذ الأمر التالي ؟

alert( null || 2 && 3 || 4 );

الإجابة: 3.

alert( null || 2 && 3 || 4 );

أولوية AND && أعلى من || لذلك تنفذ أولًا.

نتيجة 2 && 3 = 3 لذلك يصبح التعبير كالتالي:

null || 3 || 4

النتيجة الآن هي أول قيمة truthy: 3.

اكتب تعبير if يفحص أن العمر age بين 14 و 90.

يمكن للعمر age أن يكون 14 أو 90.

if (age >= 14 && age <= 90)

اكتب تعبير if يفحص أن العمر age ليس بين 14 و 90.

قم بالحل بطريقتين مختلفتين: الأولى باستخدام NOT ! والثانية بدونها.

الطريقة الأولى:

if (!(age >= 14 && age <= 90))

الطريقة الثانية:

if (age < 14 || age > 90)

أي من هذه التنبيهات alert سيتم تنفيذه ؟

ماذا ستكون نتيجة التعبيرات داخل if(...)?

if (-1 || 0) alert( 'first' );
if (-1 && 0) alert( 'second' );
if (null || -1 && 1) alert( 'third' );

الإجابة: سيتم تنفيذ الأول والثالث

التفاصيل:

// ينفذ
// نتيجة -1 || 0 = -1 هي truthy
if (-1 || 0) alert("first");

// لا ينفذ
// -1 && 0 = 0, falsy
if (-1 && 0) alert("second");

// ينفذ
// العامل && له أولوية أعلى من ||
// لذلك يتم تنفيذ -1 && 1 أولا وينتج التالي:
// null || -1 && 1  ->  null || 1  ->  1
if (null || (-1 && 1)) alert("third");

أكتب كود يكلب تسجيل الدخول باستخدام prompt.

إذا كتب المستخدم كلمة "Admin" اطلب منه prompt كلمة المرور فإذا كتب سطر فارغ أو استخدم Esc – أظهر رسالة “Canceled” وإذا كان نص آخر أظهر له “I don’t know you”.

يتم فحص كلمة المرور كالتالي:

  • إذا كانت تساوي “TheMaster” يتم عرض “Welcome!”,
  • نص آخر يتم عرض “Wrong password”,
  • نص فارغ أو إلغاء العملية يتم عرض “Canceled”

الصيغة العامة:

استخدم تعبيرات if متداخلة. انتبه أن يكون الكود مقروء.

ملحوظة: تمرير نص فارغ إلى prompt يرجع نص فارغ ''. تمرير ESC يرجع null.

قم بتشغيل العرض التوضيحي

let userName = prompt("Who's there?", '');

if (userName === 'Admin') {

  let pass = prompt('Password?', '');

  if (pass === 'TheMaster') {
    alert( 'Welcome!' );
  } else if (pass === '' || pass === null) {
    alert( 'Canceled' );
  } else {
    alert( 'Wrong password' );
  }

} else if (userName === '' || userName === null) {
  alert( 'Canceled' );
} else {
  alert( "I don't know you" );
}

لاحظ المسافات داخل if. غير مطلوبة فعليًا ولكنها تجعل الكود مقروء أكثر.

خريطة الدورة التعليمية