سجى الحاج

هناك ثلاثة معاملات منطقية في JavaScript وهي: || (OR)، و && (AND)، و ! (NOT). رغم أنها تسمى معاملات منطقية، إلا أنه يمكن تطبيقها على أي نوع من أنواع البيانات وليس فقط على البيانات المنطقية. دعنا نرى التفاصيل.

المعامل || (OR) المنطقي

يُمثَّل معامل OR المنطقي بخطين عموديين ||:

result = a || b;

في لغات البرمجة القديمة، يعالج المعامل OR المنطقي البيانات المنطقية فقط. إذا كانت أي من وسائطه (arguments) تحمل القيمة true، فإن المعامل يُرجع القيمة true، عدا ذلك يُرجع false.

في JavaScript، المعامل أصعب قليلاً وأكثر فائدة، دعنا نرى ما يحدث مع البيانات المنطقية.

هناك أربع مجموعات منطقية محتملة:

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

كما ترى، النتيجة صحيحة true دائمًا باستثناء الحالة التي يكون فيها كلا العاملين (operands) خطأ false. إذا لم يكن العامل منطقيًا، سيُحوّل إلى قيمة منطقية لتتم عملية التقييم. على سبيل المثال، يتم التعامل مع العدد 1 على أنه true، والعدد 0 على أنه false:

if (1 || 0) { // تمامًا true || false يقابل التعبير
  alert( 'truthy!' );
}

غالبًا ما يُستخدام المعامل || في الجُمل الشرطية if لاختبار ما إذا كان أي من الشروط محقق true. على سبيل المثال:

let hour = 9;
if (hour < 10 || hour > 18) {
  alert( 'The office is closed.' );
}

يمكن التحقُّق من عدَّة شروط في الوقت نفسه مثل:

let hour = 12;
let isWeekend = true;
if (hour < 10 || hour > 18 || isWeekend) {
  alert( 'The office is closed.' ); //الوقت عطلة  
}

المعامل OR يرجع القيمة الصحيحة الاولى

المنطق الموصوف أعلاه قديم إلى حد ما. لنوضّح ميزات إضافية في JavaScript. الخوارزمية الموسعة تعمل على النحو التالي. بالنظر إلى قيم المعامل OR المتسَلسَلة في المثال التالي:

result = value1 || value2 || value3;

يقوم المعامل المنطقي || بالتالي:

  • يقيم المعاملات (operand) من اليسار إلى اليمين.
  • يحوِّل جميع العاملات (operands) إلى قيم منطقية إن لم تكن كذلك. إذا كانت النتيجة صحيحة true، يتوقف ويرجع القيمة الأصلية لذلك العامل.
  • إذا قيِّمَت جميع العامِلات وكانت جميعها false خطأ، يرجع العامل الأخير.

تُرجَع القيمة بشكلها الأصلي. بمعنى آخر، سلسلة من المعامل || تُرجع القيمة الصحيحة الأولى أو القيمة الأخيرة إذا لم يتم العثور على قيمة صحيحة.

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

alert( 1 || 0 ); // 1 العدد 1 عبارة عن القيمة الصحيحة
alert( true || 'no matter what' ); // (true is truthy)

alert( null || 1 ); // 1 القيمة الصحيحة الأولى هي
alert( null || 0 || 1 ); // 1 القيمة الصحيحة الأولى هي
alert( undefined || null || 0 ); // 0 جميع القيم خاطئة، يرجع القيمة الأخيرة

هذه المميزات تؤدي إلى بعض الاستخدامات المثيرة للاهتمام موازنةً بالمعامل المنطقي (OR) الكلاسيكي، أو المنطقي فقط.

1- الحصول على أول قيمة صحيحة من قائمة المتغيرات أو التعبيرات. تخيل أن لدينا قائمة من المتغيرات التي يمكن أن تحتوي على بيانات أو تكون فارغة/غير محددة null/undefined. كيف يمكننا العثور على أول واحد مع البيانات؟ باستخدام المعامل المنطقي ||:

let currentUser = null;
let defaultUser = "John";

let name = currentUser || defaultUser || "unnamed";

alert( name ); // يختار القيمة الصحيحة الأولى

إذا كان كلًا من المتغيرات currentUser و defaultUser خطأ، فستكون النتيجة unnamed.

