في 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! ← ورثها من person
JavaScript⚠️ تنبيه: استخدام
__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 Ali
JavaScriptp
يرث من 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 barks
JavaScript🧪 حالات مهمة ومفاهيم مرتبطة
🔍 ما الفرق بين __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 sound
JavaScript🔄 تغيير الـ Prototype بعد الإنشاء
let cat = {};
Object.setPrototypeOf(cat, animal);
cat.makeSound(); // Generic sound
JavaScript📉 مخاطر التلاعب بـ 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 Sara
JavaScriptخلف الكواليس، class
هو مجرد غلاف أنيق للـ prototype.
🧩 حالات تحتاج فهم عميق للـ prototype
- التحقق من الوراثة:
console.log(d instanceof Dog); // true
console.log(d instanceof Animal); // true
JavaScriptالتحقق من سلسلة prototype:
console.log(Object.getPrototypeOf(d) === Dog.prototype); // true
console.log(Object.getPrototypeOf(Dog.prototype) === Animal.prototype); // true
JavaScriptفهم constructor
:
console.log(d.constructor === Dog); // true
JavaScript✅ خلاصة:
Prototype
هو أساس الوراثة في JavaScript.- يمكنك استخدامه لتوفير الذاكرة وإنشاء هيكل وراثي.
- بالرغم من وجود
class
، يظل فهمprototype
ضروريًا لفهم كيف تعمل JavaScript فعليًا. - استخدامه بطريقة صحيحة يساعد على كتابة كود نظيف وفعال.