Menu
العربية

الفرق بين null و undefined في جافا سكريبت

ما الفرق الحقيقي بين null و undefined في جافا سكريبت؟ وكيف تتحقق من كل منهما؟ ومتى تستخدم هذه وليس تلك في كودك؟

طريقتان للتعبير عن "لا شيء" في جافا سكريبت

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

باختصار شديد:

  • undefined هي القيمة التي تمنحها لك جافا سكريبت تلقائيًا عندما يكون هناك شيء مفقود.
  • null هي القيمة التي تكتبها أنت بنفسك حين تريد أن تقول: "هذا فارغ عن قصد."
index.js
Output
Click Run to see the output here.

لاحظ النمط: كل undefined في الأمثلة السابقة ظهر لأن جافا سكريبت لم تجد قيمة. أما null فقد ظهر لأن أحدهم كتبه بنفسه.

من أين تأتي قيمة undefined؟

تظهر undefined في جافا سكريبت في حالات محددة، وكلها تدور حول الفكرة نفسها: "لا توجد قيمة متاحة":

index.js
Output
Click Run to see the output here.

في كل الحالات السابقة، حاول جافا سكريبت أن يجد قيمة فلم يجد شيئًا. وقيمة undefined هي طريقة المحرك ليقول لك: "بحثت، ولا توجد قيمة هنا."

يمكنك طبعًا إسناد undefined بنفسك (let x = undefined;)، لكن يُفضَّل ألا تفعل. اترك هذه القيمة كإشارة تعني "جافا سكريبت لم يجد شيئًا"، واستخدم null حين تكون أنت صاحب القرار.

من أين تأتي قيمة null؟

لا تظهر null إلا إذا كتبها أحدهم بنفسه. وهذا هو بيت القصيد — فهي علامة مقصودة تضعها عمدًا.

index.js
Output
Click Run to see the output here.

تعتمد واجهات DOM على null بشكل كبير: فمثلاً document.getElementById("missing") تُرجع null وليس undefined، لأن المتصفح يخبرك صراحةً: "لقد بحثت، ولا يوجد عنصر مطابق". كذلك JSON.parse("null") يُعيد لك null — فصيغة JSON أصلاً لا تعرف undefined.

الخلاصة الذهنية: undefined هو الغياب التلقائي، أما null فهو غياب مقصود اخترته بنفسك.

المفارقة الشهيرة في typeof null

وهذه من أشهر الغرائب في جافا سكريبت:

index.js
Output
Click Run to see the output here.

typeof null ترجع القيمة "object"، وهذا باغ موجود منذ عام 1995 ولم يكن بالإمكان إصلاحه دون تعطيل مواقع كثيرة قائمة، فبقي معنا إلى الأبد. الحقيقة أنّ null ليست كائنًا، بل قيمة بدائية (primitive) تمامًا مثل undefined والأرقام والسلاسل النصية والقيم المنطقية. كل ما في الأمر أنّ نتيجة typeof تكذب علينا هنا.

النتيجة العملية: لا فائدة من typeof في التحقق من null في جافا سكريبت. استخدم المقارنة المباشرة:

index.js
Output
Click Run to see the output here.

أو، في الغالب، تحقّق من كليهما معًا — وهذا موضوع القسم التالي.

فحص null أو undefined دفعة واحدة: صيغة == null

في أغلب الحالات لا يهمّك أيّ نوع من القيم الغائبة لديك، كل ما تريده هو معرفة ما إذا كانت القيمة مفقودة قبل استخدامها. والصيغة المتعارف عليها بين مطوّري جافا سكريبت هي استخدام المساواة المرنة مع null:

index.js
Output
Click Run to see the output here.

value == null يُرجِع true فقط في حالتَي null وundefined، ويُرجِع false لأي قيمة أخرى — بما في ذلك 0 و"" وfalse، وهذا عادةً هو السلوك المطلوب. وهذه هي الحالة الوحيدة التي يُفضَّل فيها استخدام == بدل ===، وأدوات الـ linter تعرف ذلك وتسمح به.

وإن أردت الوضوح التام، فإن value === null || value === undefined تؤدي الغرض نفسه وتبقى مفهومة للقارئ.

معاملات القيم العدمية: ?? و?.

أُضيف معاملان إلى جافا سكريبت خصيصًا لتسهيل التعامل مع null وundefined، وكلاهما يعامل القيمتين بالطريقة نفسها ولا يمسّ ما عداهما.

معامل الدمج العدمي (??) يوفّر قيمة بديلة فقط عندما يكون الطرف الأيسر null أو undefined:

index.js
Output
Click Run to see the output here.

قارن هذا مع ||، التي ستستبدل 0 بالقيمة 3 لأن 0 تُعدّ قيمة falsy. أما ?? فهو أكثر صرامة: لا يعمل إلا مع القيمتين null و undefined تحديدًا.

السلسلة الاختيارية (?.) توقف تقييم السلسلة وتُرجع undefined بمجرد أن تصطدم بقيمة null أو undefined:

index.js
Output
Click Run to see the output here.

