اذهب إلى المحتوى

معاملات الموازنة


سجى الحاج

لا شك أنَّك تعرَّفت مسبقًا على معاملات الموازنة من أحد دروس الرياضيات في المدرسة وهي:

  • أكبر/أصغر من: a < b - a > b.
  • أكبر/أصغر من أو يساوي: a <= b - a >= b.
  • المساواة: a == b (يرجى ملاحظة أنَّ هذا المعامل عبارة عن علامة يساوي مزدوجة =. العلامة المنفردة a = b خاصة بمعامل الإسناد الذي تحدثنا عنه في المقال السابق).
  • عدم المساواة: يُعبر عنه في الرياضيات بالرمز، ولكن يُعبِّر عنه برمجيًّا في JavaScript بإشارة يساوي منفردة مع إشارة تعجب قبلها بالشكل: a != b.

النتيجة عبارة عن قيمة منطقية

مثل كل المعاملات الأخرى، تُرجِع معاملات الموازنة قيمة منطقية دومًا.

  • true - تعني «نعم» أو «صواب» أو «الموازنة مُحقَّقة».
  • false - تعني «لا» أو «خطأ» أو «الموازنة غير مُحقَّقة».

إليك أمثلة عن هذه المعاملات:

alert( 2 > 1 );  // true (الموازنة صحيحة)
alert( 2 == 1 ); // false (الموازنة خطأ)
alert( 2 != 1 ); // true (الموازنة صحيحة)

يمكن إسناد نتيجة معامل الموازنة لمتغير تمامًا مثل أي قيمة:

let result = 5 > 4; // إسناد الناتج من عملية الموازنة لمتغير
alert( result ); // true

موازنة السلاسل النصية

لمعرفة ما إذا كانت السلسلة النصية أكبر من الأخرى، تستخدم JavaScript ما يسمى بترتيب القاموس (dictionary) أو ترتيب المعجم (lexicographical). بمعنى آخر، تتم موازنة السلاسل النصية حرفًا تلو الآخر. على سبيل المثال:

alert( 'Z' > 'A' ); // true
alert( 'Glow' > 'Glee' ); // true
alert( 'Bee' > 'Be' ); // true

خوارزمية موازنة سلسلتين نصيتين بسيطة:

  1. موازنة الحرف الأول من كلا السلسلتين.
  2. إذا كان الحرف الأول من السلسلة النصية الأولى أكبر (أو أقل) من السلسلة النصية الأخرى، حينها تكون الأولى أكبر (أو أقل) من الثانية وبذلك تنتهي عملية الموازنة.
  3. لكن إذا كانت الأحرف الأولى في كلا السلسلتين متماثلة، وازن الأحرف الثانية بالطريقة نفسها.
  4. كرر حتى نهاية أي سلسلة.
  5. إذا انتهت كلا السلسلتين بالطول نفسه، فهما متساويتان. خلاف ذلك يكون السلسلة النصية الأطول هو الأكبر.

في الأمثلة أعلاه، تحصل الموازنة 'Z' > 'A' على النتيجة في الخطوة الأولى بينما تُوازن السلسلتين النصيتين "Glow" و "Glee" حرفًا تلو الآخر حتى الحرف الأخير بالتسلسل التالي:

  1. G هو نفسه G.
  2. l هو نفسه l.
  3. o أكبر من e. توقف هنا، السلسلة الأولى أكبر.

ليس قاموس حقيقي، ولكنه ترتيب ترميز اليونيكود

إنَّ خوارزمية الموازنة المذكورة أعلاه تعادل تقريبًا تلك المستخدمة في القواميس ودفاتر الهاتف، ولكن مع اختلاف بسيط يتعلق بحالة الحرف. فالحرف الكبير "A" لا يساوي الحرف الصغير "a" كما تعتقد فأيهما أكبر برأيك؟ الحرف الصغير "a" طبعًا. أسمعك تسأل لماذا؟ لأنَّ الحرف الصغير له رقم تسلسلي أكبر في جدول الترميز المقابل له في جدول اليونيكود المستخدم في JavaScript، حسنًا، سكفي إلى هنا وسنعاود الحديث عن هذا الموضوع والنتائج المترتبة عليه في فصل السلاسل النصية.