2- تقييم الدارة القصيرة (Short-circuit)

لا تكون العاملات (operands) قيمًا فقط، بل يمكن أن تكون تعبيرات عشوائية. المعامل المنطقي OR يفحصها ويقييمها من اليسار إلى اليمين، يتوقف التقييم عند الوصول إلى قيمة صحيحة وتُرجع القيمة. تسمى هذه العملية "تقييم الدارة القصيرة" لأنها تختصر عملية التقييم قدر الإمكان من اليسار إلى اليمين.

يظهر هذا بوضوح عندما يكون التعبير المعطى كعامل ثاني، له تأثير جانبي مثل إسناد متغير. في المثال أدناه، لا يتم إسناد x:

let x;
true || (x = 1);
alert(x); // undefined, because (x = 1) not evaluated

إذا كان العامل الأول خطأ false، يقييم المعامل المنطقي || العامل الثاني، وبالتالي تستمر عملية الإسناد:

let x;
false || (x = 1);
alert(x); // 1

عملية الإسناد عملية بسيطة. قد تكون هناك آثار جانبية، لن تظهر إذا كان التقييم لم يصل إليها.

كما نرى، فإن حالة الاستخدام هذه هي "طريقة أقصر للقيام بالمعامل الشرطيif". يُحوَّل العامل الأول إلى قيمة منطقية؛ فإذا كان خطأ، فسيُقيَّم العامل الثاني.

في أغلب الأحيان، من الأفضل استخدام المعامل الشرطي if بشكله الاعتيادي للحفاظ على سهولة فهم الشيفرة، ولكن لا يكون دائمًا في متناول اليد.

المعامل AND) &&‎) المنطقي

يُمثَّل المعامل AND المنطقي بعلامتين &&:

result = a && b;

عند كتابة شيفرة بلغات البرمجة القديمة، يُرجع المعامل AND المنطقي true إذا كان كلا العاملان صحيحين ويُرجع 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' );
}

تمامًا كما هو الحال مع المعامل المنطقي OR، يُسمح بأي قيمة لتكون عاملًا للمعامل المنطقي AND:

if (1 && 0) { // تقييم كأنها صواب او خطأ
  alert( "won't work, because the result is falsy" );
}

المعامل AND يرجع القيمة الخطأ الأولى

بالنظر إلى قيم المعامل AND المتعدِّدة في المثال التالي:

result = value1 && value2 && value3;

يقوم المعامل المنطقي AND بالتالي:

  • يقيم العاملات من اليسار إلى اليمين.
  • يحوّل جميع العاملات إلى قيم منطقية. إذا كانت النتيجة false، يتوقف ويرجع القيمة الأصلية لذلك العامل.
  • إذا قيِّمَت جميع العامِلات وكانت جميعها صحيحة، يُرجَع العامل الأخير.

بمعنى آخر، سلسلة من المعامل AND تُرجع القيمة الخطأ الأولى أو القيمة الأخيرة إذا لم يُعثَر على أي قيمة خطأ.

القواعد المذكورة أعلاه تشبه قواعد المعامل المنطقي OR. الفرق هو أن المعامل المنطقي AND يُرجع القيمة الخطأ الأولى بينما يُرجع المعامل المنطقي OR القيمة الصحيحة الأولى.

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

// إذا كان العامل الأول صحيحًا، يرجع
// العامل الثاني AND المعامل المنطقي 
alert( 1 && 0 ); // 0
alert( 1 && 5 ); // 5
// إذا كان العامل الأول خطأ، يرجع المعامل
// هذا العامل ويتجاهل العامل الثاني AND المنطقي 
alert( null && 5 ); // null
alert( 0 && "no matter what" ); // 0

يمكننا أيضا سَلسَلة العديد من القيم على التوالي. انظر كيف تُرجَع أول قيمة خطأ:

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

عندما تكون جميع القيم صحيحة، تُرجَع آخر قيمة:

alert( 1 && 2 && 3 ); // 3, القيمة الأخيرة

أولوية المعامل المنطقي && في التنفيذ أعلى من أولوية المعامل المنطقي ||

لذلك، التعبير التالي a && b || c && d هو نفس التعبير (a && b) || (c && d) مع الأقواس التي لها الأولية دومًا.

