| المفهوم | الصيغة | الحماية |
|---|---|---|
| اصطلاح قديم | _اسم | وهمية (اتفاق فقط) |
| حقل خاص حقيقي | #اسم | فعلية على مستوى اللغة |
| Getter | get اسم() {} | قراءة بواجهة بسيطة |
| Setter | set اسم(قيمة) {} | كتابة مع تحقق من الصحة |
الكبسلة (Encapsulation) هي أحد أهم مبادئ البرمجة كائنية التوجه، وتعني إخفاء التفاصيل الداخلية لكائن ما وعدم السماح بالوصول المباشر لها من خارج الفئة، والسماح فقط بالتفاعل معها عبر أساليب (Methods) محددة ومُتحكَّم بها. الهدف هو حماية بيانات الكائن من التعديل غير المقصود أو غير الصحيح من خارج الفئة.
لسنوات طويلة، لم تمتلك جافاسكريبت آلية حقيقية لإخفاء الخصائص — كان المطورون يعتمدون على اصطلاح غير مُلزم (وليس حماية فعلية) بإضافة شرطة سفلية _ في بداية اسم الخاصية (مثل _رصيد) للإشارة أنها "خاصة نظرياً"، لكن هذا لم يمنع أي أحد من الوصول إليها فعلياً من خارج الفئة إن أراد.
مع الإصدارات الحديثة من جافاسكريبت (ES2022 وما بعده)، أصبح ممكناً تعريف حقول خاصة حقيقية (True Private Fields) باستخدام رمز # قبل اسم الخاصية أو الأسلوب. أي محاولة للوصول لهذه الحقول من خارج الفئة تُنتج خطأ صريحاً فوراً — حماية فعلية على مستوى اللغة نفسها، وليست مجرد اصطلاح تسمية.
من الأنماط الشائعة جداً مع الحقول الخاصة استخدام "Getters" و"Setters" — أساليب خاصة تُستخدم بصيغة كأنها خاصية عادية (بدون أقواس عند الاستدعاء) لكنها تُنفّذ منطقاً مخصصاً عند القراءة (get) أو الكتابة (set). هذا يسمح مثلاً بالتحقق من صحة قيمة قبل تعيينها فعلياً للحقل الخاص، مع الحفاظ على واجهة استخدام بسيطة ونظيفة للمستخدمين الخارجيين للفئة.
| 1 | class حساب_بنكي { |
| 2 | #رصيد; // حقل خاص حقيقي |
| 3 | |
| 4 | constructor(رصيد_ابتدائي) { |
| 5 | this.#رصيد = رصيد_ابتدائي; |
| 6 | } |
| 7 | |
| 8 | get الرصيد() { |
| 9 | return this.#رصيد; |
| 10 | } |
| 11 | |
| 12 | إيداع(مبلغ) { |
| 13 | if (مبلغ > 0) this.#رصيد += مبلغ; |
| 14 | } |
| 15 | } |
| 16 | |
| 17 | const ح = new حساب_بنكي(1000); |
| 18 | console.log(ح.الرصيد); // 1000 عبر getter |
| 19 | // console.log(ح.#رصيد); // ❌ خطأ: خاص تماماً |
مثال 1: Getter و Setter مع تحقق من صحة القيمة
| 1 | // Getter و Setter مع تحقق من الصحة |
| 2 | class منتج { |
| 3 | #سعر; |
| 4 | |
| 5 | constructor(اسم, سعر) { |
| 6 | this.اسم = اسم; |
| 7 | this.سعر = سعر; // يستدعي الـ setter تلقائياً |
| 8 | } |
| 9 | |
| 10 | get سعر() { |
| 11 | return this.#سعر; |
| 12 | } |
| 13 | |
| 14 | set سعر(قيمة) { |
| 15 | if (قيمة < 0) { |
| 16 | throw new Error("السعر لا يمكن أن يكون سالباً"); |
| 17 | } |
| 18 | this.#سعر = قيمة; |
| 19 | } |
| 20 | } |
| 21 | |
| 22 | const م = new منتج("قلم", 5); |
| 23 | console.log(م.سعر); // 5 — يبدو كخاصية عادية لكنه getter فعلياً |
| 24 | م.سعر = 10; // يستدعي setter مع التحقق |
مثال 2: الأساليب الخاصة (Private Methods)
| 1 | // أساليب خاصة أيضاً (Private Methods) |
| 2 | class معالج_دفع { |
| 3 | #تحقق_من_البطاقة(رقم) { |
| 4 | return رقم.toString().length === 16; |
| 5 | } |
| 6 | |
| 7 | دفع(رقم_البطاقة, مبلغ) { |
| 8 | if (!this.#تحقق_من_البطاقة(رقم_البطاقة)) { |
| 9 | return "رقم بطاقة غير صالح"; |
| 10 | } |
| 11 | return `تم دفع ${مبلغ} بنجاح`; |
| 12 | } |
| 13 | } |
| 14 | |
| 15 | const معالج = new معالج_دفع(); |
| 16 | console.log(معالج.دفع(1234567890123456, 100)); |
| 17 | // معالج.#تحقق_من_البطاقة(...); // ❌ خطأ: خاص تماماً |