* على الأرجح ، فاتني شيء ما ، لكنني متأكد من أن التعليقات سوف تخبرني بذلكأكتب هذه المقالة لاحتياجاتي الشخصية. من المخطط أن يحتوي على إجابات لجميع الأسئلة التي يطرحها علي الطلاب حول هذا الموضوع. إذا كان من المفيد لشخص آخر - عظيم.
المحتوى.
- مقدمة
- مفاهيم خاطئة حول هذا الموضوع
- كيفية تحديد قيمة هذا
مقدمة
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
حجة إضافية "ناقص الأول" للوظيفة ، والتي يتم تمريرها هناك بطريقة معقدة وغير واضحة للمبتدئين. مع الاحتمال الكبير ، يمكن استبداله بالحجة المعتادة ، وسوف تتحسن فقط.
كيفية تحديد قيمة هذا
سأحاول هنا إعطاء خوارزمية صارمة وموجزة والتي حتى المبرمج عديم الخبرة سيكون قادرًا على فهم ما يساويها في حالته الخاصة. سيتم إخفاء المزيد من التفسيرات المطوّلة تحت المفسدين ، حتى لا يتم تجميع المساحة المرئية.
- هل نحن داخل وظيفة؟
- نعم: انظر البند التالي.
- لا:
this
يساوي كائن عالمي .
تعليقفي رمز المستوى الأعلى (ليس داخل أي وظيفة) ، يشير this
دائمًا إلى كائن عمومي. في حالة وجود برنامج نصي منتظم في المستعرض ، هذا كائن window
. ولكن بشكل عام ، هناك حالات مختلفة.
- هل نحن داخل وظيفة السهم؟
- نعم: قيمة
this
هي نفسها كما في الوظيفة أعلى مستوى واحد (أي تحتوي على هذا واحد). ارجع إلى الخطوة السابقة وكرر الخوارزمية لها. إذا لم تكن الوظيفة مضمنة في أي شيء آخر ، this
كائن عالمي. - لا: انظر الفقرة التالية.
تعليقواحدة من السمات الرئيسية لوظائف السهم هو ما يسمى " this
المعجمية". هذا يعني أن قيمة this
في دالة السهم يتم تحديدها فقط حسب المكان (في أي سياق معجمي) الذي تم إنشاؤه فيه ، ولا تعتمد على كيفية استدعاؤها لاحقًا. في بعض الأحيان ، هذا ليس ما نحتاج إليه ، ولكنه في كثير من الأحيان يجعل وظائف السهم مريحة للغاية ويمكن التنبؤ بها.
- هل تسمى هذه الوظيفة مُنشئ (باستخدام المشغل الجديد)؟
- نعم: يشير
this
إلى كائن جديد "قيد الإنشاء". - لا: انظر الفقرة التالية.
تعليقربما يستحق تحديد الحالة بشكل منفصل عندما يتعلق الأمر بمنشئ فئة ES6 الموروثة. بعد ذلك ، قبل الاتصال بـ super()
، لا تحتوي هذه القيمة على (الوصول إليها سيتسبب في حدوث خطأ) ، وبعد الاتصال بـ super()
تساوي الكائن الجديد للفئة الأصل.
- هل تم إنشاء هذه الوظيفة باستخدام الارتباط ؟
- نعم: قيمة
this
تساوي قيمة الوسيطة الأولى التي انتقلنا إلى طريقة bind
عند إنشاء هذه الوظيفة. - لا: انظر الفقرة التالية.
تعليقتنشئ طريقة bind
نسخة من الوظيفة ، وتصلحها ، واختياريا ، الوسيطات القليلة الأولى لها. في الواقع ، هذا يخلق ليس فقط نسخة من الوظيفة ، ولكن ، أقتبس ، "كائن BoundFunction الغريب". تتجلى الغرابة ، على وجه الخصوص ، في أنه من خلال الدعوة المتكررة bind
لم يعد بإمكاننا تغيير this
. لذلك ، بالمعنى الدقيق للكلمة ، ينبغي صياغة الإجابة في هذه الفقرة على النحو التالي: إذا كان الأمر كذلك ، this
يساوي الحجة الأولى للنداء الأول bind
، مما أدى إلى إنشاء هذه الوظيفة.
- هل تم تمرير هذه الوظيفة في مكان ما كرد اتصال أو معالج؟
- نعم: الرب وحده يعلم ما سوف يساوي هذا عند الاستدعاء. اذهب قراءة الوثائق عن الشيء الذي سوف يسبب ذلك.
- لا: انظر الفقرة التالية.
تعليقللدالة غير المرتبطة بالسهم والمنضم ، تعتمد قيمة
this
على الظروف التي تم استدعاؤها. إذا لم تقم بالاتصال بها شخصيًا ، ولكنك قمت بتمريرها في مكان ما ، فقد يتم استبدال
this
القيمة أو لا تكون بقيمة غير معروفة لك.
الأمثلة على ذلك:
`use strict` document.addEventListener('keydown', function(){ console.log(this); });
- وتسمى هذه الوظيفة باستخدام تطبيق أو الاتصال ؟
- نعم: في هذه الحالة ، يساوي
this
الوسيطة الأولى التي تم تمريرها إلى الطريقة المقابلة. - لا: انظر الفقرة التالية.
تعليقهناك طريقة أخرى لتعيين this
بوضوح. بتعبير أدق ، اثنان. ومع ذلك ، فيما يتعلق this
يوجد فرق بين apply
call
، والفرق الوحيد هو كيف يتم تمرير بقية الحجج.
- هل تم الحصول على هذه الوظيفة كقيمة خاصية كائن ويتم استدعاؤها على الفور؟
- نعم:
this
يساوي الكائن أعلاه. - لا: انظر الفقرة التالية.
تعليقفي الواقع ، من هذه الآلية (وكذلك من الخبرة في العمل مع لغات أخرى) تنمو الأرجل من الاعتقاد بأن "
this
هو الشيء الذي نسميه أسلوبه." ربما سأكتب الرمز فقط.
'use strict'; const object1 = { method: function(){ console.log(this); } } const object2 = { method: object1.method } object1.method();
- هل الشفرة تنفذ في وضع صارم؟ ("استخدام صارم" ، وحدة ES6)
- نعم:
this
يساوي undefined
. - لا:
this
يساوي كائن عالمي.
تعليقإذا وصلنا إلى هذه النقطة ، فلن
this
تحديد ذلك بواسطة أي من الآليات التي تسمح بتعيينها. هناك العديد من المفاهيم الخاطئة حول كيف يمكن تمرير ذلك. على سبيل المثال ، أثناء المقابلات ، يخبرونني شيئًا كهذا:
const obj = { test: function(){ (function(){ console.log(this); })();
أو ، كما قلت في قسم "المفاهيم الخاطئة" ، يعتقد الكثير من الناس أنه إذا كانت الوظيفة هي وسيلة لكائن تم إنشاؤه باستخدام فئات ES6 ، فسيكون هذا دائمًا مساويا لهذا الكائن فيه. هذا أيضا غير صحيح.
لذلك ، إذا وصلنا إلى هذه النقطة ، فإن الظروف الأخرى للاتصال بوظيفتنا لا تهم. والأمر كله يتعلق بما إذا كنا في وضع صارم أم لا.
تاريخيا ، ك "الافتراضي"
this
، تم تمرير كائن عمومي لمثل هذه الوظائف. تم التعرف على هذا النهج لاحقًا على أنه غير آمن. قدم ES5 وضعًا صارمًا يعمل على إصلاح العديد من مشكلات الإصدارات السابقة من ECMAScript. يتم تضمينه مع التوجيه "استخدام صارم" في بداية الملف أو الوظيفة. في هذا الوضع ، القيمة "الافتراضية"
this
غير
undefined
.
في الوحدات النمطية ES6 ، يتم تمكين الوضع الصارم افتراضيًا.
هناك أيضًا آليات أخرى لإدراج الوضع الصارم ، على سبيل المثال ، في NodeJS ، يمكن تمكين الوضع الصارم لجميع الملفات
--use-strict
.
هذا ، بشكل عام ، هو كل شيء. تحديد قيمة
this
، بطبيعة الحال ، أقل بساطة مما نود ، لكنه ليس بالأمر الصعب الذي قد يبدو. تعلم هذه الخوارزمية كجدول للضرب - ولن تواجه أي مشاكل مع
this
مرة أخرى. مثل هذه الأشياء.
اقترح PS User
Aingis أنه عند استخدام
العلامة with ، فإن الكائن الذي تم تمريره إليها كسياق يحل محل الكائن العمومي. ربما لن أدخل هذا في المصنف الخاص بي ، لأن فرصة الالتقاء
with
في 2019+ صغيرة جدًا. ولكن على أي حال ، هذه نقطة مثيرة للاهتمام.
اقترح مستخدم PPS
rqrqrqrq أن الأولوية
new
أعلى من
bind
. تم إجراء المراجعة المناظرة للمصنف. شكرا لك