هذه الكلمة الأساسية في JavaScript. كامل * دليل

* على الأرجح ، فاتني شيء ما ، لكنني متأكد من أن التعليقات سوف تخبرني بذلك

أكتب هذه المقالة لاحتياجاتي الشخصية. من المخطط أن يحتوي على إجابات لجميع الأسئلة التي يطرحها علي الطلاب حول هذا الموضوع. إذا كان من المفيد لشخص آخر - عظيم.

صورة

المحتوى.

  1. مقدمة
  2. مفاهيم خاطئة حول هذا الموضوع
  3. كيفية تحديد قيمة هذا

مقدمة


this هي واحدة من أكثر السمات المحيرة للغة JavaScript. قادمة من Java ، كان الغرض منه المساعدة في تنفيذ OOP. لقد كتبت في جافا لبعض الوقت ، ويجب أن أقول أنه خلال هذا الوقت ، ربما شككت ذات مرة في ما يعادل this في مكان معين في الشفرة. في JavaScript ، يمكن أن تنشأ هذه الشكوك يوميًا - على الأقل حتى اللحظة التي تتعلم فيها بعض القواعد البسيطة ولكن غير الواضحة.

مفاهيم خاطئة حول this


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

هذا سياق معجمي.

هذا الانطباع غالبا ما ينشأ بين المبتدئين. يبدو لهم أن this هو الكائن الذي ، مثل الخصائص ، يتم تخزين جميع المتغيرات في هذا النطاق. ينبع هذا المفهوم الخاطئ من حقيقة أنه في حالة واحدة معينة ، بشكل تقريبي ، يكون هذا صحيحًا. إذا كنا على أعلى مستوى ، فعندئذٍ تساوي this window (في حالة وجود نص عادي في المتصفح). وكما نعلم ، تتوفر جميع المتغيرات المعلنة في المستوى العلوي كخصائص window .

بشكل عام ، هذا غير صحيح. هذا سهل التحقق.

 function test(){ const a = "     ,   "; console.log(this.a); } test(); //  ,    

هذا هو الكائن الذي تنتمي إليه الطريقة

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

 const f = function(){ console.log(this); } const object1 = { method: f }; const object2 = { method: f }; 

لذلك أي من هذه الأشياء سوف يكون لها هذا؟

! المهم حتى إذا تم إنشاء كائن باستخدام فئات ES6 ، فإن هذا لا يضمن على الإطلاق أن طريقته ستحتوي دائمًا على this . لا تنخدع بالتشابه مع الفصول الدراسية من اللغات "العادية".

هذه هي تقنية Jedi ، بمجرد تعلمها ، يجب استخدامها في كل مكان

من الأفضل تجنب استخدام this إن أمكن. الحالة الوحيدة عندما تكون مبررة تمامًا هي OOP. في مكان آخر ، استخدام this ليس مجرد شر ، ولكن عادةً مبالغة تربك الشفرة. في جوهرها ، this حجة إضافية "ناقص الأول" للوظيفة ، والتي يتم تمريرها هناك بطريقة معقدة وغير واضحة للمبتدئين. مع الاحتمال الكبير ، يمكن استبداله بالحجة المعتادة ، وسوف تتحسن فقط.