موازنة بين أنواع البيانات المختلفة

عند موازنة أنواع بيانات مختلفة، تحوّل JavaScript القيم إلى أعداد. على سبيل المثال:

alert( '2' > 1 ); // true, تُحوَّل السلسلة النصية '2' إلى العدد 2
alert( '01' == 1 ); // true, تُحوَّل السلسلة النصية '01' إلى العدد 1

بالنسبة للقيم المنطقية، true تصبح 1 و false تصبح 0. على سبيل المثال:

alert( true == 1 ); // true
alert( false == 0 ); // true

نتيجة مضحكة أليس كذلك؟!

من الممكن في الوقت نفسه أن تكون القيمتان:

  • متساويتين.
  • واحدة منهما true والأخرى false.

إليك مثال عن حالة مماثلة:

let a = 0;
alert( Boolean(a) ); // false

let b = "0";
alert( Boolean(b) ); // true

alert(a == b); // true!

من وجهة نظر JavaScript، هذه النتيجة طبيعية تمامًا. تُحوّل عملية التحقق من المساواة القيم باستخدام التحويل العددي (وبالتالي السلسلة النصية "0" تساوي القيمة 0)، بينما يستخدم التحويل الصريح Boolean مجموعة أخرى من القواعد.

معامل المساواة الصارمة

معامل المساواة العادية == لديه مشكلة، وهي عدم قدرته على التمييز بين 0 و false:

alert( 0 == false ); // true

يحدث الشيء نفسه مع السلسلة النصية الفارغة:

alert( '' == false ); // true

يحدث هذا لأنَّ الأنواع المختلفة من العاملات تُحول إلى أعداد بواسطة معامل المساواة ==. السلسلة النصية الفارغة مثل false، تصبح صفرًا.

ماذا نفعل إذا كنا نرغب في التمييز بين 0 و false؟ معامل المساواة الصارمة === يتحقق من المساواة دون تحويل القيم. بمعنى آخر، إذا كان a وb قيمتين من نوعين مختلفين، فسوف تُرجع المعادلة a === b على الفور false دون محاولة تحويلها، وبذلك يتحقق المعامل === من تساوي النوع أولًا ثم تساوي القيمة.

دعنا نجرب:

alert( 0 === false ); // false, لأن القيمتين من نوعين مختلفين

هناك أيضًا معامل عدم مساواة صارم ‎!==‎ مماثل للمعامل ‎!=‎.

يعد معامل المساواة الصارمة أطول قليلاً في الكتابة، ولكنه أكثر وضوحًا ويترك مساحة أقل للأخطاء.

الموازنة مع قيمة فارغة null وغير مُعرّفة undefined

دعنا نرى المزيد من الحالات الخاصة. تسلك عملية الموازنة سلوكًا غير منطقي عند موازنة قيمة فارغة null أو غير مُعرّفة undefined مع قيم أخرى، إذ هاتان القيمتان من نوعين مختلفين.

تذكر أنَّه للتحقق من المساواة بصرامة، استعمل المعامل === دومًا:

alert( null === undefined ); // false

للتحقق من المساواة دون أخذ النوع بالحسبان، استعمل المعامل ==. بمعنى أنَّ القيمتين null و undefined متساويتان فقط مع بعضهما ولكن ليستا متساويتان مع أي قيمة أخرى.

alert( null == undefined ); // true

الرياضيات ومعاملات الموازنة الأخرى ‎< > <= >=‎

القيمة الفارغة وغير المُعرّفة null و undefined يتم تحويلها إلى عدد: null تصبح 0، بينما undefined تصبح NaN.

الآن دعنا نرى بعض الأشياء المضحكة التي تحدث عندما نطبق هذه القواعد، والأهم من ذلك هو كيفية تجنب هذا الفخ.

نتيجة غريبة: null مقابل 0

دعنا نوازن null مع 0:

alert( null > 0 );  // (1) false
alert( null == 0 ); // (2) false
alert( null >= 0 ); // (3) true

رياضيًّا، هذا غريب، إذ تشير النتيجة الأخيرة إلى أنَّ «null أكبر من أو تساوي 0»، لذلك يجب في إحدى الموازنات أعلاه أن تكون صحيحة true، لكن كلاهما خطأ.

