`n

`null` و`undefined` في JavaScript

1 تمرين

نبذة عن `null` و`undefined`

على عكس كثير من اللغات الأخرى، توجد في JavaScript كيانان مختلفان يمثلان غياب قيمة (ذات معنى). وهما null وundefined.

Null

تُستخدم القيمة البدائية null كـ«قيمة فارغة» مقصودة لمتغير. في لغات أخرى، ربما يُستخدم تركيب مشابه فقط للكائنات (المفقودة) أو لأنواع المؤشرات. في JavaScript، يمثّل null عمومًا قيمة فارغة لأي نوع.

let name = null;
// name is intentionally set to "empty" because it is not
// available

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

let name = null;

name === null;
// => true

// Pitfall:
typeof name;
// => 'object'

Undefined

المتغير الذي لم تُسنَد إليه قيمة يكون من النوع undefined.1

وهذا يعني أنه بينما يمثّل null قيمة فارغة (لكنها تبقى قيمة)، فإن undefined يمثّل الغياب التام للقيمة. 🤯

يظهر undefined في سياقات مختلفة.

  • إذا أُعلن عن متغير دون قيمة (تهيئة)، فإنه يكون undefined.
  • إذا حاولت الوصول إلى قيمة لمفتاح غير موجود في كائن، فستحصل على undefined.
  • إذا لم تُرجع دالة قيمة، فستكون النتيجة undefined.
  • إذا لم يُمرَّر وسيط إلى دالة، فإنه يكون undefined، إلا إذا كان لهذا الوسيط قيمة افتراضية.
let name;
console.log(name);
// => undefined

let obj = { greeting: 'hello world' };
console.log(obj.missingKey);
// => undefined

function returnNothing() {
  return;
}
console.log(returnNothing());
// => undefined

يمكنك التحقق مما إذا كان المتغير undefined باستخدام عامل المساواة الصارمة === أو عامل typeof.

let name;

name === undefined;
// => true

typeof name === 'undefined';
// => true

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

التسلسل الاختياري

كما ذُكر أعلاه، فإن الوصول إلى مفتاح غير موجود في كائن يُرجع undefined في JavaScript. ومع ذلك، إذا حاولت استرجاع قيمة متداخلة ولم يكن المفتاح الأب موجودًا، فإن تقييم المفتاح المتداخل يُنفَّذ على undefined ويؤدي إلى TypeError: Cannot read property ... of undefined. نظريًا، ستحتاج دائمًا إلى التحقق من وجود المفتاح الأب قبل أن تحاول استرجاع المفتاح المتداخل. كان هذا يُفعَل غالبًا باستخدام عامل AND &&، لكن مع القيم المتداخلة بعمق يؤدي هذا إلى تعبيرات طويلة جدًا.

obj.level1 && obj.level1.level2 && obj.level1.level2.level3;

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

const obj = {
  address: {
    street: 'Trincomalee Highway',
    city: 'Batticaloa',
  },
};

obj.residence;
// => undefined

obj.address.zipCode;
// => undefined

obj.residence.street;
// => TypeError: Cannot read property 'street' of undefined

obj.residence?.street;
// => undefined

obj.residence?.street?.number;
// => undefined

الدمج الصفري

هناك حالات تريد فيها تطبيق قيمة افتراضية في حال كان المتغير null أو undefined. في الماضي، كان هذا يُفعَل غالبًا باستخدام عامل شرطي ثلاثي ? أو بالاستفادة من التقييم الكسول لعامل OR ||. وهذا له عيب هو أن القيمة الافتراضية تُطبَّق في كل الحالات التي تكون فيها قيمة المتغير زائفة (مثل '' أو 0)، وليس فقط عندما يكون null أو undefined. وقد يتسبب هذا بسهولة في نتائج غير متوقعة.

let amount = null;
amount = amount || 1;
// => 1

amount = 0;
amount = amount || 1;
// => 1

amount = 0;
amount ? amount : 1;
// => 1

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

let amount = null;
amount = amount ?? 1;
// => 1

amount = 0;
amount = amount ?? 1;
// => 0

[1] Undefined, MDN. (2021). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined (تاريخ الوصول: 4 يونيو 2021).

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم `null` و`undefined`