كما نعلم جميعًا ، == في JavaScript هي عملية معقدة نسبيًا. قواعد تشغيلها غريبة للغاية ويمكنها ارتكاب أخطاء بسهولة ، مما يجعلها واحدة من "أسوأ الميزات" في JavaScript.
استنادًا إلى قراءة مواصفات ECMASCRIPT بعناية ، رسمت صورة. اعتقدت أنه بعد أن تفهم هذه الصورة ، ستفهم تمامًا كل شيء عن العملية ==. في الوقت نفسه ، حاولت إثبات للجميع من خلال هذا المقال أن == ليس بهذا الشيء السيئ. من السهل إتقانه وحتى يبدو معقولًا وليس بهذا السوء.
أولا ، الصورة:
== الوصف الدقيق لقواعد التشغيل هنا: خوارزمية مقارنة المساواة التجريدية. ومع ذلك ، مع هذا الوصف المعقد ، هل أنت متأكد من أنك لن تشعر بالدوار بعد قراءته؟ هل يمكنك استخدامه لتوجيه ممارستك على الفور؟
بالتأكيد لا يعمل. بعد كل شيء ، فإن المواصفات مخصصة لمطوري بيئة تشغيل JavaScript (مقارنة مع مطوري محركات V8) ، وليس لمستخدمي اللغات. تترجم الصورة أعلاه المواصفات إلى نموذج مناسب للجميع.
قبل تقديم كل جزء في الشكل 1 بالتفصيل ، دعنا نراجع المعرفة حول الأنواع في JS:
هناك نوعان من القيم في JS: النوع الأساسي ونوع الكائن.
وتشمل الأنواع الأساسية: غير محددة ، لاغية ، منطقية ، العدد والسلسلة.
كل من النوع غير المحدد والنوع الفارغ لهما قيمة واحدة فقط ، وهي غير محددة و NULL ؛ النوع المنطقي له قيمتان: صحيح وكاذب ؛ هناك العديد من القيم من نوع الرقم. ونوع السلسلة له قيم لا حصر لها (نظريًا).
تحتوي جميع الكائنات على قيمة () و ToString () ، والتي يتم ترجيحها من الكائن ويمكن بالطبع إعادة كتابة الفئات الفرعية.
الآن فكر في التعبير:
x == y
حيث x و y هما قيم أحد الأنواع الستة.
عندما تكون أنواع x و y هي نفسها ، يمكن تحويل x == y إلى x === y ، والأخير بسيط للغاية (الشيء الوحيد الذي يجب ملاحظته هو NAN) ، لذلك ننظر فقط في الحالات التي تختلف فيها أنواع x و y.
1. ليس ولا شيء
في الشكل 1 ، يتم تمثيل ستة أنواع من قيم JavaScript بواسطة مستطيلات ذات خلفية زرقاء. أولاً يتم تقسيمها إلى مجموعتين:
السلسلة والرقم والطغل والكائن (المقابل لصندوق مستطيل كبير على اليسار)
غير محدد ودون فارغ (المقابل للصندوق المستطيل على اليمين)
ما هو أساس التجميع؟ دعونا نلقي نظرة. يتم استخدام غير محدد و NULL على اليمين للإشارة إلى عدم اليقين ، غير أو فارغة ، في حين أن الأنواع الأربعة على اليمين كلها محددة ، موجودة وغير فارغة. يمكننا أن نقول هذا:
على اليسار عالم من الوجود ، وعلى اليمين هو عالم فارغ.
لذلك ، من المعقول مقارنة أي قيمة في العالمين مع خطأ. (على سبيل المثال ، الخط الأفقي الذي يربط اثنين من المستطيلات في الشكل 1 تم وضع علامة عليه خطأ)
2. فارغة وفارغة
غير محدد و Null في JavaScript هو مكان آخر غالبًا ما يعطلنا. وعادة ما يعتبر عيب في التصميم ، ولن نحفر فيه. لكنني سمعت أن مؤلف JavaScript يعتقد في البداية هذا:
إذا كنت تخطط لتعيين متغير لقيمة نوع الكائن ، ولكن لم تقم بتعيين قيمة حتى الآن ، فيمكنك استخدام NULL لتمثيل الحالة في هذا الوقت (أحد الأدلة هو أن نتيجة typeof null هي "كائن") ؛ على العكس من ذلك ، إذا كنت تخطط لتعيين متغير لقيمة النوع الأصلي ، ولكن لم يتم تعيين قيمة حتى الآن ، فيمكنك استخدام غير محدد لتمثيل الحالة في هذا الوقت.
بغض النظر عما إذا كانت هذه الشائعات موثوقة أم لا ، فمن المعقول أن تكون نتيجة المقارنة بين الاثنين صحيحة. (أي صحيح تم وضع علامة على الخط العمودي على اليمين في الشكل 1)
قبل الانتقال إلى الخطوة التالية ، دعنا نتحدث عن الرموسين في الشكل 1: الحروف الرأسمالية N و P. لا يعني هذان الرموسين إيجابية وسلبية في قسم PN. بدلاً من:
يمثل N عملية TONMORMER ، مما يعني تحويل المعامل إلى رقم. إنها عملية مجردة في مواصفات ES ، ولكن يمكننا استخدام وظيفة الرقم () في JS لاستبدالها بشكل متساوٍ.
يمثل P العملية ذات الحواف ، أي تحويل المعامل إلى قيمة النوع الأصلي. إنها أيضًا عملية مجردة في مواصفات ES ، ويمكن ترجمتها أيضًا إلى رمز JS مكافئ. لكنه أكثر تعقيدًا بقليل. بعبارة ببساطة ، لكائن OBJ:
تعادل Toprimitive (OBJ): أولاً حساب OBJ.Valueof () ، إذا كانت النتيجة هي القيمة الأصلية ، يتم إرجاع هذه النتيجة ؛ خلاف ذلك ، يتم حساب OBJ.ToString () ، وإذا كانت النتيجة هي القيمة الأصلية ، يتم إرجاع هذه النتيجة ؛ خلاف ذلك ، يتم طرح استثناء.
ملاحظة: هناك استثناء هنا ، أي كائن من تاريخ النوع ، والذي سيتصل أولاً بطريقة ToString ().
في الشكل 1 ، يشير الخط الذي يحمل علامة N أو P إلى أنه عندما يكون نوعين من البيانات متصلين بتنفيذ العملية == ، يجب على المعامل على الجانب N أو P أولاً إجراء التحول أو التحول العلوي.
3. صحيح وكاذب
كما يتضح من الشكل 1 ، عند مقارنة قيمة منطقية مع الأنواع الأخرى من القيم ، يتم تحويل القيمة المنطقية إلى رقم. خاصة
صحيح -> 1
خطأ -> 0
هذا لا يتطلب الكثير من الإساءة اللفظية على الإطلاق. فكر في الأمر ، في C ، لا يوجد نوع منطقي على الإطلاق. عادة ما يتم استخدام الأعداد الصحيحة 1 و 0 لتمثيل المنطق الحقيقي أو الخاطئ.
رابعا. تسلسل الشخصيات
في الشكل 1 ، نقسم السلسلة والرقم إلى مجموعة. لماذا؟ من بين الأنواع الستة ، السلسلة والرقم هي تسلسلات من الأحرف (على الأقل حرفيًا). السلسلة هي سلسلة من جميع الأحرف القانونية ، في حين يمكن اعتبار الرقم سلسلة من الأحرف التي تلبي شروطًا معينة. لذلك ، يمكن اعتبار الأرقام مجموعة فرعية من الأوتار.
وفقًا للشكل 1 ، عند إجراء == تشغيل السلاسل والأرقام ، تحتاج إلى استخدام عملية Tonumber لتحويل السلسلة إلى أرقام. على افتراض أن x عبارة عن سلسلة و y رقم ، ثم:
x == y -> الرقم (x) == y
إذن ما هي قاعدة تحويل السلاسل إلى أرقام؟ يتم وصف المواصفات بطريقة معقدة للغاية ، ولكن بشكل عام ، فإن إزالة الاقتباسات على جانبي السلسلة ومعرفة ما إذا كان يمكن أن يشكل رقمًا قانونيًا. إذا كان الأمر كذلك ، فإن نتيجة التحويل هي هذا الرقم ؛ خلاف ذلك ، والنتيجة هي نان. على سبيل المثال:
الرقم ('123') // النتيجة 123
الرقم ('1.2e3') // النتيجة 1200
الرقم ('123ABC') // النتيجة nan
بالطبع ، هناك استثناءات ، مثل نتيجة تحويل سلسلة فارغة إلى رقم 0.
الرقم ('') // النتيجة 0
خامسا بسيطة ومعقدة
الأنواع البدائية هي أنواع بسيطة ، فهي واضحة وسهلة الفهم. ومع ذلك ، فإن العيب هو أن قدرة التعبير محدودة ويصعب التوسع ، لذلك هناك كائنات. الكائن عبارة عن مجموعة من السمات ، ويمكن أن تكون السمة نفسها كائنًا. لذلك يمكن بناء الكائنات معقدة بشكل تعسفي بما يكفي لتمثيل أشياء مختلفة.
لكن في بعض الأحيان تكون الأمور معقدة وليست شيئًا جيدًا. على سبيل المثال ، ليس لدى كل شخص الوقت أو الصبر أو الحاجة إلى قراءته من البداية إلى النهاية. عادة ما يكون ذلك يكفي لفهم أفكاره المركزية فقط. لذلك تحتوي الورقة على كلمات رئيسية ووجهات عامة. وينطبق الشيء نفسه على الكائنات في جافا سكريبت. نحتاج إلى أن يكون لدينا وسيلة لفهم خصائصها الرئيسية ، وبالتالي فإن الكائنات لها طرق tostring () و valueof ().
يتم استخدام طريقة ToString () للحصول على وصف نص للكائن ؛ ويتم استخدام طريقة ValueOF () للحصول على القيمة الذاتية للكائن.
بالطبع ، هذا مجرد فهمي الخاص. أيضًا ، كما يوحي الاسم ، تميل طريقة ToString () إلى إرجاع السلسلة. ماذا عن طريقة قيمة ()؟ وفقًا للوصف في المواصفات ، فإنه يميل إلى إرجاع رقم - على الرغم من أنه في النوع المدمج ، فإن طريقة ValueOF () تُرجع الرقم والتاريخ فقط.
وفقًا للشكل 1 ، عندما تتم مقارنة كائن ما مع غير كائن ، يجب تحويل الكائن إلى نوع بدائي (على الرغم من أنه عند المقارنة مع نوع منطقي ، يجب تحويل النوع المنطقي إلى نوع رقمي أولاً ، ولكن يجب تحويل نوع الكائن إلى نوع بدائي بعد ذلك). هذا معقول أيضا. بعد كل شيء ، == ليست مقارنة صارمة. نحتاج فقط إلى إخراج الميزات الرئيسية للكائن للمشاركة في العملية ، ووضع الميزات الثانوية جانباً.
ستة. يتم حساب كل شيء
دعونا ننظر إلى الوراء في الشكل 1. لا توجد اتجاهات N أو P في الداخل. إذا وضعنا علامة على الأسهم على هذه السطور ، فإن نقاط الاتصال من النهاية تحمل علامة N أو P إلى الطرف الآخر ، فسنحصل (لن ندرس غير محددة و NULL):
هل اكتشفت أي شيء؟ نعم ، أثناء عملية الحساب ، تميل جميع أنواع القيم إلى التحويل إلى أنواع رقمية. بعد كل شيء ، قال أحد المشاهير ذات مرة:
يتم حساب كل شيء.
7. فقط أعطني الكستناء
هناك الكثير من الهراء في الماضي ، لذلك هنا مثال لإثبات أن الشكل 1 مناسب بالفعل وفعال لتوجيه الممارسة.
مثال ، احسب ما يلي:
[''] == خطأ
أولاً ، المعاملتين هما نوع الكائن ونوع منطقي على التوالي. وفقًا للشكل 1 ، من الضروري تحويل نوع Boolean إلى نوع رقمي ، ونتيجة تحويل False إلى Numeric هي 0 ، لذلك يصبح التعبير:
[''] == 0
تصبح المعاملين نوع الكائن ونوع الرقم. وفقًا للشكل 1 ، يجب تحويل نوع الكائن إلى النوع الأصلي:
أولا ، اتصل [] .valueof (). نظرًا لأن طريقة ValueOF () من الصفيف تُرجع نفسها ، فإن النتيجة ليست هي النوع الأصلي. استمر في الاتصال [] .ToString ().
بالنسبة للصفائف ، تتمثل خوارزمية طريقة ToString () في تحويل كل عنصر إلى نوع سلسلة ثم تسلسله بدوره بـ "،" ، وبالتالي فإن النتيجة النهائية هي سلسلة فارغة ، وهي قيمة للنوع الأصلي.
في هذه المرحلة ، يصبح التعبير:
'' == 0
تصبح المعاملتان أنواعًا من السلسلة وأنواع الرقمية. وفقًا للشكل 1 ، يجب تحويل نوع السلسلة إلى أنواع رقمية. كما ذكرنا سابقًا ، تصبح السلسلة الفارغة عددًا من 0. لذلك يصبح التعبير:
0 == 0
حتى الآن ، تكون أنواع المعاملتين متماثلة في النهاية ، والنتيجة صحيحة بشكل واضح.
من هذا المثال ، يمكننا أن نرى أنه من أجل إتقان قواعد التشغيل == ، بالإضافة إلى تذكر الشكل 1 ، نحتاج أيضًا إلى تذكر قواعد ToString () و Valueof () أساليب تلك الكائنات المدمجة. بما في ذلك الكائن ، الصفيف ، التاريخ ، الرقم ، السلسلة ، منطقية ، إلخ.
8. دعونا نلخص
البيان السابق مربك للغاية. هنا سألخص قواعد == العملية المعبر عنها في الشكل 1:
نتيجة غير محددة == فارغة صحيحة. نتيجة المقارنة مع جميع القيم الأخرى خاطئة.
عندما يتم تحويل سلسلة == ، يتم تحويل السلسلة إلى رقم.
القيمة المنطقية == عند استخدام أنواع أخرى ، يتم تحويل القيمة المنطقية إلى رقم.
عندما يكون كائن == رقمي/سلسلة ، يتم تحويل الكائن إلى نوع بدائي.
أخيرًا ، غيرت الصورة لتكون للترفيه فقط :)
حسنًا ، لقد انتهى الأمر. إذا كنت تعتقد أن هذه المقالة مفيدة لك ، فيرجى إعجابها حتى يتمكن المزيد من الناس من رؤيته.
بالإضافة إلى ذلك ، يرجى الإشارة إلى المغالطات في المقالة.