كيف تعمل علامة الاستفهام (?) في JavaScript؟ شرح المعامل الثلاثي وOptional Chaining وNullish Coalescing
مقدمة: لماذا تُعد علامة ? من أقوى الرموز في JavaScript؟
تبدو علامة ? بسيطة للوهلة الأولى، لكنها في الواقع من أكثر الأدوات مرونة وفائدة في لغة JavaScript. فهي لا تُستخدم فقط لاختصار الشروط، بل تدخل أيضاً في ميزات حديثة تساعد على كتابة كود أكثر أماناً ووضوحاً، خاصة عند التعامل مع القيم المفقودة أو البيانات القادمة من API أو قواعد البيانات.
في هذا المقال سنشرح الاستخدامات الثلاثة الأهم لعلامة ? في JavaScript بأسلوب عملي ومبسط:
- المعامل الثلاثي
Ternary Operator - السلسلة الاختيارية
Optional Chaining - دمج القيم الفارغة
Nullish Coalescing

أولاً: المعامل الثلاثي Ternary Operator
مصطلح Ternary يعني أن العملية تعتمد على ثلاثة أجزاء. ولهذا سُمّي هذا المعامل بالمعامل الثلاثي، لأنه الوحيد تقريباً في الاستخدام الشائع داخل JavaScript الذي يستقبل ثلاثة عناصر:
- شرط
- قيمة تُعاد إذا كان الشرط صحيحاً
- قيمة تُعاد إذا كان الشرط خاطئاً
الصيغة العامة تكون كالتالي:
condition ? valueIfTrue : valueIfFalse
بمعنى آخر، نكتب الشرط أولاً، ثم نضع ?، ثم القيمة التي ستُعاد عند تحقق الشرط، وبعدها : ثم القيمة البديلة إذا لم يتحقق الشرط.

متى نستخدم المعامل الثلاثي؟
يُستخدم هذا الأسلوب عندما تحتاج إلى شرط بسيط وتريد كتابة الكود بشكل مختصر وواضح بدلاً من استخدام جملة if...else الكاملة.
مقارنة بين Ternary Operator وif...else
المعامل الثلاثي يُعد اختصاراً أنيقاً لعبارة if...else. ففي كثير من الحالات، يمكن كتابة نفس المنطق في سطر واحد بدلاً من عدة أسطر.

هذا لا يعني أن المعامل الثلاثي أفضل دائماً، لكنه مناسب جداً عندما يكون الشرط قصيراً والنتيجة واضحة. أما إذا كان لديك أكثر من شرط متداخل أو منطق معقد، فغالباً تكون if...else أكثر قابلية للقراءة والصيانة.
مزايا المعامل الثلاثي
- تقليل عدد الأسطر البرمجية
- جعل الشروط البسيطة أكثر اختصاراً
- مناسب داخل عمليات الإسناد أو
return
ثانياً: السلسلة الاختيارية Optional Chaining
في الإصدارات الحديثة من JavaScript ظهرت ميزة ممتازة تُعرف باسم Optional Chaining. هذه الميزة تحل مشكلة شائعة جداً عند الوصول إلى خصائص كائن قد لا تكون موجودة.
تخيل أنك تتعامل مع بيانات قادمة من قاعدة بيانات أو من خدمة API، وتحاول الوصول إلى خاصية داخل كائن غير معرّف. في هذه الحالة ستواجه خطأ وقت التشغيل من نوع TypeError.


ومن أشهر الرسائل التي قد تراها: TypeError: Cannot read property 'salary' of undefined.
كيف تعمل Optional Chaining؟
الفكرة بسيطة: بدلاً من الوصول المباشر إلى الخاصية، نضع ?. قبل الخاصية التالية. فإذا كانت القيمة السابقة undefined أو null فلن يتسبب ذلك في انهيار التنفيذ، بل ستُعاد القيمة undefined بهدوء.

