الرئيسيةمن أناالدوراتالمدونةسوق الأوامرالمناهج والباقاتالشركاء

دورات عربية متخصصة في التقنية والبرمجة والذكاء الاصطناعي.

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

المنصة

  • الرئيسية
  • من أنا
  • الدورات
  • المناهج والباقات
  • سوق الأوامر
  • المدونة

الدعم

  • الأسئلة الشائعة
  • تواصل معنا
  • سياسة الخصوصية
  • شروط استخدام التطبيق
  • سياسة الاسترجاع

© 2026 أحمد حايس. جميع الحقوق محفوظة.

الرئيسيةالدوراتالمناهجالمدونةالدخول
البرمجة بالعربي

الـ this في جافاسكريبت: ليه معناها بيتغيّر حسب مين اللي نادى الدالة

متوسط28 يوليو 20265 دقائق قراءة
الـ this في جافاسكريبت: ليه معناها بيتغيّر حسب مين اللي نادى الدالة

هذا المقال يتطلب مستوى متوسط. لو انت لسه بادئ في جافاسكريبت خالص، هتفهم المثال البسيط في الأول عادي، والجزء العلمي هيبقى مرجع ترجعله بعدين.

لو دالتك بتشتغل تمام لمّا تناديها لوحدها، وبتضرب undefined لمّا تحطها جوه setTimeout أو addEventListener، المشكلة مش في الدالة. المشكلة إن قيمة this اترمت وقت النداء. المقال ده هيوريك بالظبط إمتى بتضيع وإزاي تمسكها من غير ما تكسر باقي الكود.

الـ this في جافاسكريبت: قيمة بتتحدد وقت النداء مش وقت الكتابة

المشكلة باختصار

معظم اللغات بتربط الكلمة اللي زي this بالكلاس اللي اتكتبت جواه. جافاسكريبت لأ. هنا this قيمتها بتتحدد حسب إزاي ناديت الدالة، مش حسب فين عرّفتها. نفس الدالة ممكن تديك ثلاث قيم مختلفة لـ this حسب طريقة الاستدعاء. ده اللي بيخلّي مطورين شاطرين يقضّوا ساعات في باج، سببه سطر واحد نقل الدالة من مكان لمكان.

شاشة محرر كود تعرض دالة جافاسكريبت تستخدم الكلمة المفتاحية this داخل كائن

الفكرة بمثال بسيط قبل الكلام العلمي

تخيّل كلمة "أنا" في جملة. لو قلت "أنا جعان"، مين "أنا" دي؟ حسب مين اللي بيتكلم. نفس الكلمة بالظبط، بس معناها بيتغيّر حسب المتحدث اللي نطقها دلوقتي.

الـ this زيها بالظبط. مش اسم ثابت لحاجة معيّنة، ده ضمير بيشير لـ "المتحدث" وقت النداء. و"المتحدث" في جافاسكريبت هو الكائن اللي على شمال النقطة لحظة استدعاء الدالة. غيّر مين اللي بينده، هيتغيّر معنى this.

الشرح العلمي: قيمة this بتتحدد من موقع الاستدعاء

القاعدة الدقيقة: قيمة this بتتحسب من call-site، يعني الشكل اللي اتنادت بيه الدالة فعليًا. فيه أربع طرق ربط، بالأولوية دي:

  1. ربط عبر new: لو ناديت الدالة بـ new، this بتبقى الكائن الجديد.
  2. ربط صريح: لو استخدمت call أو apply أو bind، انت اللي بتحدد this بإيدك.
  3. ربط ضمني: لو ناديت الدالة كـ method بالشكل obj.fn()، this بتبقى obj.
  4. الربط الافتراضي: لو نادِتها لوحدها fn()، في الوضع الصارم this بتبقى undefined، وفي الوضع العادي بتبقى الكائن العام (window في المتصفح).

الافتراض هنا إننا بنتكلم عن الدوال العادية. الدوال السهمة (arrow) قصة تانية هنشرحها تحت.

الكود اللي بيوريك ضياع this بعينك

JavaScript
"use strict";

