في JavaScript، مفهوم Prototype (النموذج الأولي) هو أحد أهم المفاهيم في البرمجة الكائنية التوجه (OOP) في هذه اللغة، ويُعد حجر الأساس لنظام الوراثة فيها.
🧠 ما هو Prototype في JavaScript؟
في JavaScript، كل كائن (object) له خاصية داخلية تُسمى [[Prototype]]. يمكنك الوصول إليها (بطريقة غير رسمية) باستخدام خاصية __proto__، أو (بطريقة رسمية) باستخدام Object.getPrototypeOf(obj).
الـ prototype هو كائن يُستخدم كقالب (template) للكائنات الأخرى لوراثة خصائصه ودواله.
🏗️ الوراثة باستخدام Prototype
عندما تبحث عن خاصية في كائن ولم تجدها، يبحث JavaScript تلقائيًا في كائن الـ prototype المرتبط به، وهكذا حتى يصل إلى نهاية السلسلة (null).
let person = {
greet() {
console.log("Hello!");
}
};
let student = {
study() {
console.log("Studying...");
}
};
// ربط student بـ person
student.__proto__ = person;
student.study(); // Studying...
student.greet(); // Hello! ← ورثها من personJavaScript⚠️ تنبيه: استخدام
__proto__غير مستحسن في المشاريع الحقيقية. يُفضل استخدامObject.create()أوObject.setPrototypeOf().
🔄 إنشاء الوراثة باستخدام الدوال البنائية (Constructor Functions)
function Person(name) {
this.name = name;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}`);
};
let p = new Person("Ali");
p.sayHello(); // Hello, my name is AliJavaScriptp يرث من Person.prototype
📦 فوائد واستخدامات prototype✅
توفير الذاكرة
بدلاً من إنشاء نسخة من نفس الدالة لكل كائن، يمكن وضع الدالة في prototype ليتم مشاركتها بين كل النسخ.
function Car(model) {
this.model = model;
}
Car.prototype.drive = function() {
console.log(`${this.model} is driving`);
};
let c1 = new Car("Toyota");
let c2 = new Car("Honda");
console.log(c1.drive === c2.drive); // true ✅JavaScript✅ إنشاء سلاسل وراثة
يمكنك بناء سلسلة وراثة معقدة:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a noise`);
};
function Dog(name) {
Animal.call(this, name);
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
console.log(`${this.name} barks`);
};
let d = new Dog("Rex");
d.speak(); // Rex makes a noise
d.bark(); // Rex barksJavaScript🧪 حالات مهمة ومفاهيم مرتبطة
🔍 ما الفرق بين __proto__ و prototype؟
| العنصر | المعنى |
|---|---|
obj.__proto__ | يشير إلى prototype الذي يرث منه الكائن |
Func.prototype | الكائن الذي سيتم استخدامه كـ prototype لأي كائن يتم إنشاؤه بهذه الدالة |
❓ ما هو Object.create()؟
ينشئ كائن جديد ويربطه بكائن موجود كـ prototype.
let animal = {
makeSound() {
console.log("Generic sound");
}
};
let dog = Object.create(animal);
dog.makeSound(); // Generic soundJavaScript🔄 تغيير الـ Prototype بعد الإنشاء
let cat = {};
Object.setPrototypeOf(cat, animal);
cat.makeSound(); // Generic soundJavaScript📉 مخاطر التلاعب بـ prototype
- يمكن أن يؤدي إلى تعقيد في تتبع الأخطاء.
- يجعل الكود أقل وضوحًا.
- التلاعب بـ
Object.prototypeيؤثر على كل الكائنات، وقد يسبب مشاكل:
Object.prototype.sayHi = function() {
console.log("Hi from Object");
};
let x = {};
x.sayHi(); // Hi from Object ← خطير!JavaScript📚 ملخص الفوائد
| الفائدة | التوضيح |
|---|---|
| تقليل استهلاك الذاكرة | تشارك الدوال عبر جميع النسخ |
| دعم الوراثة | بدون الحاجة للفئات |
| التحكم الكامل في السلسلة | يمكن ربط prototype يدوياً أو باستخدام دوال |
🎯 استخدامات شائعة
- بناء نماذج كائنية قبل ظهور
class. - إضافة دوال إلى كائنات أنشأتها دوال بنائية.
- إنشاء مكتبات خفيفة دون
class. - تعزيز الكائنات بميزات إضافية دون تعديلها مباشرة.
🆕 استخدام class (واجهة أحدث للـ prototype)
class Person {
constructor(name) {
this.name = name;
}
greet() {
console.log(`Hi, I'm ${this.name}`);
}
}
let p = new Person("Sara");
p.greet(); // Hi, I'm SaraJavaScriptخلف الكواليس، class هو مجرد غلاف أنيق للـ prototype.
🧩 حالات تحتاج فهم عميق للـ prototype
- التحقق من الوراثة:
console.log(d instanceof Dog); // true
console.log(d instanceof Animal); // trueJavaScriptالتحقق من سلسلة prototype:
console.log(Object.getPrototypeOf(d) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // trueJavaScriptفهم constructor:
console.log(d.constructor === Dog); // trueJavaScript✅ خلاصة:
Prototypeهو أساس الوراثة في JavaScript.- يمكنك استخدامه لتوفير الذاكرة وإنشاء هيكل وراثي.
- بالرغم من وجود
class، يظل فهمprototypeضروريًا لفهم كيف تعمل JavaScript فعليًا. - استخدامه بطريقة صحيحة يساعد على كتابة كود نظيف وفعال.