| المفهوم | التعريف |
|---|---|
| Prototype | كائن يحتوي خصائص ودوال يرثها كائن آخر |
| Prototype Chain | سلسلة البحث عن خاصية عبر عدة مستويات Prototype |
| Constructor Function | دالة تُستخدم مع new لإنشاء كائنات |
الـ Prototype هو الآلية الأساسية التي تُطبّق بها جافاسكريبت الوراثة (Inheritance)، وهي تختلف جوهرياً عن نموذج الوراثة الكلاسيكي في لغات مثل Java أو C++. بدلاً من "الفئات" (Classes) الصارمة، تعتمد جافاسكريبت على مفهوم "الوراثة النموذجية" (Prototypal Inheritance) — كل كائن في جافاسكريبت مرتبط بكائن آخر يُسمى Prototype الخاص به، ويمكنه "استعارة" خصائصه ودواله منه.
عندما تحاول الوصول لخاصية أو دالة على كائن ولا تجدها مباشرة عليه، لا يتوقف محرك جافاسكريبت هناك — بل يبحث في الـ Prototype الخاص بذلك الكائن، فإن لم يجدها هناك أيضاً، يبحث في Prototype الخاص بذلك الـ Prototype، وهكذا صعوداً حتى يصل إلى null. تُسمى هذه السلسلة "سلسلة الـ Prototype" (Prototype Chain)، وهي السبب في أن كل المصفوفات مثلاً "ترث" دوالاً جاهزة مثل map وfilter، رغم أنك لم تُعرّفها بنفسك في كل مصفوفة تُنشئها.
كل دالة في جافاسكريبت (عند استخدامها كدالة بانية Constructor) تمتلك خاصية تلقائية تُسمى prototype، ويمكنك إضافة دوال عليها لتُصبح متاحة لكل الكائنات التي تُنشأ من تلك الدالة البانية عبر new — وهذا يُوفر الذاكرة بشكل كبير، لأن الدالة تُخزَّن مرة واحدة فقط في الـ Prototype، بدل تكرارها في كل كائن على حدة.
في الكود الحديث، نادراً ما تتعامل مع الـ Prototype مباشرة بهذا الشكل، لأن صيغة Classes الأحدث (وهي التي سنتعلمها في الموضوع التالي) توفر واجهة أنظف وأسهل قراءة لنفس الآلية الأساسية تماماً — فالـ Classes في جافاسكريبت ما هي في جوهرها إلا "غلاف تجميلي" (Syntactic Sugar) فوق نظام الـ Prototype، وليست نظام وراثة كلاسيكي حقيقي جديد كلياً.
| 1 | function شخص(اسم) { |
| 2 | this.اسم = اسم; |
| 3 | } |
| 4 | |
| 5 | // إضافة دالة على الـ Prototype (تُشارك بين كل الكائنات) |
| 6 | شخص.prototype.يقول_مرحبا = function () { |
| 7 | return `مرحباً، أنا ${this.اسم}`; |
| 8 | }; |
| 9 | |
| 10 | const ص1 = new شخص("أحمد"); |
| 11 | console.log(ص1.يقول_مرحبا()); // "مرحباً، أنا أحمد" |
مثال 1: سلسلة الـ Prototype للمصفوفات
| 1 | // كل المصفوفات "ترث" دوالها من Array.prototype |
| 2 | const مصفوفة = [1, 2, 3]; |
| 3 | console.log(مصفوفة.__proto__ === Array.prototype); // true |
| 4 | |
| 5 | // يمكنك رؤية سلسلة الـ Prototype |
| 6 | console.log(Array.prototype.__proto__ === Object.prototype); // true |
| 7 | console.log(Object.prototype.__proto__); // null — نهاية السلسلة |
مثال 2: مشاركة الدوال عبر Prototype لتوفير الذاكرة
| 1 | // توفير الذاكرة: الدالة تُخزَّن مرة واحدة في prototype فقط |
| 2 | function سيارة(الموديل) { |
| 3 | this.الموديل = الموديل; |
| 4 | } |
| 5 | سيارة.prototype.وصف = function () { |
| 6 | return `سيارة موديل ${this.الموديل}`; |
| 7 | }; |
| 8 | |
| 9 | const س1 = new سيارة("2024"); |
| 10 | const س2 = new سيارة("2025"); |
| 11 | console.log(س1.وصف === س2.وصف); // true — نفس الدالة بالضبط، غير مكررة |