البرمجة

التسلسل الاختياري في JavaScript

التسلسل الاختياري ?. للوصول لخاصيات الكائن في JavaScript: المفهوم، الاستخدامات، والفوائد

في عالم تطوير البرمجيات، خصوصًا عند العمل على تطبيقات الويب باستخدام لغة JavaScript، كثيرًا ما يتعامل المطورون مع كائنات (Objects) تحتوي على تراكيب متداخلة ومعقدة. خلال عمليات البرمجة اليومية، قد يحدث أن يحاول المطور الوصول إلى خاصية داخل كائن عميق أو متداخل دون التأكد أولًا من أن كل خطوة في المسار موجودة فعليًا. في هذه الحالة، قد تؤدي المحاولة إلى حدوث خطأ من نوع TypeError لأن البرنامج يحاول الوصول إلى خاصية على قيمة غير معرفة (undefined) أو فارغة (null).

هنا تبرز أهمية التسلسل الاختياري ?. أو ما يُعرف بالـ Optional Chaining. يقدم هذا المشغل وسيلة آمنة للوصول إلى خصائص الكائنات أو استدعاء دوال مرتبطة بها دون التسبب في أعطال للبرنامج إذا لم تكن إحدى الطبقات الوسيطة موجودة.

في هذا المقال، سيتم التطرق بعمق إلى هذا المفهوم، مع تغطية شاملة للأساس النظري، الأمثلة العملية، والفروقات بينه وبين الأساليب التقليدية، بالإضافة إلى حالات الاستخدام الشائعة، الجوانب التقنية، ودوره في تحسين كتابة الكود من حيث الأمان، الأداء، والتنظيم.


ما هو التسلسل الاختياري ?. في JavaScript؟

التسلسل الاختياري ?. هو عامل تشغيل جديد تم إدخاله في JavaScript بدءًا من ECMAScript 2020 (ES11). وظيفته الأساسية هي تمكين المطور من الوصول إلى خاصية داخل كائن أو استدعاء دالة على كائن بشرط وجود ذلك الكائن، دون الحاجة إلى التحقق من وجوده يدويًا في كل خطوة.

يُستخدم المشغل ?. في حالات تتطلب الوصول إلى خصائص أو عناصر داخلية في كائنات قد تكون غير معرفة undefined أو فارغة null. بدلاً من أن يتسبب الوصول في رفع خطأ يوقف تنفيذ البرنامج، يقوم هذا المشغل بإرجاع undefined إن لم تكن إحدى الخطوات في السلسلة موجودة.


الشكل العام لاستخدام ?.

javascript
obj?.prop obj?.[expr] obj?.method?.()

مقارنة مع الطريقة التقليدية:

الطريقة التقليدية تتطلب كتابة تحقق يدوي لكل طبقة:

