مقدمة: لماذا يتعطل كودك بسبب خطأ "undefined"؟
\n\nتكتب الكود، كل شيء يبدو منطقياً، وفجأة — TypeError: Cannot read properties of undefined. هل هذا مألوف؟ هذا الخطأ هو كابوس المبتدئين وضيف متكرر على Stack Overflow. موضوع "Detecting an undefined object property" حصد آلاف المشاهدات، وهذا ليس من قبيل الصدفة.
\n\nالكائنات في JavaScript تشبه صناديق المفاجآت. أنت لا تعرف أبداً على وجه اليقين ما إذا كانت الخاصية التي تحتاجها موجودة بداخلها، خاصة إذا كان الكائن قادماً من API أو قاعدة بيانات أو من مطور آخر. اليوم سنصبح محققين حقيقيين وسنستعرض جميع الطرق لاكتشاف undefined. ستتعرف على الفرق بين undefined وnull، ومتى تستخدم typeof، ومتى تستخدم hasOwnProperty، وكيف تجعل JavaScript الحديثة حياتنا أسهل.
هيا بنا! 🚀
\n\nما هو undefined بالضبط؟
\n\nقبل أن نكتشف undefined، دعنا نفهم ما هو هذا المفهوم. في JavaScript، undefined هي قيمة بدائية تُعطى تلقائياً للمتغير إذا لم يتم تعيين قيمة له. لكن مع الكائنات، الأمور أكثر تعقيداً.
يمكن أن تكون خاصية الكائن undefined في حالتين:
- \n
- الخاصية موجودة، ولكن قيمتها تم تعيينها صراحةً على
undefined. \n - الخاصية غير موجودة في الكائن على الإطلاق. \n
وهنا يبدأ الجزء المثير للاهتمام. بالنسبة للكود الخارجي، تبدو هاتان الحالتان متطابقتين: عند محاولة قراءة خاصية غير موجودة، تحصل على undefined. لكن بالنسبة لمنطقك، قد يكون الفرق حاسماً.
const user = {\n name: 'آنا',\n age: undefined, // الخاصية موجودة ولكن القيمة undefined\n // city: غير مُعلنة تماماً\n};\n\nconsole.log(user.age); // undefined\nconsole.log(user.city); // undefined\n\nكلا الاستدعاءين سيعيدان undefined، لكن الأول لأن القيمة محددة هكذا، والثاني لأن الخاصية غير موجودة. كيف تفرق بينهما؟ تابع القراءة.
الطريقة 1: عامل typeof — الطريقة القديمة الموثوقة
\n\nأبسط وأكثر طريقة آمنة للتحقق من الخاصية هي استخدام typeof. هذا العامل لا يرمي خطأ أبداً، حتى لو كنت تصل إلى خاصية غير موجودة.
const book = {\n title: 'الأخوة كارامازوف',\n author: 'دوستويفسكي'\n};\n\nif (typeof book.year !== 'undefined') {\n console.log('سنة النشر:', book.year);\n} else {\n console.log('الخاصية year غير موجودة');\n}\n// الإخراج: الخاصية year غير موجودة\n\nالمزايا: آمن، يعمل في جميع المتصفحات، لا يتطلب دوال إضافية.
\nالعيوب: لا يفرق بين الحالة التي تكون فيها الخاصية موجودة ولكن قيمتها undefined. إذا كان book.year = undefined، فإن typeof سيظل يُظهر 'undefined'.
متى تستخدم typeof؟
\nمثالي للفحص السريع عندما تحتاج فقط إلى تجنب الخطأ، ولا يهم الفرق الدقيق بين "الخاصية موجودة ولكنها undefined" و"الخاصية غير موجودة". مفيد بشكل خاص للمتغيرات العامة.
\n\nالطريقة 2: عامل in — كاشف الوجود
\n\nعامل in يتحقق مما إذا كانت الخاصية موجودة في الكائن، بما في ذلك الخصائص الموروثة. يُرجع true أو false بناءً على وجود الخاصية في سلسلة النماذج الأولية.
const car = {\n brand: 'Tesla',\n model: 'Model 3'\n};\n\nconsole.log('brand' in car); // true\nconsole.log('year' in car); // false\nconsole.log('toString' in car); // true (موروثة من Object.prototype)\n\nلاحظ: in سيعيد true حتى لو كانت قيمة الخاصية undefined:
const config = {\n debug: undefined\n};\n\nconsole.log('debug' in config); // true — الخاصية موجودة