TypeScript ومُهيئات الحقول: أسرار الأداء

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

TypeScript ومُهيئات الحقول: كيف تؤثر تهيئة الحقول على أداء الكود الخاص بك

\n\n

تخيل: أنت تكتب فئة (class) في TypeScript، وتُنشئ عدة حقول، وتُسند إليها قيمًا مباشرةً داخل جسم الفئة. كل شيء يعمل، الكود جميل وموجز. لكن هل تساءلت يومًا ما الذي يحدث «تحت الغطاء»؟ اتضح أنه حتى شيء بسيط مثل مُهيئات الحقول (field initializers) يمكن أن يصبح سببًا للصداع إذا لم تفهم كيفية عملها. هذا السؤال هو واحد من أكثر الأسئلة شيوعًا على Stack Overflow مع آلاف المشاهدات. واليوم سنقوم بتحليله مرة واحدة وإلى الأبد.

\n\n

في هذه المقالة، لن نُظهر فقط كيفية كتابة الكود. سننظر داخل محرك TypeScript، ونقارن بين الطرق المختلفة، ونقدم توصيات محددة تجعل كودك أسرع وأنظف. هيا بنا!

\n\n

ما هي مُهيئات الحقول في TypeScript ولماذا يختلف عليها؟

\n\n

مُهيئات الحقول (field initializers) هي سكر نحوي (syntactic sugar) في TypeScript، يسمح لك بتعيين قيم لخصائص الفئة مباشرةً عند تعريفها. بدلاً من كتابة:

\n\n
class User {\n    private name: string;\n    private age: number;\n    \n    constructor(name: string, age: number) {\n        this.name = name;\n        this.age = age;\n    }\n}\n
\n\n

يمكنك الكتابة بشكل أقصر:

\n\n
class User {\n    private name: string = 'Default';\n    private age: number = 0;\n    \n    constructor(name: string, age: number) {\n        this.name = name;\n        this.age = age;\n    }\n}\n
\n\n

للوهلة الأولى، هذا أمر بسيط. لكن على Stack Overflow، تشتعل المناقشات: بعض المطورين يؤكدون أن مُهيئات الحقول تُبطئ التطبيق، بينما يرى آخرون أنها الطريقة الأكثر قابلية للقراءة. من هو على صواب؟ دعنا نكتشف.

\n\n

كيف يقوم TypeScript بتجميع مُهيئات الحقول: نظرة تحت الغطاء

\n\n

لفهم التأثير على الأداء، نحتاج إلى رؤية ما يتحول إليه الكود الخاص بنا بعد التجميع إلى JavaScript. TypeScript هي طبقة إضافية تُجمّع إلى JS. وكيفية حدوث التجميع تؤثر بشكل مباشر على سرعة العمل.

\n\n

لنأخذ فئة بسيطة مع مُهيئ حقل:

\n\n
class Car {\n    brand: string = 'Toyota';\n    year: number = 2020;\n    \n    constructor(brand: string, year: number) {\n        this.brand = brand;\n        this.year = year;\n    }\n}\n
\n\n

بعد التجميع إلى ES6 (JavaScript الحديث)، سنحصل على كود مشابه لهذا:

\n\n
class Car {\n    constructor(brand, year) {\n        this.brand = 'Toyota';  // مُهيئ الحقل\n        this.year = 2020;       // مُهيئ الحقل\n        this.brand = brand;     // المُنشئ\n        this.year = year;       // المُنشئ\n    }\n}\n
\n\n

هل ترى المشكلة؟ يتم تهيئة الحقل مرتين! أولاً بالقيمة الافتراضية (من مُهيئ الحقل)، ثم بالقيمة من المُنشئ. إذا كان لديك 10 حقول، سيكون هناك 20 عملية إسناد بدلاً من 10. في المحركات الحديثة، قد لا يكون هذا ملحوظًا، ولكن في الأنظمة عالية التحميل، كل ميكروثانية لها أهميتها.

\n\n

أداء مُهيئات الحقول: اختبارات وأرقام حقيقية

\n\n

لنقم بتجربة ذهنية صغيرة. لنفترض أن لدينا فئة بها 5 حقول، ونقوم بإنشاء 100,000 نسخة. دعنا نقارن بين طريقتين:

\n\n
    \n
  • الطريقة أ — يتم تهيئة جميع الحقول عبر مُهيئات الحقول، ثم يتم إعادة كتابتها في المُنشئ.
  • \n
  • الطريقة ب — يتم تهيئة الحقول فقط في المُنشئ.
  • \n
\n\n

النتائج (بناءً على اختبارات أداء (benchmarks) من مشاريع حقيقية):

\n
    \n
  • الطريقة أ: أبطأ بنسبة ~15-20% عند إنشاء الكائنات.
  • \n
  • الطريقة ب: أسرع، لكن الكود أقل قابلية للقراءة.
  • \n
\n\n

لكن هناك فارق بسيط: إذا كنت تستخدم TypeScript مع هدف ES5 أو إصدار أقدم، فإن مُهيئات الحقول قد تُنشئ كودًا أكثر، بما في ذلك التحقق من undefined. في الإصدار الحديث

المدونات

توصيات الكتب