const user = {
  name: "أحمد",
  greet() {
    return `أهلاً يا ${this.name}`;
  }
};

console.log(user.greet());     // "أهلاً يا أحمد"  ← ربط ضمني، this = user

const sayHi = user.greet;      // نقلنا الدالة برّه الكائن
console.log(sayHi());          // TypeError: Cannot read properties of undefined
                               // this بقت undefined لأننا نادِناها لوحدها

لاحظ إن الدالة ماتغيرتش حرف. اللي اتغيّر هو طريقة النداء. أول مرة كانت user.greet()، تاني مرة بقت sayHi() من غير كائن على الشمال، فضاعت this.

سيناريو واقعي: الباج اللي بيظهر بعد ساعات

لو عندك واجهة فيها زرار وربطت الميثود مباشرة:

JavaScript
class Counter {
  constructor() { this.count = 0; }
  increment() { this.count++; console.log(this.count); }
}

const c = new Counter();
button.addEventListener("click", c.increment);  // غلط

لمّا يتضغط الزرار، المتصفح بينده increment والـ this بتبقى عنصر الـ DOM بتاع الزرار مش الكائن c. فـ this.count بتبقى undefined، وundefined++ بتطلع NaN. في الوضع العادي (مش strict) الوضع أخطر: this بتبقى window، فبتكتب على متغيّر عام من غير ما ترمي خطأ، والباج بيفضل مستخبّي.

الأرقام هنا مش عن السرعة، دي عن التكلفة الخفية: باج زي ده في لوحة فيها 30 معالج حدث ممكن ياكل نص يوم debugging، وكله سببه إن this اترمت في سطر ربط واحد.

الحل: bind أو الدالة السهمة

الدالة السهمة ماعندهاش this خاص بيها. بترث this من النطاق المحيط بيها وقت التعريف (lexical). ده بيحلّ مشكلة الـ callbacks بأناقة:

JavaScript
button.addEventListener("click", () => c.increment());  // this جوه increment = c

// أو التثبيت الصريح:
button.addEventListener("click", c.increment.bind(c));  // ثبّتنا this على c

الـ trade-offs: مش كل حل ببلاش

  • bind: بيثبّت this بشكل صريح وواضح، لكنه بيعمل دالة جديدة في كل استدعاء. لو حطيت this.method.bind(this) جوه دالة render بتتنفّذ مع كل إعادة رسم، وعندك قائمة 1000 عنصر، انت بتخلق 1000 دالة جديدة كل re-render. ثبّت الـ bind مرة واحدة في الـ constructor بدل ما تكرره.
  • الدالة السهمة: بترث this تلقائيًا، بس ماينفعش تستخدمها كـ method على prototype ولا كـ constructor بـ new، لأنها أصلًا ماعندهاش this خاص تربطه.

المقايضة باختصار: bind = تحكّم صريح مقابل دالة إضافية في الذاكرة. Arrow = راحة وربط تلقائي مقابل إنها مش صالحة لكل المواضع.

متى لا تشغّل بالك بـ this أصلًا

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

الخطوة التالية

افتح أقرب addEventListener أو setTimeout عندك، وبُصّ على الدالة اللي بتمرّرها. لو هي method من كائن ومتمرّرة بالاسم من غير .bind ولا لفّها في دالة سهمة، دي قنبلة موقوتة. صلّحها دلوقتي بواحد من الحلّين اللي فوق، وجرّب تطبع this جواها قبل وبعد التعديل عشان تشوف الفرق بعينك.

المصادر

  • MDN Web Docs — this: توثيق ربط this وقواعده. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this
  • MDN Web Docs — Arrow function expressions: سلوك this في الدوال السهمة. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions
  • ECMAScript Language Specification (ECMA-262): تعريف this والوضع الصارم رسميًا. tc39.es/ecma262
  • Kyle Simpson — You Don't Know JS: this & Object Prototypes: شرح قواعد الربط الأربعة بالتفصيل.

هل استفدت من المقال؟

اطّلع على المزيد من المقالات والدروس المجانية من نفس المسار المعرفي.

تصفّح المدونة