يمكن استعمال المعامل المنطقي && بدلًا من if مثل المعامل المنطقي ||. على سبيل المثال:

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

لن ينفَّذ الإجراء في الجزء الأيمن الخاص بالمعامل المنطقي && إلا إذا وصل التقييم إليه، أي فقط إذا كان x>0 محقَّقًا (صحيحًا):

let x = 1;
if (x > 0) {
  alert( 'Greater than zero!' );
}

يبدو المثال الأول الذي استعملنا فيه المعامل المنطقي && أقصر، ولكن المثال الثاني الذي استعلمنا فيه if أوضح أضف إلى سهولة قراءة الشيفرة. لذلك، نوصي باستخدام كل معامل للغرض المناسب له: أي يمكنك استخدام التعليمة الشرطية if عندم وجود شرط، واستعمل المعامل المنطقي &&عند التعامل مع القيم المنطقية.

المعامل المنطقي ! (NOT)

المعامل المنطقي NOT يُعبَّر عنه بعلامة التعجب !. الصيغة الخاصة به بسيطة للغاية:

result = !value;

يقبل المعامل المنطقي NOT عاملًا واحدًا (operand) ويقوم بما يلي:

  • يُحوِّل العامل إلى قيمة منطقية: true/false.
  • يرجع القيمة العكسية لتلك القيمة المنطقية.

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

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

يُستخدَم المعامل المنطقي NOT المزدوج (أي !!) في بعض الأوقات لتحويل قيمة معينة إلى قيمة منطقية:

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

بمعنى، المعامل المنطقي NOT الأول (أي ‎!"non-empty string"‎) يحول القيمة إلى قيمة منطقية (true!) ويرجع القيمة العكسية (false)، والمعامل المنطقي NOT الثاني (أي ‎!!"non-empty string"‎) يرجع القيمة العكسية مرة أخرى للقيمة التي أعادها المعامل الأول (true الناتج النهائي). في النهاية، يوفر لنا المعامل !! وسيلةً لتحويل أي قيمة إلى قيمة منطقية بسهولة.

هناك طريقة مطوّلة أكثر قليلاً لفعل الشيء نفسه - باستخدام الدالة Boolean:

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

أولوية المعامل المنطقي ! هي الأعلى بين جميع المعاملات المنطقية الأخرى، لذلك ينفذ أولًا قبل المعامل && والمعامل ||.

تمارين

ما هي نتيجة المعامل OR

الأهمية: 5

ما ناتج الشيفرة التالية؟

alert( null || 2 || undefined );

الحل:

الإجابة هي 2، هذه هي القيمة الصحيحة الأولى.

alert( null || 2 || undefined );

ما هي نتيجة سلسلة من المعامل OR للدالة alert

الأهمية: 3

ما ناتج الشيفرة التالية؟

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 للعامل التالي بحثًا عن قيمة صحيحة.
  3. العامل الثاني 2 عبارة عن قيمة صحيحة (أي يقيَّم إلى true)، وبذلك يتوقف تنفيذ سلسلة المعامل OR ويُرجع العامل 2 ثم يُعرَض بواسطة الدالة alert.

لن يظهر العدد 3، لأن التقييم انتهى عند العامل الثاني و لن يصل إلى alert(3)‎.

ما هي نتيجة المعامل AND

الأهمية: 5

ما ناتج الشيفرة التالية؟

alert( 1 && null && 2 );

الحل:

الإجابة هي: null لأنها القيمة الخطأ الأولى في التعبير:

alert( 1 && null && 2 );

ما هي نتيجة سلسلة من المعامل AND للدالة alert

الأهمية: 3

ماذا ستُظهر الشيفرة التالية؟

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

الحل:

الإجابة هي: 1 ثم undefined:

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

استدعاء الدالة alert يُرجع undefined (هي فقط تُظهر رسالة للمستخدم، أي ليس هناك شيء ذا معنى لإعادته). لهذا السبب، يقيِّم المعامل && العامل الأيسر (المخرجات 1) ، ويتوقف على الفور، لأنَّ القيمة undefined هي قيمة خطأ (أي false). والمعامل && يبحث عن أول قيمة خطأ ويُرجعها، فقط.