كلا العاملَين موجودان لأن سؤال "هل هذه القيمة فارغة (nullish)؟" سؤال يتكرر كثيرًا في الكود اليومي. وسنتناولهما بتفصيل أعمق في فصول لاحقة من المنهج.

القيم الافتراضية للبارامترات تعمل مع undefined فقط

هناك قاعدة دقيقة لكنها مهمة: القيم الافتراضية للبارامترات في الدوال تُفعَّل فقط عند تمرير undefined، أما null فلا يستدعيها.

index.js
Output
Click Run to see the output here.

تمرير null يُفهم على أنه "اخترت عمداً ألا أمرر قيمة"، ويُحترم هذا الاختيار كما هو. أما إذا أردت أن يؤدي null بدوره إلى تفعيل القيمة الافتراضية، فاستخدم ?? داخل الدالة:

index.js
Output
Click Run to see the output here.

هنا فخ يقع فيه كثيرون. القيم الافتراضية للبارامترات تتعامل مع الوسائط المفقودة، بينما ?? يتعامل مع القيم العدمية (null أو undefined).

JSON وغياب undefined

صيغة JSON تعرف null لكنها لا تعرف undefined إطلاقًا. وهذا يفتح الباب لمفاجآت صامتة عند تحويل البيانات إلى نص:

index.js
Output
Click Run to see the output here.

حقل age اختفى تمامًا — لأن JSON.stringify يتجاهل الخصائص التي تحمل قيمة undefined، بينما تبقى null لأن صيغة JSON تدعمها. تمرير كائن عبر JSON ذهابًا وإيابًا من الأسباب الشائعة لاختفاء خصائص undefined بهدوء دون أن تلاحظ.

أما داخل المصفوفات، فتتحول undefined إلى null:

index.js
Output
Click Run to see the output here.

إذا كنت تصمّم حمولة (payload) لواجهة API، فضّل null على undefined للحقول التي لا تحمل قيمة، لأنّ null يصمد عند التسلسل والنقل عبر الشبكة.

متى نستخدم null ومتى نستخدم undefined؟

إليك اتفاقية منطقية يمكنك اعتمادها في شيفرتك:

  • اجعل undefined تعني "لم تُمرَّر قيمة" — وسيطات ناقصة، متغيّرات لم تُسنَد، أو خصائص غير موجودة. ولا تُسنِد undefined يدويًا أبدًا.
  • استخدم null حين تريد أن تقول صراحةً: "هذا الحقل فارغ عن قصد" — كمستخدم سجّل خروجه، أو خيار لم يُختَر بعد، أو حقل نموذج جرى تفريغه.
  • تقبّل الاثنين عند حدود الـ API (عبر == null أو ??)، لكن التزم بقيمة واحدة فيما تُنتِجه أنت.

بعض أدلة التنسيق (ومنها دليل TypeScript) تستغني عن null نهائيًا وتكتفي بـ undefined وحدها. وهذا توجّه له ما يبرّره — قيمة واحدة أبسط من قيمتين. المهم أن تختار قاعدة موحّدة لكل مشروع وتُطبّقها في كل مكان.

التالي: التحويل التلقائي للأنواع (Type Coercion)

يتصرّف كلٌّ من null وundefined بطرق مختلفة عندما تحوّلهما جافا سكريبت إلى أرقام أو نصوص أو قيم منطقية — فمثلًا Number(null) يُعطي 0، بينما Number(undefined) يُعطي NaN، وهذا النوع من عدم التناظر يتسبّب في أخطاء حقيقية. موضوعنا القادم هو التحويل التلقائي للأنواع، وحين تستوعب قواعده كاملةً، ستجد أنّ كثيرًا من غرائب جافا سكريبت لم تعد ألغازًا.

الأسئلة الشائعة

ما الفرق بين null و undefined في جافا سكريبت؟

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

كيف أتحقق من null و undefined معًا في فحص واحد؟

استخدم value == null. المساواة المرنة تعتبر null و undefined متساويتين مع بعضهما فقط ولا تتساويان مع أي شيء آخر، لذا فإن x == null تكون true لهاتين القيمتين تحديدًا. هذا هو الموضع الوحيد الذي يكون فيه استخدام == بدلًا من === اصطلاحًا شائعًا وآمنًا.

لماذا تُرجع typeof null القيمة 'object'؟

هذا خطأ قديم موجود منذ أول إصدار من جافا سكريبت، ولا يمكن إصلاحه دون كسر مواقع الويب القائمة. typeof null تُرجع 'object' رغم أن null قيمة بدائية (primitive). للتحقق من null تحديدًا قارن مباشرةً بهذا الشكل: value === null.

هل أستخدم null أم undefined في كودي؟

اجعل undefined تعني «لم يُمرَّر شيء»، واستخدم null عندما تريد الإشارة صراحةً إلى أن القيمة «فارغة عن قصد». كثير من المشاريع (ودليل الأسلوب الخاص بـ TypeScript) يتجنبون null تمامًا ويستخدمون undefined فقط. المهم أن تختار اصطلاحًا واحدًا في المشروع وتلتزم به.

تعلّم البرمجة مع Coddy

ابدأ الآن