سؤال يقابل كل متعلّم جافاسكريبت، وسؤال مقابلات دائم: ما
الفرق بين undefined وnull؟ كلاهما «لا شيء»، لكن نوع اللاشيء مختلف،
والخلط بينهما مصدر أخطاء حقيقية.
معنى undefined
undefined كلمة إنجليزية تعني «غير معرّف». وفي JavaScript هي قيمة خاصة
تضعها اللغة بنفسها حين تسأل عن شيء لم تُعطَ له قيمة بعد:
let name;
console.log(name); // undefined: صُرّح بالمتغيّر ولم يُسند
ومعنى null: «فارغ عمدًا». لا تظهر وحدها أبدًا، بل يكتبها المبرمج بيده
ليقول «هذا المكان فارغ، وأنا أعرف ذلك».
فكّر فيها كصندوق بريد: undefined صندوق لم يضع فيه أحد شيئًا قط، وnull
صندوق وضع فيه صاحبه ورقة مكتوب عليها «فارغ».
لماذا أرى كلمة undefined في صفحة أو تطبيق؟
إن ظهرت لك undefined مكتوبة في موقع (مكان اسم أو مدينة أو سعر)، أو
undefined,undefined في عنوان، فهذا خلل برمجي في الموقع: الكود حاول عرض
معلومة لم تصله، فحوّل JavaScript الغياب نفسه إلى نص:
const user = {}; // البيانات لم تصل
console.log(`${user.city},${user.country}`); // undefined,undefined
console.log("الاسم: " + user.name); // الاسم: undefined
كزائر، أعد تحميل الصفحة؛ غالبًا تأخرت البيانات أو فشل طلب. وكمطور، الحل ألّا
تعرض القيمة قبل التحقق منها، أو أن تعطيها بديلًا: user.city ?? "غير محدد".
جدول المقارنة الكامل
| الخاصية | undefined | null |
|---|---|---|
| المعنى | لم تُعطَ قيمة بعد | فارغ بقرار مقصود |
| من يضعها؟ | اللغة تلقائيًّا | المبرمج يدويًّا |
typeof | "undefined" | "object" (خطأ تاريخي) |
التحويل لرقم Number(x) | NaN | 0 |
| تُفعّل القيمة الافتراضية للمعامل؟ | نعم | لا |
| في كائن JSON | تُحذف الخاصية | تبقى null |
null == undefined | true | true |
null === undefined | false | false |
كل سطر في الجدول جرّبناه في Node.js، وأهم سطرين عمليًّا شرحهما تحت.
أين تظهر undefined تلقائيًّا؟
let name; // صُرّح ولم يُسند → undefined
const user = {};
user.age; // خاصية غير موجودة → undefined
const arr = [1, 2];
arr[9]; // فهرس خارج الحدود → undefined
function greet() {} // دالة بلا return → undefined
greet();
function hi(msg) {} // وسيط لم يُمرَّر → msg هي undefined
hi();
لاحظ: في كل الحالات لم يكتب أحد undefined بيده. هي علامة اللغة على الغياب.
أين تستخدم null بقرارك؟
let selectedLesson = null; // قيمة ابتدائية: «لا درس مختارًا بعد»
function findUser(users, id) {
// «بحثنا ولم نجد»: قرار صريح أوضح من undefined
return users.find((u) => u.id === id) ?? null;
}
let timer = setTimeout(save, 1000);
clearTimeout(timer);
timer = null; // «لا مؤقّت فعّال الآن»
الفرق الذي يفاجئ الجميع: القيم الافتراضية
function greet(name = "زائر") {
return name;
}
greet(undefined); // "زائر"
greet(null); // null
القيمة الافتراضية للمعامل (وكذلك في التفكيك const { lang = "ar" } = obj) تعمل
فقط حين تكون القيمة undefined. أما null فتعتبرها اللغة قيمة حقيقية
أرسلتها عمدًا، فتمرّ كما هي. فإن كان الخادم يرسل null للحقول الفارغة، فلن
تحميك القيمة الافتراضية، وستحتاج ??:
function greet(name) {
return name ?? "زائر"; // تعمل مع null وundefined معًا
}
الفرق في JSON: undefined تختفي
JSON.stringify({ a: undefined, b: null }); // '{"b":null}'
JSON.stringify([undefined, null]); // '[null,null]'
JSON لا يعرف undefined أصلًا: في الكائن تُحذف الخاصية كلها، وفي المصفوفة
تتحوّل إلى null. هذا مهم حين ترسل بيانات لخادم: إرسال { "phone": null }
يعني «امسح الهاتف»، أما undefined فتجعل الحقل يختفي من الطلب، فيُفهم غالبًا
«لا تغيّره». قرار صغير بنتيجة مختلفة تمامًا في قاعدة البيانات.
فخ المقارنات: == و===
null == undefined // true: الحالة الوحيدة المتسامحة
null === undefined // false: النوعان مختلفان
null == 0 // false: null لا تساوي صفرًا هنا
null >= 0 // true: المقارنات الحسابية تحوّلها إلى 0
undefined >= 0 // false: undefined تتحوّل إلى NaN
هذه التناقضات سبب القاعدة الشهيرة: قارن بـ === دائمًا. والاستثناء المقبول
الوحيد الذي يستخدمه بعض الفرق عن قصد هو x == null، لأنها تفحص الغيابين معًا في
مقارنة واحدة.
undefined ليست «x is not defined»
let a;
console.log(a); // undefined: المتغيّر موجود وفارغ
console.log(b); // ReferenceError: b is not defined
الاسمان متشابهان والمعنى مختلف: undefined قيمة في متغيّر موجود. أما
is not defined فخطأ يعني أن المتغيّر غير موجود أصلًا: لم تصرّح به، أو
أخطأت في كتابة اسمه، أو تستخدمه خارج نطاقه. الأولى تمرّ بهدوء، والثاني يوقف
البرنامج.
الأدوات الحديثة: ?? و?.
المعاملان صُمّما للتعامل مع «الغيابين» معًا:
// ?? قيمة بديلة فقط إذا كانت null أو undefined
const lang = settings.lang ?? "ar";
0 || "x" // "x": || تستبدل كل قيمة «كاذبة»
0 ?? "x" // 0: ?? تستبدل الغياب فقط
// ?. تتوقف بأمان إذا صادفت null أو undefined في السلسلة
const city = user?.address?.city; // undefined بدل الانهيار
استخدم ?? لا || حين تكون 0 أو "" قيمًا صالحة (كمية، أو نص فارغ عن قصد).
⚠️ وإذا انهار كودك بـ
Cannot read properties of undefined، فهذه هي النتيجة الأشهر للموضوع كله: حلّه الكامل هنا.
وفي اللغات الأخرى؟
معظم اللغات فيها قيمة «فارغة» واحدة فقط: None في Python، وnull في Java وC#،
وNULL في SQL. JavaScript من القليلة التي تملك اثنتين، ولهذا يحتاج المتعلم
هذا الفرق تحديدًا فيها. وفي TypeScript يصبح الفرق جزءًا من النوع نفسه
(string | undefined مقابل string | null)، فيمنعك المترجم من نسيان أي منهما.
متى تستخدم أيًّا منهما؟ قاعدة قرار
| الموقف | استخدم |
|---|---|
| متغيّر سيُملأ لاحقًا بقيمة تعرفها | null |
| دالة بحث لم تجد شيئًا | null |
| تريد مسح حقل في الخادم صراحة | null في JSON |
| حقل اختياري لم يُرسل | اترك undefined (لا تكتبه) |
| تفحص «هل توجد قيمة؟» | ?? أو ?. أو x == null |
تعطي قيمة افتراضية لمعامل قد يأتي null | ?? لا = قيمة |
قائمة تحقّق سريعة
- لا تكتب
x = undefinedبيدك: اتركها للغة، واستخدمnullللتفريغ المقصود. - قارن بـ
===، وللغيابين معًا استخدم??و?.. typeof null === "object": لفحصnullاستخدمx === null.- القيمة الافتراضية للمعامل لا تعمل مع
null. JSON.stringifyيحذفundefinedويُبقيnull.is not definedخطأ مختلف: المتغيّر غير موجود أصلًا.
الخلاصة
undefined غياب تكتبه اللغة، وnull فراغ تكتبه أنت. التزم بهذا العرف، وقارن
بـ ===، وتذكّر الفرقين العمليين (القيم الافتراضية وJSON)، ودع ?? و?.
يتكفلان بالتعامل الآمن مع الاثنين.
أتقن الأساس في درس أنواع البيانات ضمن مسار جافاسكريبت بالعربي، وأكمل مع جدول أخطاء TypeError الشائعة والفرق بين JavaScript وTypeScript، حيث تحلّ الأنواع الصارمة نصف هذا الصداع من جذوره.