| العنصر | الوظيفة |
|---|---|
| class | تعريف فئة جديدة |
| constructor() | دالة تهيئة تُستدعى تلقائياً مع new |
| method() | دالة متاحة لكل كائن من الفئة |
| static method() | دالة تنتمي للفئة نفسها وليس لكائن |
الفئات (Classes) هي صيغة أُضيفت في ES6 توفر طريقة أنظف وأوضح لإنشاء الكائنات وتنظيم الكود كائني التوجه، وكما ذكرنا هي مبنية فعلياً فوق نظام الـ Prototype الذي سبقها. تُعرَّف الفئة بالكلمة المفتاحية class متبوعة باسم يبدأ عادة بحرف كبير حسب الاصطلاح البرمجي (Naming Convention).
كل فئة تحتوي دالة خاصة تُسمى constructor، وتُستدعى تلقائياً عند إنشاء كائن جديد من الفئة عبر الكلمة المفتاحية new. مهمة constructor الأساسية هي تهيئة خصائص الكائن الجديد (Instance) بالقيم الممرَّرة إليه. أي دوال أخرى تُعرَّف داخل الفئة (خارج constructor) تُصبح تلقائياً "أساليب" (Methods) متاحة لكل كائن يُنشأ من هذه الفئة، وتُخزَّن فعلياً في الـ Prototype خلف الكواليس تماماً كما تعلمنا في الموضوع السابق.
يمكن أيضاً تعريف خصائص وأساليب "ثابتة" (Static) باستخدام الكلمة المفتاحية static — وهذه لا تنتمي لأي كائن فردي مُنشأ من الفئة، بل تنتمي للفئة نفسها ويُستدعى مباشرة عبر اسم الفئة، وتُستخدم عادة لدوال مساعدة (Utility Functions) مرتبطة منطقياً بالفئة لكن لا تحتاج بيانات كائن محدد.
من الأخطاء الشائعة عند المبتدئين نسيان الكلمة المفتاحية new عند إنشاء كائن من فئة — في الوضع الصارم (Strict Mode) الذي تعمل به الفئات تلقائياً، هذا يرمي خطأ صريحاً بدلاً من التصرف بشكل غير متوقع كما كان يحدث مع الدوال البانية القديمة.
| 1 | class شخص { |
| 2 | constructor(اسم, عمر) { |
| 3 | this.اسم = اسم; |
| 4 | this.عمر = عمر; |
| 5 | } |
| 6 | |
| 7 | يقدم_نفسه() { |
| 8 | return `أنا ${this.اسم} وعمري ${this.عمر}`; |
| 9 | } |
| 10 | |
| 11 | static من_كائن(بيانات) { |
| 12 | return new شخص(بيانات.اسم, بيانات.عمر); |
| 13 | } |
| 14 | } |
| 15 | |
| 16 | const ص = new شخص("سارة", 30); |
| 17 | console.log(ص.يقدم_نفسه()); |
مثال 1: فئة حساب بنكي كاملة مع أساليب
| 1 | class حساب_بنكي { |
| 2 | constructor(صاحب_الحساب, رصيد_ابتدائي = 0) { |
| 3 | this.صاحب_الحساب = صاحب_الحساب; |
| 4 | this.الرصيد = رصيد_ابتدائي; |
| 5 | } |
| 6 | |
| 7 | إيداع(مبلغ) { |
| 8 | this.الرصيد += مبلغ; |
| 9 | return this.الرصيد; |
| 10 | } |
| 11 | |
| 12 | سحب(مبلغ) { |
| 13 | if (مبلغ > this.الرصيد) { |
| 14 | console.log("رصيد غير كافٍ"); |
| 15 | return this.الرصيد; |
| 16 | } |
| 17 | this.الرصيد -= مبلغ; |
| 18 | return this.الرصيد; |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | const حساب1 = new حساب_بنكي("خالد", 1000); |
| 23 | حساب1.إيداع(500); |
| 24 | console.log(حساب1.سحب(2000)); // "رصيد غير كافٍ"، ثم 1500 |
مثال 2: الأساليب الثابتة (Static Methods)
| 1 | // أسلوب ثابت (Static) لا يحتاج كائناً فردياً |
| 2 | class أدوات_رياضية { |
| 3 | static جمع(أ, ب) { |
| 4 | return أ + ب; |
| 5 | } |
| 6 | static مربع(رقم) { |
| 7 | return رقم * رقم; |
| 8 | } |
| 9 | } |
| 10 | |
| 11 | // يُستدعى مباشرة على الفئة، لا على كائن |
| 12 | console.log(أدوات_رياضية.جمع(3, 4)); // 7 |
| 13 | console.log(أدوات_رياضية.مربع(5)); // 25 |