كيفية تحديد قيمة هذا


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

  1. هل نحن داخل وظيفة؟


    تعليق
    في رمز المستوى الأعلى (ليس داخل أي وظيفة) ، يشير this دائمًا إلى كائن عمومي. في حالة وجود برنامج نصي منتظم في المستعرض ، هذا كائن window . ولكن بشكل عام ، هناك حالات مختلفة.
  2. هل نحن داخل وظيفة السهم؟

    • نعم: قيمة this هي نفسها كما في الوظيفة أعلى مستوى واحد (أي تحتوي على هذا واحد). ارجع إلى الخطوة السابقة وكرر الخوارزمية لها. إذا لم تكن الوظيفة مضمنة في أي شيء آخر ، this كائن عالمي.
    • لا: انظر الفقرة التالية.

    تعليق
    واحدة من السمات الرئيسية لوظائف السهم هو ما يسمى " this المعجمية". هذا يعني أن قيمة this في دالة السهم يتم تحديدها فقط حسب المكان (في أي سياق معجمي) الذي تم إنشاؤه فيه ، ولا تعتمد على كيفية استدعاؤها لاحقًا. في بعض الأحيان ، هذا ليس ما نحتاج إليه ، ولكنه في كثير من الأحيان يجعل وظائف السهم مريحة للغاية ويمكن التنبؤ بها.
  3. هل تسمى هذه الوظيفة مُنشئ (باستخدام المشغل الجديد)؟

    • نعم: يشير this إلى كائن جديد "قيد الإنشاء".
    • لا: انظر الفقرة التالية.

    تعليق
    ربما يستحق تحديد الحالة بشكل منفصل عندما يتعلق الأمر بمنشئ فئة ES6 الموروثة. بعد ذلك ، قبل الاتصال بـ super() ، لا تحتوي هذه القيمة على (الوصول إليها سيتسبب في حدوث خطأ) ، وبعد الاتصال بـ super() تساوي الكائن الجديد للفئة الأصل.
  4. هل تم إنشاء هذه الوظيفة باستخدام الارتباط ؟

    • نعم: قيمة this تساوي قيمة الوسيطة الأولى التي انتقلنا إلى طريقة bind عند إنشاء هذه الوظيفة.
    • لا: انظر الفقرة التالية.

    تعليق
    تنشئ طريقة bind نسخة من الوظيفة ، وتصلحها ، واختياريا ، الوسيطات القليلة الأولى لها. في الواقع ، هذا يخلق ليس فقط نسخة من الوظيفة ، ولكن ، أقتبس ، "كائن BoundFunction الغريب". تتجلى الغرابة ، على وجه الخصوص ، في أنه من خلال الدعوة المتكررة bind لم يعد بإمكاننا تغيير this . لذلك ، بالمعنى الدقيق للكلمة ، ينبغي صياغة الإجابة في هذه الفقرة على النحو التالي: إذا كان الأمر كذلك ، this يساوي الحجة الأولى للنداء الأول bind ، مما أدى إلى إنشاء هذه الوظيفة.
  5. هل تم تمرير هذه الوظيفة في مكان ما كرد اتصال أو معالج؟

    • نعم: الرب وحده يعلم ما سوف يساوي هذا عند الاستدعاء. اذهب قراءة الوثائق عن الشيء الذي سوف يسبب ذلك.
    • لا: انظر الفقرة التالية.

    تعليق
    للدالة غير المرتبطة بالسهم والمنضم ، تعتمد قيمة this على الظروف التي تم استدعاؤها. إذا لم تقم بالاتصال بها شخصيًا ، ولكنك قمت بتمريرها في مكان ما ، فقد يتم استبدال this القيمة أو لا تكون بقيمة غير معروفة لك.

    الأمثلة على ذلك:

     `use strict` document.addEventListener('keydown', function(){ console.log(this); }); //    this === document.    DOM- this  currentTarget [1, 2, 3].forEach(function(){ console.log(this); }); //         ,  undefined. ?     . 
  6. وتسمى هذه الوظيفة باستخدام تطبيق أو الاتصال ؟

    • نعم: في هذه الحالة ، يساوي this الوسيطة الأولى التي تم تمريرها إلى الطريقة المقابلة.
    • لا: انظر الفقرة التالية.

    تعليق
    هناك طريقة أخرى لتعيين this بوضوح. بتعبير أدق ، اثنان. ومع ذلك ، فيما يتعلق this يوجد فرق بين apply call ، والفرق الوحيد هو كيف يتم تمرير بقية الحجج.
  7. هل تم الحصول على هذه الوظيفة كقيمة خاصية كائن ويتم استدعاؤها على الفور؟

    • نعم: this يساوي الكائن أعلاه.
    • لا: انظر الفقرة التالية.

    تعليق
    في الواقع ، من هذه الآلية (وكذلك من الخبرة في العمل مع لغات أخرى) تنمو الأرجل من الاعتقاد بأن " this هو الشيء الذي نسميه أسلوبه." ربما سأكتب الرمز فقط.

     'use strict'; const object1 = { method: function(){ console.log(this); } } const object2 = { method: object1.method } object1.method(); //    object1 -           object1['method'](); //  .        object2.method(); //    object2 -  " ",      ,         
  8. هل الشفرة تنفذ في وضع صارم؟ ("استخدام صارم" ، وحدة ES6)

    • نعم: this يساوي undefined .
    • لا: this يساوي كائن عالمي.

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

     const obj = { test: function(){ (function(){ console.log(this); })(); //      } } obj.test(); //  ,     obj.   

    أو ، كما قلت في قسم "المفاهيم الخاطئة" ، يعتقد الكثير من الناس أنه إذا كانت الوظيفة هي وسيلة لكائن تم إنشاؤه باستخدام فئات ES6 ، فسيكون هذا دائمًا مساويا لهذا الكائن فيه. هذا أيضا غير صحيح.

    لذلك ، إذا وصلنا إلى هذه النقطة ، فإن الظروف الأخرى للاتصال بوظيفتنا لا تهم. والأمر كله يتعلق بما إذا كنا في وضع صارم أم لا.

    تاريخيا ، ك "الافتراضي" this ، تم تمرير كائن عمومي لمثل هذه الوظائف. تم التعرف على هذا النهج لاحقًا على أنه غير آمن. قدم ES5 وضعًا صارمًا يعمل على إصلاح العديد من مشكلات الإصدارات السابقة من ECMAScript. يتم تضمينه مع التوجيه "استخدام صارم" في بداية الملف أو الوظيفة. في هذا الوضع ، القيمة "الافتراضية" this غير undefined .

    في الوحدات النمطية ES6 ، يتم تمكين الوضع الصارم افتراضيًا.

    هناك أيضًا آليات أخرى لإدراج الوضع الصارم ، على سبيل المثال ، في NodeJS ، يمكن تمكين الوضع الصارم لجميع الملفات --use-strict .


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

اقترح PS User Aingis أنه عند استخدام العلامة with ، فإن الكائن الذي تم تمريره إليها كسياق يحل محل الكائن العمومي. ربما لن أدخل هذا في المصنف الخاص بي ، لأن فرصة الالتقاء with في 2019+ صغيرة جدًا. ولكن على أي حال ، هذه نقطة مثيرة للاهتمام.

اقترح مستخدم PPS rqrqrqrq أن الأولوية new أعلى من bind . تم إجراء المراجعة المناظرة للمصنف. شكرا لك

Source: https://habr.com/ru/post/ar464163/


All Articles