| طريقة الاستدعاء | قيمة this |
|---|---|
| كائن.دالة() | الكائن نفسه |
| دالة() بمفردها | undefined (strict) أو window |
| new دالة() | الكائن الجديد قيد الإنشاء |
| دالة.call/apply/bind(كائن) | الكائن المُحدَّد يدوياً |
| دالة سهمية => | موروثة من السياق المحيط عند التعريف |
this هي واحدة من أكثر المفاهيم إرباكاً للمبتدئين في جافاسكريبت، لأن قيمتها لا تُحدَّد عند تعريف الدالة، بل تُحدَّد ديناميكياً حسب "كيفية استدعاء" الدالة فعلياً — وهذا يختلف جذرياً عن لغات أخرى حيث this ثابتة السلوك.
توجد أربع قواعد أساسية تُحدد قيمة this: أولاً، عندما تُستدعى دالة كأسلوب على كائن (كائن.دالة())، تُشير this إلى ذلك الكائن نفسه. ثانياً، عندما تُستدعى الدالة بمفردها دون كائن (دالة())، تُشير this إلى undefined في الوضع الصارم (Strict Mode) الذي تعمل به الفئات والوحدات (Modules) تلقائياً، أو إلى الكائن العام window في المتصفح في الوضع غير الصارم.
ثالثاً، عند استخدام new مع دالة بانية أو فئة، تُشير this إلى الكائن الجديد الذي يجري إنشاؤه حالياً. رابعاً، يمكنك التحكم اليدوي الصريح في قيمة this عبر call() أو apply() أو bind() — الثلاثة تسمح بتحديد قيمة this يدوياً بغض النظر عن كيفية الاستدعاء الطبيعية، مع فرق: call وapply تستدعيان الدالة فوراً (بفرق طريقة تمرير الوسائط)، بينما bind تُعيد دالة جديدة مربوطة بـ this محدد يمكن استدعاؤها لاحقاً.
كما تعلمنا سابقاً، الدوال السهمية (Arrow Functions) استثناء مهم من كل هذه القواعد الأربع — فهي لا تملك this خاصاً بها إطلاقاً، بل ترث قيمته من السياق المحيط بها وقت التعريف (وليس وقت الاستدعاء). هذا يجعلها الحل المثالي لمشكلة شائعة جداً: فقدان قيمة this الصحيحة داخل دوال Callback المُمرَّرة لدوال مثل setTimeout أو addEventListener عند الحاجة للوصول لـ this الخاص بكائن خارجي.
| 1 | const شخص = { |
| 2 | اسم: "علي", |
| 3 | تحية: function () { |
| 4 | console.log(this.اسم); // this = شخص هنا |
| 5 | }, |
| 6 | }; |
| 7 | شخص.تحية(); // "علي" |
| 8 | |
| 9 | function دالة_عادية() { console.log(this); } |
| 10 | dالة_عادية(); // undefined (strict mode) أو window |
| 11 | |
| 12 | const مربوطة = دالة_عادية.bind(شخص); |
| 13 | مربوطة(); // this أصبحت شخص يدوياً |
مثال 1: مشكلة this الشهيرة وحلها بالدالة السهمية
| 1 | // مشكلة this الشائعة داخل callback واستخدام arrow function لحلها |
| 2 | const مؤقت = { |
| 3 | ثواني: 0, |
| 4 | ابدأ_خاطئ: function () { |
| 5 | setInterval(function () { |
| 6 | this.ثواني++; // ❌ this هنا ليست مؤقت! تُسبب خطأ أو NaN |
| 7 | }, 1000); |
| 8 | }, |
| 9 | ابدأ_صحيح: function () { |
| 10 | setInterval(() => { |
| 11 | this.ثواني++; // ✅ الدالة السهمية ترث this من ابدأ_صحيح |
| 12 | console.log(this.ثواني); |
| 13 | }, 1000); |
| 14 | }, |
| 15 | }; |
مثال 2: الفرق بين call و apply و bind
| 1 | // الفرق بين call, apply, bind |
| 2 | function تقديم(مدينة) { |
| 3 | console.log(`أنا ${this.اسم} من ${مدينة}`); |
| 4 | } |
| 5 | const شخص = { اسم: "ريم" }; |
| 6 | |
| 7 | تقديم.call(شخص, "القاهرة"); // استدعاء فوري، وسائط منفصلة |
| 8 | تقديم.apply(شخص, ["القاهرة"]); // استدعاء فوري، وسائط كمصفوفة |
| 9 | const مقدمة_ريم = تقديم.bind(شخص); // يُعيد دالة جديدة، لا تُستدعى فوراً |
| 10 | مقدمة_ريم("القاهرة"); |