السبب هو أنَّ التحقق من المساواة == ومعاملات الموازنة ‎> < >= <=‎ تعمل بشكل مختلف. تحول الموازنات القيمة الفارغة null إلى عدد، وتعاملها على أنها 0 ولهذا السبب، نتيجة الموازنة في المثال السابق في السطر (3) null >= 0 مُحقَّقة أي true وفي السطر (1) خطأ null > 0.

من ناحية أخرى، يتم التحقق من المساواة == على undefinedوnull بدون أي تحويل، حيث أنه يساوي كل منهما الآخر ولا يساويها أي قيمة أخرى. لهذا السبب، نتيجة الموازنة في المثال السابق في السطر (2) null == 0 غير محقَّقة.

القيمة غير المُعرّفة undefined غير قابلة للموازنة أي لا ينبغي موازنتها undefined مع القيم الأخرى:

alert( undefined > 0 ); // false (1)
alert( undefined < 0 ); // false (2)
alert( undefined == 0 ); // false (3)

لماذا يُكره الصفر كثيرًا؟ دائما خطأ! حصلنا على هذه النتائج لأن:

  • معاملات الموازنة في السطر (1) و(2) في المثال السابق تُرجع false، لأن القيمة undefined تُحوّل إلى NaN وهي عبارة عن قيمة رقمية خاصة تعيد false لكافة الموازنات.
  • تُرجع عملية التحقق من المساواة في السطر(3) القيمة false، لأن القيمة غير المُعرّفة undefined تساوي فقط القيمة null و undefined، ولا تساوي قيم أخرى.

تجنب المشاكل

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

  • تعامل بالصورة المألوفة مع أي موازنة بها undefined/null، باستثناء المساواة الصارمة === فهي تحتاج معاملة استثنائية.
  • لا تستخدم معاملات الموازنة ‎>= > < <=‎ مع متغير قد يأخذ إحدى القيمتين null/undefined، إلا إذا كنت متأكدًا حقًا مما تفعله. إذا كان المتغير عبارة عن هاتين القيمتين، فتحقق منها بشكل منفصل.

الخلاصة

  • تُرجع معاملات الموازنة قيمة منطقية.
  • تُوازن السلاسل النصية حرفًا تلو الآخر حسب ترتيب القاموس (dictionary).
  • عند موازنة قيم من أنواع بيانات مختلفة، يتم تحويلها إلى أرقام (باستثناء التحقق من المساواة الصارمة).
  • القيم الفارغة null وغير المعرّفة undefined تساوي == بعضها بعضًا، ولا تساوي أي قيمة أخرى.
  • كن حذرًا عند استخدام معاملات موازنة مثل> أو < مع متغيرات يمكن أن تكون فارغة null أو غير معرّفة undefined ويفضل التحقق من ذلك بشكل منفصل.

تمارين

الموازنات

الأهمية: 5

ماذا ستكون نتيجة هذه الموازنات

5 > 4
"apple" > "pineapple"
"2" > "12"
undefined == null
undefined === null
null == "\n0\n"
null === +"\n0\n"

الحل

  1. 5 > 4                 ← true
  2. "apple" > "pineapple"‏ ← false
  3. "2" > "12"            ← true
  4. undefined == null‏     ← true
  5. undefined === null‏    ← false
  6. null == "\n0\n"‏       ← false
  7. null === +"\n0\n"‏     ← false

بعض الأسباب:

  1. نتيجة الموازنة واضحة، صحيحة.
  2. حسب موازنة القاموس، النتيجة خاطئة.
  3. حسب موازنة القاموس مرة أُخرى، الحرف الأول من القيمة"2" أكبر من الحرف الأول من القيمة"1".
  4. القيم null و undefined تساويان بعضهما فقط.
  5. المساواة الصارمة صارمة فيما يخص نوع المتغير، وعند اختلاف نوع طرفي المعامل فإن النتيجة تصبح خاطئة.
  6. انظر للنقطة رقم (4).
  7. مساواة صارمة لنوعان مختلفان من القيم.

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

اقرأ أيضًا


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

أفضل التعليقات

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



انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أضف تعليق

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • أضف...