@decorator الزخارف (Decorators)

آخر تحديث: 2026-10-22

@decorator الزخارف (Decorators)

الزخرفة صياغة خاصة توضع قبل الأصناف والمناهج والخصائص والمعاملات على الشكل @name: دالة غلاف ترفق سلوكًا بالصنف (تسجيل أحداث، تحقق، حقن تبعيات) دون المساس بشيفرة الصنف ذاته. وما تزال الزخارف في TypeScript ميزة تجريبية تتطلب تفعيل experimentalDecorators في tsconfig؛ وتستخدمها أطر مثل NestJS وTypeORM بكثافة، وإتقانها شرط لازم لقراءة شيفرة هذه الأطر.

المجموعةالإعداد والتطبيق
النوعبناء الجملة
الوضع الصارمغير مطلوب

ℹ️ معلومة يحوّل المحرر لغة TypeScript إلى JavaScript ثم يشغّلها (بدون فحص أنواع)؛ راجع ناتج كل مثال لنتيجة فحص الأنواع.

📝 الصيغة

// ديكوريتر الكلاس: يستقبل المُنشئ
function sealed(Ctor: Function): void {
  Object.seal(Ctor);
  Object.seal(Ctor.prototype);
}

// ديكوريتر الدالة: يستقبل (النموذج الأولي، اسم الدالة، واصف الخاصية)
function logged(target: object, key: string, desc: PropertyDescriptor): void {
  const original = desc.value;
  desc.value = function (...args: unknown[]) {
    console.log("call", key, args);
    return original.apply(this, args);
  };
}

@sealed
class Calculator {
  @logged
  add(a: number, b: number) { return a + b; }
}

⚙️ المعاملات

ClassDecoratorالمعامل هو باني الصنف؛ يمكنه تعديل الصنف أو إعادة صنف جديد يحل محله — وتُستخدم له قيود «الصنف ككل» مثل @sealed
MethodDecoratorيُنفَّذ مرة واحدة عند تعريف الصنف، ويغلّف المنهج الأصلي بإعادة كتابة desc.value؛ وإعادة واصف جديد تستبدل الواصف كله
experimentalDecoratorsمفتاح في tsconfig، ومن دونه يظهر خطأ «الزخارف ميزة تجريبية»؛ ويعتمد عليه أطر الأوساط البيئية (NestJS وغيرها) حاليًا بناءً على هذه النسخة التجريبية

القيمة المُعادة:يمكن للزخرفة الصنفية أن تعيد بانيًا جديدًا يحل محل الصنف الأصلي (وإن لم تعد شيئًا فالصنف الأصلي يبقى)؛ ويمكن للزخرفة المنهجية أن تعيد واصفًا للخاصية (property descriptor) جديدًا أو أن تعيد undefined وتعمل عبر الآثار الجانبية فقط.

▶ مثال

عدّل الكود أدناه واضغط «جرّب» لرؤية نتيجة التحويل:

الناتج:

-> add(2, 3)
add = 5
-> mul(4, 5)
mul = 20

(مخرجات التشغيل بعد الترجمة؛ يكتمل التغليف الزخرفي المنهجي عند تعريف الصنف — فعند الاستدعاء يُطبع -> add(2, 3) أولًا ثم تُعاد النتيجة)

💡 نقاط مهمة

ℹ️ معلومة توقيت التنفيذ هو «عند تعريف الصنف» لا «عند استدعاء المنهج»: تُنفَّذ دالة الزخرفة مرة واحدة لحظة تقييم تعليمة class وتستبدل desc.value بالنسخة المغلّفة؛ ثم تمر كل الاستدعاءات اللاحقة عبر الغلاف.
💡 تلميح لتمرير معاملات إلى الزخرفة استخدم «مصنع زخارف»: @log("debug") دالة تعيد دالة زخرفة — تستقبل الطبقة الخارجية الإعدادات وتستقبل الداخلية (target, key, desc). و@Injectable() في NestJS بالأقواس هو مصنع بالضبط.
⚠️ تنبيه تواقيع النسخة التجريبية والمعيارية غير متوافقة: منذ TS 5 يمكن إسقاط experimentalDecorators واستخدام زخارف ES المعيارية، حيث يتلقى الزخرفة المنهجية كائن context بدلًا من (target, key, desc). تأكد من النسخة المستخدمة قبل قراءة شيفرة المشاريع القديمة أو الأطر.
المزيد من الحالات قادم قريبًا.

📚 دروس ذات صلة

❓ أسئلة شائعة

س ما الفرق بين الزخارف والدوال رتبة أعلى العادية؟
ج في الجوهر كلاهما «دالة تغلف دالة». الفرق في موضع الإعلان: تُكتب الزخرفة فوق العضو المزخرف ويتكفل المترجم بربطه بالتعريف فيبقى متن الصنف/المنهج نظيفًا؛ بينما يجب تطبيق الدوال رتبة أعلى صراحةً عند الإنشاء (const add = logged(Calculator.prototype.add)). تقرأ الزخارف كوسوم وهي أنسب للشواغل العرضية.
س كيف تعمل @Injectable() في NestJS؟
ج @Injectable() مصنع زخارف؛ ترفق زخرفة الصنف المعادة بيانات وصفية بالصنف تجعله قابلًا للإنشاء بواسطة حاوية الحقن التبعي. وعند بناء Controller تقرأ الحاوية البيانات الوصفية لأنواع معاملات الباني وتحل التبعيات وتحقنها تلقائيًا — فالزخرفة نفسها لا تحقن شيئًا بل تسجّل المعلومات فقط.
س أيهما ينبغي لمشروع جديد: الزخارف التجريبية أم المعيارية؟
ج اتبع إطارك: مع أنظمة NestJS/TypeORM أبقِ experimentalDecorators (فهي تعتمد الدلالات القديمة)؛ أما شيفرة موقعك الخاصة فيُفضَّل فيها النسخة المعيارية (الافتراضية في TS 5+) — فقد دخلت معيار ES ولم يعد عليها عبء «التجريبية»، لكن لا يجوز خلط أسلوبي النسختين.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%