فاتحة
أريد أن أقدم للمحكمة الخاصة بك عددًا من التماثيل البسيطة التي تصف تقنيات وأسس metaprogramming. سأكتب بشكل رئيسي حول استخدام بعض التقنيات في JavaScript أو في TypeScript
هذه هي المقالة الأولى (ونأمل ألا تكون الأخيرة) في السلسلة.
فما هو metaprogramming
Metaprogramming هي تقنية برمجة تتمتع فيها برامج الكمبيوتر بالقدرة على التعامل مع البرامج الأخرى على أنها بياناتها. وهذا يعني أنه يمكن تصميم برنامج لقراءة أو إنشاء أو تحليل أو تحويل البرامج الأخرى ، وحتى تعديل نفسه أثناء التشغيل. في بعض الحالات ، يسمح هذا للمبرمجين بتقليل عدد سطور التعليمات البرمجية للتعبير عن حل ، وبالتالي تقليل وقت التطوير .
وصف مربك إلى حد ما ، ولكن الفائدة الرئيسية من metaprogramming مفهومة:
... يتيح ذلك للمبرمجين تقليل عدد أسطر التعليمات البرمجية لتنفيذ الحل ، مما يقلل بدوره من وقت التطوير

في الواقع ، metaprogramming لديه الكثير من الوجه والمظهر. ويمكنك مناقشة لفترة طويلة حول "أين ينتهي metaprogramming وتبدأ البرمجة نفسها"
بنفسي ، قبلت القواعد التالية:
- لا تتعامل Metaprogramming مع منطق العمل ، ولا تغيره ولا تؤثر عليه بأي شكل من الأشكال.
- إذا قمت بإزالة كل رمز metaprogramming ، فلن يؤثر ذلك (جذريًا) على البرنامج.
في JavaScript ، يعد metaprogramming اتجاهًا جديدًا نسبيًا ، حيث يعتبر الطوب الأساسي هو واصف.
واصف جافا سكريبت
الواصف هو نوع من الوصف (معلومات التعريف) لخاصية معينة أو طريقة معينة في كائن ما.
يتيح فهم هذا الكائن ( واصفه ) ومعالجته بشكل صحيح أكثر بكثير من مجرد إنشاء وتغيير الأساليب أو الخصائص في الكائنات.
كما سيساعد الواصف في فهم العمل مع الديكور (ولكن المزيد عن ذلك في المقالة التالية).
من أجل الوضوح ، تخيل أن هدفنا هو وصف الشقة.
نحن تصف وجوه شقتنا:
let apt = { floor: 12, number: '12B', size: 3400, bedRooms: 3.4, bathRooms: 2, price: 400000, amenities: {...} };
دعونا نحدد أي من الخصائص قابلة للتعديل وأيها غير قابلة للتعديل.
على سبيل المثال ، لا يمكن تغيير الطابق أو الحجم الإجمالي للشقة ، لكن عدد الغرف أو الحمامات ممكن تمامًا.
وبالتالي لدينا المتطلبات التالية: في الكائنات المناسبة ، تجعل من المستحيل تغيير الخصائص: الأرضية والحجم .
لحل هذه المشكلة ، نحتاج فقط إلى واصفات كل من هذه الخصائص. للحصول على واصف ، نستخدم الأسلوب الثابت getOwnPropertyDescriptor ، الذي ينتمي إلى كائن الفئة.
let descriptor = Object.getOwnPropertyDescriptor(todoObject, 'floor'); console.log(descriptor);
دعنا نحلل بالترتيب:
القيمة: أي - في الواقع نفس القيمة التي تم تعيينها في وقت ما لخاصية الكلمة
قابل للكتابة: منطقي - يحدد ما إذا كان سيتم تغيير القيمة أم لا
تعداد: منطقي - يحدد ما إذا كان يمكن إدراج خاصية الكلمة أو عدم إدراجها - (المزيد حول ذلك لاحقًا).
configurable: boolean - يحدد القدرة على إجراء تغييرات على كائن الواصف .
من أجل منع إمكانية تغيير خاصية الكلمة ، بعد التهيئة ، من الضروري تغيير قيمة للكتابة إلى false .
لتغيير خصائص واصف ، هناك طريقة ثابتة defineProperty ، والتي تأخذ الكائن نفسه ، واسم الخاصية ، واصف .
Object.defineProperty(apt, 'floor', {writable: false});
في هذا المثال ، لا نمرر كائن واصف بأكمله ، ولكن خاصية واحدة قابلة للكتابة فقط ذات القيمة false .
الآن دعونا نحاول تغيير القيمة في خاصية الكلمة:
apt.floor = 44; console.log(apt.floor);
لم تتغير القيمة ، وعند استخدام "استخدام صارم" ، نحصل على رسالة خطأ:
لا يمكن التعيين لقراءة خاصية "أرضية" الكائن فقط ...
والآن لم يعد بإمكاننا تغيير القيمة. ومع ذلك ، لا يزال بإمكاننا العودة للكتابة -> صواب ، ثم تغيير خاصية الكلمة . لتجنب ذلك ، من الضروري تغيير قيمة الخاصية القابلة للتكوين إلى false في واصف .
Object.defineProperty(apt, 'floor', {writable: false, configurable: false});
إذا حاولنا الآن تغيير قيمة أي من خصائص الواصف الخاص بنا ...
Object.defineProperty(apt, 'floor', {writable: true, configurable: true});
استجابة لذلك ، نحصل على:
TypeError: لا يمكن إعادة تعريف الخاصية: floor
بمعنى آخر ، لا يمكننا تغيير قيمة الكلمة أو واصفها بعد الآن.
لخص
لجعل قيمة الخاصية في الكائن دون تغيير ، من الضروري تسجيل تكوين هذه الخاصية: {writable: false، configurable: false} .
يمكن القيام بذلك كما هو الحال أثناء تهيئة العقار:
Object.defineProperty(apt, 'floor', {value: 12, writable: false, configurable: false});
او بعد.
Object.defineProperty(apt, 'floor', {writable: false, configurable: false});
في النهاية ، فكر في مثال مع الفصل الدراسي:
class Apartment { constructor(apt) { this.apt = apt; } getFloor() { return this.apt.floor } } let apt = { floor: 12, number: '12B', size: 3400, bedRooms: 3.4, bathRooms: 2, price: 400000, amenities: {...} };
تغيير طريقة getFloor:
Apartment.prototype.getFloor = () => { return 44 }; let myApt = new Apartment(apt); console.log(myApt);
الآن قم بتغيير واصف الأسلوب getFloor () :
Object.defineProperty(Apartment.prototype, 'getFloor', {writable: false, configurable: false}); Apartment.prototype.getFloor = () => { return 44 }; let myApt = new Apartment(apt); console.log(myApt);
آمل أن يلقي هذا المقال مزيدًا من الضوء على ماهية الواصف وكيف يمكن استخدامه.
كل ما كتب أعلاه لا يدعي أنه صحيح تمامًا أو الصحيح فقط.