javascript
if (obj && obj.prop && obj.prop.deep) { // use obj.prop.deep }

بينما باستخدام التسلسل الاختياري:

javascript
obj?.prop?.deep

الحالات التي يمكن استخدام ?. فيها

1. الوصول إلى خاصية في كائن

javascript
const user = { name: "Ahmad", address: { city: "Riyadh" } }; const city = user?.address?.city; // "Riyadh" const street = user?.address?.street; // undefined، بدون خطأ

2. استخدام ?. مع الأقواس المربعة []

javascript
const key = "city"; const city = user?.address?.[key]; // "Riyadh"

3. استدعاء دالة داخل كائن

javascript
const user = { getName: () => "Fatima" }; const name = user.getName?.(); // "Fatima" const age = user.getAge?.(); // undefined، لا يتم استدعاء شيء، ولا يحدث خطأ

4. التعامل مع المصفوفات

javascript
const data = { list: [ { value: 1 }, { value: 2 } ] }; const firstValue = data.list?.[0]?.value; // 1 const thirdValue = data.list?.[2]?.value; // undefined

أهمية وفوائد استخدام ?.

1. تجنب أخطاء TypeError

من أبرز فوائد التسلسل الاختياري أنه يقي من ظهور الأخطاء الشائعة من نوع:

bash
Uncaught TypeError: Cannot read property 'x' of undefined

عند محاولة الوصول إلى خاصية على كائن غير موجود.

2. تقليل التعقيد في الشيفرة

بدلاً من كتابة سلسلة من الشروط للتحقق من وجود كل خاصية في كائن متداخل، يمكن استخدام ?. لكتابة الكود بشكل مختصر وواضح، ما يسهل قراءته وصيانته.

3. مناسب للكائنات الديناميكية

في كثير من الأحيان، خاصة عند العمل مع البيانات الواردة من API خارجي، لا يمكن ضمان أن جميع الخصائص ستكون موجودة. التسلسل الاختياري يساعد على بناء تطبيق أكثر مرونة يتعامل بذكاء مع الحالات الناقصة أو المتغيرة.


الفرق بين ?. والمشغل المنطقي &&

غالبًا ما يستخدم المطورون العامل && للوصول الآمن إلى خاصيات كائنات:

javascript
const country = user && user.address && user.address.country;

لكن هذه الطريقة تزداد تعقيدًا مع كل طبقة إضافية، بينما باستخدام ?.:

javascript
const country = user?.address?.country;

كما أن ?. يتعامل فقط مع null و undefined بينما && قد يوقف الوصول عند أي قيمة “Falsy” مثل 0 أو “” أو false، مما يؤدي أحيانًا إلى نتائج غير متوقعة.


حالات لا يمكن استخدام ?. فيها

رغم فعاليته، إلا أن للتسلسل الاختياري بعض الحدود:

  • لا يمكن استخدامه على الجهة اليسرى من المعاملات (مثلاً: في تعيين القيم).

javascript
user?.name = "Ali"; // خطأ
  • لا يعمل مع المتغيرات غير المعرفة في الأصل:

javascript
let result = unknownVar?.prop; // TypeError: unknownVar is not defined

يجب تعريف المتغير أولًا، حتى إن لم يكن يحمل قيمة.


مقارنة بين الطرق التقليدية واستخدام ?. (جدول)

التقنية المستخدمة مثال آمنة من الخطأ؟ مناسبة للكود المختصر؟
التحقق اليدوي user && user.address && user.address.city نعم لا
التسلسل الاختياري ?. user?.address?.city نعم نعم
التحقق باستخدام try/catch try { ... } catch(e) { ... } نعم لا
التحقق باستخدام typeof typeof user === "object" جزئيًا لا

تأثير استخدام ?. على الأداء

رغم أن استخدام ?. يقلل من تعقيد الكود ويزيد من أمانه، إلا أنه من المهم فهم تأثيره على الأداء. بشكل عام، لا يُحدث ?. فرقًا كبيرًا في أداء التطبيق عند الاستخدام العادي. ومع ذلك، في سيناريوهات تتضمن عددًا هائلًا من العمليات على خصائص متداخلة، يُفضل دائمًا قياس الأداء باستخدام أدوات مثل Chrome DevTools أو أدوات تحليل الأداء في Node.js.


دعم المتصفحات

تم دعم ?. في معظم المتصفحات الحديثة:

المتصفح الحد الأدنى من الإصدارات
Chrome 80
Firefox 74
Edge 80
Safari 13.1
Node.js 14

لضمان دعم هذه الميزة في بيئات لا تدعم ECMAScript 2020، يمكن استخدام محولات (Transpilers) مثل Babel التي تترجم الكود إلى نسخة أقدم متوافقة مع المتصفحات القديمة.


دور التسلسل الاختياري في البرمجة الدفاعية

البرمجة الدفاعية (Defensive Programming) هي أسلوب في كتابة الشيفرة يهدف إلى تقليل الأخطاء المحتملة والتعامل معها قبل وقوعها. في هذا السياق، يعد استخدام ?. أداة ممتازة لكتابة شيفرة تتعامل بذكاء مع البيانات الناقصة أو غير المكتملة، خصوصًا في الواجهات الأمامية التي تتعامل مع بيانات JSON غير مضمونة من واجهات RESTful أو GraphQL.


حالات استخدام عملية شائعة

1. تحليل استجابات واجهات API

عند جلب البيانات من API، قد لا تتضمن الاستجابة جميع الحقول، وهنا يأتي دور ?.:

javascript
fetch("https://api.example.com/user") .then(res => res.json()) .then(data => { const username = data?.user?.profile?.username; });

2. التعامل مع عناصر DOM

javascript
const element = document.querySelector(".non-existent-class"); const value = element?.textContent;

3. التعامل مع كائنات المكونات في React

javascript
function UserProfile({ user }) { return ( <div> {user?.profile?.avatarUrl ? ( <img src={user.profile.avatarUrl} /> ) : ( "No avatar" )} div> ); }

الختام

يعد التسلسل الاختياري ?. في JavaScript أداة قوية تساهم في كتابة شيفرة أكثر أمانًا وتنظيمًا ووضوحًا، خصوصًا في البرامج المعقدة التي تتعامل مع بيانات متغيرة أو غير مضمونة المصدر. هو جزء من جهود مجتمع JavaScript لتقليل الأخطاء الشائعة وتمكين المطورين من كتابة كود نظيف وقابل للصيانة والتوسعة.

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


المراجع:

  1. MDN Web Docs – Optional Chaining (?.)

  2. ECMAScript® 2020 Language Specification (ECMA-262)