الناتج من سَلسلة المعاملات على النحو التالي (OR AND OR)

الأهمية: 5

ما الناتج من الشيفرة التالية؟

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

الحل:

الإجابة هي: 3.

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

أولوية المعامل && في التنفيذ أكبر من أولوية المعامل ||، لذلك يُنفَّذ أولًا. نتيجة لذلك 2 && 3 = 3، يصبح التعبير:

null || 3 || 4

الآن، الإجابة هي القيمة الصحيحة الأولى: 3.

حصر قيمة متغير ضمن مجال

الأهمية: 3

اكتب شرطًا (أي if) للتحقق من أنَّ قيمة المتغير age محصورة بين 14 و 90 (داخلة ضمن المجال).

الحل:

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

حصر متغير خارج مجال

الأهمية: 3

اكتب شرطًا (أي if) للتحقق من أنَّ قيمة المتغير age لا تقع ضمن 14 و 90 (داخلة ضمن المجال). أنشئ تعبيرين مختلفين: الأول باستخدام معامل النفي !، والثاني دونه.

الحل:

التعبير الأول:

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

التعبير الثاني:

if (age < 14 || age > 90)

سؤال باستخدام التعبير الشرطي if

الأهمية: 5

أي دالة من الدوال alert سوف تُنفَّذ؟ ماذا ستكون نتائج التعبيرات الموجودة في داخل التعبير الشرطي if(...)‎:

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

الحل:

الإجابة هي: التعبير الأول والثالث والسبب:

// يعمل
// ناتج 0 || 1- هو 1-، أول قيمة صحيحة
if (-1 || 0) alert( 'first' );

// لا يعمل
// ناتج 0 && 1- هو 0، قيمة خطأ
if (-1 && 0) alert( 'second' );

// يُنفَّذ بالشكل التالي
// || المعامل && له أولوية في التنفيذ أكبر من المعامل 
// || يُنفذ أولًا 1 && 1- ثم المعامل 
// null || -1 && 1  ->  null || 1  ->  1
if (null || -1 && 1) alert( 'third' );

التحقق من تسجيل الدخول

الأهمية: 3

اكتب الشيفرة التي تطلب من المستخدم تسجيل الدخول بواسطة الدالة prompt. إذا أدخل المستخدم Admin، فاطلب كلمة مرور بواسطة الدالة prompt، إذا كان الإدخال عبارة عن سطر فارغ أو مفتاح الهروب Esc - فأظهر "تم الإلغاء"، إذا كان عبارة عن سلسلة نصية أخرى - فأظهر "لا أعرفك".

تُقحص كلمة المرور على النحو التالي:

  • إذا كانت تساوي "TheMaster"، سيُعرَض "مرحبًا!" ،
  • سلسلة نصية أخرى، سيُعرَض "خطأ" ،
  • سلسلة نصية فارغة أو "Cancel"، أظهر "إلغاء".

schema.png

يُرجى استخدام الشرط المتداخل (nested) للمحافظة على سهولة قراءة الشيفرة.

ملاحظة: تمرير قيمة فارغة للدالة prompt يُرجِع سلسلة فارغة ''. الضغط على مفتاح الهروب ESC أثناء تنفيذ الدالة prompt يُرجِع null.

الحل:

let userName = prompt("من أنت؟", '');

if (userName == 'Admin') {

  let pass = prompt(ما كلمة المرور؟', '');

  if (pass == 'TheMaster') {
    alert( 'مرحبًا!' );
  } else if (pass == '' || pass == null) {
    alert( 'إلغاء' );
  } else {
    alert( 'خطأ' );
  }

} else if (userName == '' || userName == null) {
  alert( 'إلغاء' );
} else {
  alert( "لا أعرفك" );
}

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

ترجمة -وبتصرف- للفصل Logical operators من كتاب The JavaScript Language

اقرأ أيضًا





تفاعل الأعضاء


لا توجد أيّة تعليقات بعد



يجب أن تكون عضوًا لدينا لتتمكّن من التعليق

انشاء حساب جديد

يستغرق التسجيل بضع ثوان فقط


سجّل حسابًا جديدًا

تسجيل الدخول

تملك حسابا مسجّلا بالفعل؟


سجّل دخولك الآن