هذا السلوك مفيد جداً عند التعامل مع كائنات متداخلة، مثل بيانات المستخدمين أو الردود القادمة من واجهات البرمجة، لأنه يقلل الحاجة إلى كتابة فحوصات متكررة قبل كل مستوى من الخصائص.
فوائد Optional Chaining
- منع أخطاء وقت التشغيل الناتجة عن الخصائص غير الموجودة
- تقليل عدد الشروط الدفاعية في الكود
- تحسين قابلية القراءة عند التعامل مع الكائنات المتداخلة
ثالثاً: دمج القيم الفارغة Nullish Coalescing
أحياناً تحتاج إلى تعيين قيمة افتراضية إذا كانت قيمة معينة غير موجودة. مثال شائع على ذلك: تطبيق طقس يعرض صورة المدينة، ودرجة الحرارة، والرطوبة، وسرعة الرياح. إذا كانت صورة إحدى المدن غير متوفرة في قاعدة البيانات، فمن الأفضل عرض صورة افتراضية بدلاً من ترك المساحة فارغة.
كثير من المطورين يلجؤون إلى المعامل || لتحديد قيمة افتراضية، لأنه يُعيد القيمة اليمنى إذا كانت القيمة اليسرى غير صالحة منطقياً.

لكن هنا تظهر مشكلة مهمة: المعامل || لا يفرّق بين القيم الفارغة فعلياً مثل undefined وnull، وبين القيم الصالحة التي تعتبر falsy مثل 0 أو ''.
مشكلة || مع القيم الصالحة
const value1 = 0 || 'default string';
console.log(value1);
const value2 = '' || 1000;
console.log(value2);
في المثال السابق، قد تتوقع أن تكون قيمة value1 هي 0 لأن الصفر قيمة موجودة فعلاً، وأن تكون قيمة value2 هي السلسلة الفارغة ''. لكن ما يحدث هو أن || يتعامل معهما كقيم غير صالحة ويعيد القيم الافتراضية.

الحل الأفضل: استخدام ??
هنا يأتي دور Nullish Coalescing عبر المعامل ??. هذا المعامل يعيد القيمة الموجودة على اليمين فقط إذا كانت القيمة اليسرى undefined أو null، وليس إذا كانت 0 أو ''.
const value1 = 0 ?? 'default string';
console.log(value1);
const value2 = '' ?? 1000;
console.log(value2);
في هذه الحالة، ستكون النتيجة كما نتوقع تماماً: سيتم الاحتفاظ بالقيمة 0 والسلسلة الفارغة '' لأنهما قيمتان موجودتان وليستا null أو undefined.

الفرق بين || و??
| المعامل | متى يعيد القيمة اليمنى؟ | هل يعتبر 0 و'' قيماً مفقودة؟ |
|---|---|---|
|| |
عندما تكون القيمة اليسرى falsy |
نعم |
?? |
عندما تكون القيمة اليسرى null أو undefined |
لا |
لذلك، إذا كنت تريد قيمة افتراضية فقط عند غياب البيانات فعلاً، فغالباً يكون ?? هو الخيار الأدق.
متى تستخدم كل أسلوب؟
- استخدم
condition ? value1 : value2عندما تريد كتابة شرط مختصر وواضح. - استخدم
?.عندما تصل إلى خصائص متداخلة قد لا تكون موجودة. - استخدم
??عندما تريد تعيين قيمة افتراضية للقيمnullأوundefinedفقط.
أفضل الممارسات عند استخدام علامة ? في JavaScript
- لا تفرط في استخدام المعامل الثلاثي داخل شروط متداخلة كثيرة حتى لا يصبح الكود صعب القراءة.
- اعتمد على
Optional Chainingعند التعامل مع البيانات الخارجية غير المضمونة. - فضّل
??على||إذا كانت القيم مثل0و''مهمة في منطق التطبيق. - احرص على أن يكون الكود واضحاً للمطورين الآخرين، فاختصار الكود لا يعني دائماً أنه الأفضل.
الخلاصة التقنية
علامة ? في JavaScript ليست مجرد رمز بسيط، بل تمثل ثلاث أدوات قوية تخدم أهدافاً مختلفة: اختصار الشروط عبر Ternary Operator، وتأمين الوصول إلى الخصائص عبر Optional Chaining، والتعامل الذكي مع القيم المفقودة باستخدام Nullish Coalescing. من الناحية العملية، فهم الفرق بين هذه الاستخدامات يرفع جودة الكود ويقلل الأخطاء ويجعل التطبيقات أكثر مرونة، خصوصاً في المشاريع التي تتعامل مع بيانات ديناميكية ومتغيرة باستمرار.