مقدمة: لماذا قد "يتسرب" enum الخاص بك، وكيف تتجنب ذلك
تخيل أنك تعمل على مشروع كبير بلغة JavaScript. لقد قمت بإنشاء enum لحالات الطلب: PENDING، SHIPPED، DELIVERED. كل شيء يعمل بشكل مثالي، حتى يقوم أحد المطورين في أحد الوحدات (أو أنت نفسك بعد ستة أشهر) بكتابة شيء مثل: OrderStatus.PENDING = 'CANCELLED'. أو الأسوأ من ذلك، Object.assign(OrderStatus, { NEW_STATUS: 'hacked' }). بوم! تنهار منطق التطبيق، يصل الخلل إلى الإنتاج، وتقضي ليلة بلا نوم في تصحيح الأخطاء.
هذه مشكلة كلاسيكية حصدت آلاف المشاهدات على Stack Overflow. السؤال "كيف يمكنني ضمان عدم تغيير تعريف enum الخاص بي في JavaScript؟" يقلق الكثيرين. وليس بدون سبب: JavaScript لغة ديناميكية، وكائناتها قابلة للتغيير افتراضيًا. لكن هناك حل، واليوم سنستعرض جميع الطرق الموثوقة لحماية تعداداتك.
في هذه المقالة، سأعرض عليك عدة طرق مجربة: من Object.freeze() البسيط إلى التقنيات المتقدمة باستخدام Symbol و TypeScript. ستتعلم كيفية كتابة enum غير قابل للتغيير يصمد أمام أي تعديلات عرضية (أو غير عرضية).
المشكلة: لماذا enum في JavaScript هو مجرد كائن
على عكس بعض اللغات (C#، Java، Rust)، لا يوجد في JavaScript بناء enum أصلي. يقوم المطورون بمحاكاتها باستخدام كائنات بسيطة:
const OrderStatus = { PENDING: 'pending', SHIPPED: 'shipped', DELIVERED: 'delivered'};هذا يعمل، لكن لهذه المحاكاة عيب قاتل: يمكن لأي شخص تغيير القيمة. وهذا ليس فقط سوء نية - بل يحدث غالبًا عن طريق الخطأ:
- تعيين عرضي في حلقة أو دالة رد اتصال.
- الثبات؟ نسيت - وقام شخص بتوسيع الكائن.
- المكتبات التي قد تحور الكائنات الممررة.
تتفاقم المشكلة في قواعد الأكواد الكبيرة حيث يصعب تتبع هذه التغييرات. لهذا السبب، سؤال حماية enum من التعديلات شائع جدًا.
الحل رقم 1: Object.freeze() - درعك الأول
أبسط وأشهر طريقة هي استخدام Object.freeze(). هذه الطريقة تجعل الكائن غير قابل للتغيير: لا يمكنك إضافة أو حذف أو تعديل الخصائص.
كيف يعمل هذا
const OrderStatus = Object.freeze({ PENDING: 'pending', SHIPPED: 'shipped', DELIVERED: 'delivered'});
// محاولة التغيير - لن تنجحOrderStatus.PENDING = 'CANCELLED'; // صمت (في الوضع الصارم - خطأ)OrderStatus.NEW = 'new'; // لن يُضافdelete OrderStatus.SHIPPED; // لن يُحذف
console.log(OrderStatus.PENDING); // 'pending' - القيمة لم تتغيرلماذا هذا مفيد؟ يعمل Object.freeze() على مستوى الكائن نفسه. إنها آلية مدمجة لا تتطلب مكتبات إضافية. إنها مثالية لحماية enum في JavaScript من التحويرات العرضية.
قيود Object.freeze()
- تجميد سطحي - إذا كانت قيم enum كائنات، فإنها تبقى قابلة للتغيير.
- لا يحمي من إعادة التعيين - إذا استخدمت
letبدلاً منconst، يمكن إعادة كتابة المتغير بالكامل. - لا يعطي أخطاء في الوضع غير الصارم - يتم تجاهل التغييرات ببساطة، مما قد يخفي الخلل.
لكن بالنسبة لـ enum البسيط، هذا أكثر من كافٍ. إذا كنت بحاجة إلى حماية إضافية - تابع القراءة.
الحل رقم 2: استخدم const + Object.freeze() للحظر الكامل
مزيج const (يحمي من إعادة تعيين المتغير) و Object.freeze() (يحمي من