أتقن عامل دمج القيم الفارغة (??) في JavaScript لتعيين قيم افتراضية أكثر نظافة وكفاءة. تعلم كيف يختلف عن عامل OR (||) وشاهد أمثلة عملية.
دمج القيم الفارغة في JavaScript: دليل شامل لتعيين القيم الافتراضية
في JavaScript، يعد تعيين القيم الافتراضية مهمة شائعة. تقليديًا، استخدم المطورون عامل OR (||
) لهذا الغرض. ومع ذلك، يوفر عامل دمج القيم الفارغة (??
)، الذي تم تقديمه في ECMAScript 2020، طريقة أكثر دقة وموثوقية للتعامل مع تعيينات القيم الافتراضية، خاصة عند التعامل مع قيم null
أو undefined
. يقدم هذا الدليل نظرة عميقة على عامل دمج القيم الفارغة، مستكشفًا صياغته وسلوكه واختلافاته عن عامل OR وحالات الاستخدام العملية.
ما هو دمج القيم الفارغة (Nullish Coalescing)؟
عامل دمج القيم الفارغة (??
) هو عامل منطقي يُرجع المعامل الموجود على جانبه الأيمن عندما يكون المعامل الموجود على جانبه الأيسر null
أو undefined
. وإلا، فإنه يُرجع المعامل الموجود على جانبه الأيسر. بعبارات أبسط، فإنه يوفر قيمة افتراضية فقط عندما يكون المتغير null
أو undefined
بشكل صارم.
الصياغة
صياغة عامل دمج القيم الفارغة بسيطة ومباشرة:
leftOperand ?? rightOperand
هنا، leftOperand
هو المتغير أو التعبير الذي تريد التحقق من كونه null
أو undefined
، و rightOperand
هو القيمة الافتراضية التي تريد تعيينها إذا كان leftOperand
بالفعل null
أو undefined
.
مثال
تأمل المثال التالي:
const username = null ?? "Guest";
console.log(username); // المخرجات: Guest
const age = undefined ?? 25;
console.log(age); // المخرجات: 25
const city = "London" ?? "Unknown";
console.log(city); // المخرجات: London
في هذا المثال، يتم تعيين القيمة الافتراضية "Guest" للمتغير username
لأنه في البداية null
. وبالمثل، يتم تعيين 25 للمتغير age
لأنه يبدأ كـ undefined
. ومع ذلك، يحتفظ المتغير city
بقيمته الأصلية "London"، لأنه ليس null
ولا undefined
.
القيم الفارغة (Nullish) مقابل القيم الكاذبة (Falsy)
من المهم للغاية فهم الفرق بين القيم الفارغة (nullish) والقيم الكاذبة (falsy) في JavaScript. القيمة الفارغة هي إما null
أو undefined
. أما القيمة الكاذبة فهي قيمة تعتبر خاطئة عند مواجهتها في سياق منطقي (Boolean). تشمل القيم الكاذبة:
null
undefined
0
(صفر)NaN
(ليس رقمًا)''
(سلسلة نصية فارغة)false
يكمن الفرق الرئيسي في أن عامل دمج القيم الفارغة يتحقق فقط من null
أو undefined
، بينما يتحقق عامل OR (||
) من أي قيمة كاذبة.
الفرق بين ??
و ||
عامل OR (||
) هو عامل منطقي يُرجع المعامل الموجود على جانبه الأيمن إذا كان المعامل الموجود على جانبه الأيسر كاذبًا. على الرغم من أنه يمكن استخدامه لتعيين قيم افتراضية، إلا أنه يمكن أن يؤدي إلى سلوك غير متوقع عند التعامل مع قيم مثل 0
أو سلسلة نصية فارغة.
مثال: عيوب استخدام ||
const quantity = 0 || 10; // نعتزم تعيين قيمة افتراضية 10 إذا كانت الكمية مفقودة
console.log(quantity); // المخرجات: 10 (غير متوقع!) لأن 0 قيمة كاذبة
const text = '' || 'Default Text'; // نعتزم تعيين نص افتراضي إذا كان النص مفقودًا
console.log(text); // المخرجات: Default Text (غير متوقع!) لأن '' قيمة كاذبة
في المثال الأول، كنا نعتزم تعيين كمية افتراضية قدرها 10 فقط إذا كانت quantity
مفقودة (null
أو undefined
). ومع ذلك، نظرًا لأن 0
هي قيمة كاذبة، فقد قام عامل OR بتعيين القيمة الافتراضية بشكل غير صحيح. وبالمثل، تسببت السلسلة النصية الفارغة في عرض النص الافتراضي حتى لو كانت السلسلة موجودة (ولكنها فارغة).
استخدام ??
للدقة
دعنا نعيد كتابة المثال السابق باستخدام عامل دمج القيم الفارغة:
const quantity = 0 ?? 10;
console.log(quantity); // المخرجات: 0 (صحيح!)
const text = '' ?? 'Default Text';
console.log(text); // المخرجات: '' (صحيح!)
الآن، المخرجات كما هو متوقع. يتحقق عامل دمج القيم الفارغة فقط من null
أو undefined
، لذلك يتم التعامل مع 0
و ''
كقيم صالحة، ويتم الحفاظ على قيمهما الأصلية.
حالات استخدام دمج القيم الفارغة
يعتبر عامل دمج القيم الفارغة مفيدًا في سيناريوهات مختلفة حيث تحتاج إلى توفير قيم افتراضية فقط عندما يكون المتغير null
أو undefined
بشكل صارم. فيما يلي بعض حالات الاستخدام الشائعة:
1. التعامل مع معاملات الدوال الاختيارية
عند تعريف دالة ذات معاملات اختيارية، يمكنك استخدام عامل دمج القيم الفارغة لتوفير قيم افتراضية إذا لم يتم توفير المعاملات.
function greet(name, greeting) {
const userName = name ?? "User";
const userGreeting = greeting ?? "Hello";
console.log(`${userGreeting}, ${userName}!`);
}
greet(); // المخرجات: Hello, User!
greet("Alice"); // المخرجات: Hello, Alice!
greet("Bob", "Greetings"); // المخرجات: Greetings, Bob!
2. تعيين خيارات التكوين الافتراضية
عند العمل مع كائنات التكوين، يمكنك استخدام عامل دمج القيم الفارغة لضمان استخدام القيم الافتراضية إذا لم يتم تحديد خيارات تكوين معينة.
const config = {
timeout: 5000,
retries: 3
};
function fetchData(options) {
const timeout = options.timeout ?? 10000; // مهلة افتراضية 10 ثوانٍ
const retries = options.retries ?? 5; // 5 محاولات افتراضية
console.log(`Timeout: ${timeout}, Retries: ${retries}`);
}
fetchData(config); // المخرجات: Timeout: 5000, Retries: 3
fetchData({}); // المخرجات: Timeout: 10000, Retries: 5
fetchData({timeout:null, retries: undefined}); // المخرجات: Timeout: 10000, Retries: 5
3. الوصول إلى خصائص الكائنات المتداخلة
عند الوصول إلى خصائص الكائنات المتداخلة، يمكن دمج عامل دمج القيم الفارغة مع التسلسل الاختياري (?.
) لتوفير قيم افتراضية إذا كانت أي من الخصائص الوسيطة null
أو undefined
.
const user = {
profile: {
address: {
city: "New York"
}
}
};
const cityName = user?.profile?.address?.city ?? "Unknown";
console.log(cityName); // المخرجات: New York
const unknownUser = {};
const unknownCityName = unknownUser?.profile?.address?.city ?? "Unknown";
console.log(unknownCityName); // المخرجات: Unknown
4. العمل مع واجهات برمجة التطبيقات (APIs) والبيانات الخارجية
عند جلب البيانات من واجهات برمجة التطبيقات أو المصادر الخارجية، يمكن استخدام عامل دمج القيم الفارغة لتوفير قيم افتراضية إذا كانت بعض حقول البيانات مفقودة أو تحتوي على قيم null
أو undefined
. لنفترض أننا نسترد بيانات المستخدم من مناطق مختلفة، وقد لا تتضمن بعض المناطق حقل `country` في بيانات المستخدم الخاصة بها.
async function getUserData(userId) {
try {
const response = await fetch(`https://api.example.com/users/${userId}`);
const data = await response.json();
const country = data.country ?? "Unknown Country";
const timezone = data.timezone ?? "UTC";
console.log(`User is from: ${country}, Timezone: ${timezone}`);
} catch (error) {
console.error("Error fetching user data:", error);
}
}
// محاكاة استجابات API مختلفة:
const userWithCountry = { name: "John", country: "USA", timezone: "EST" };
const userWithoutCountry = { name: "Jane", timezone: "GMT" };
// لاختبار هذا، ستحتاج إلى واجهة برمجة تطبيقات فعلية أو محاكاة للدالة fetch.
// لأغراض العرض، دعنا نحاكي الاستجابات:
global.fetch = async (url) => {
if (url.includes("123")) {
return { json: async () => userWithCountry };
} else if (url.includes("456")) {
return { json: async () => userWithoutCountry };
}
throw new Error("Unexpected URL");
};
getUserData(123); // المخرجات: User is from: USA, Timezone: EST
getUserData(456); // المخرجات: User is from: Unknown Country, Timezone: GMT
أسبقية العوامل
لعامل دمج القيم الفارغة أسبقية منخفضة نسبيًا. إنها أقل من عاملي OR (||
) و AND (&&
). لذلك، عند دمج عامل دمج القيم الفارغة مع عوامل منطقية أخرى، من الضروري استخدام الأقواس لتحديد ترتيب العمليات بشكل صريح. قد يؤدي عدم القيام بذلك إلى أخطاء في الصياغة أو سلوك غير متوقع.
مثال: استخدام الأقواس للوضوح
// بدون أقواس (SyntaxError)
// const result = false || null ?? "Default"; // SyntaxError: Unexpected token '??'
// مع الأقواس (صحيح)
const result = false || (null ?? "Default");
console.log(result); // المخرجات: Default
const anotherResult = (false || null) ?? "Default";
console.log(anotherResult); // المخرجات: null
في المثال الأول، يؤدي عدم وجود الأقواس إلى SyntaxError
لأن محرك JavaScript لا يمكنه تحديد الترتيب المقصود للعمليات. بإضافة الأقواس، نخبر المحرك صراحة بتقييم عامل دمج القيم الفارغة أولاً. المثال الثاني صالح؛ ومع ذلك، فإن المخرجات مختلفة لأن تعبير ||
يتم تقييمه أولاً.
توافق المتصفحات
يعد عامل دمج القيم الفارغة (??
) ميزة جديدة نسبيًا، لذا من المهم مراعاة توافق المتصفحات، خاصة إذا كنت تستهدف المتصفحات القديمة. تدعم معظم المتصفحات الحديثة عامل دمج القيم الفارغة، بما في ذلك:
- Chrome 80+
- Firefox 72+
- Safari 13.1+
- Edge 80+
- Node.js 14+
إذا كنت بحاجة إلى دعم المتصفحات القديمة، فيمكنك استخدام مترجم مثل Babel لتحويل الكود الخاص بك إلى إصدار متوافق من JavaScript. سيقوم Babel بتحويل عامل ??
إلى كود JavaScript مكافئ يعمل في البيئات القديمة.
أفضل الممارسات
فيما يلي بعض أفضل الممارسات لاستخدام عامل دمج القيم الفارغة بفعالية:
- استخدم
??
للتحقق من القيم الفارغة: استخدم عامل دمج القيم الفارغة (??
) عندما تريد تحديدًا توفير قيمة افتراضية فقط عندما يكون المتغيرnull
أوundefined
. - استخدم الأقواس للتعبيرات المعقدة: عند دمج عامل دمج القيم الفارغة مع عوامل منطقية أخرى، استخدم الأقواس لتحديد ترتيب العمليات بوضوح.
- ضع في اعتبارك توافق المتصفح: تحقق من توافق المتصفح واستخدم مترجمًا إذا لزم الأمر لدعم المتصفحات القديمة.
- استخدمه باستمرار: اعتمد استخدام
??
عند الاقتضاء لأسلوب برمجة أكثر قابلية للتنبؤ في جميع أنحاء المشروع. - ادمجه مع التسلسل الاختياري: استخدم
??
بالاقتران مع التسلسل الاختياري?.
للوصول الآمن وتعيين قيم افتراضية للخصائص المتداخلة للكائنات.
الاعتبارات العالمية
عند التطوير لجمهور عالمي، ضع في اعتبارك النقاط التالية المتعلقة بتعيينات القيمة الافتراضية:
- الترجمة والتوطين (Localization): قد تحتاج القيم الافتراضية إلى التوطين بناءً على لغة المستخدم أو منطقته. على سبيل المثال، رمز عملة افتراضي أو تنسيق تاريخ.
- الأعراف الثقافية: قد تحتاج بعض القيم الافتراضية إلى التعديل بناءً على الأعراف الثقافية. على سبيل المثال، قد تحتاج رسالة ترحيب افتراضية إلى أن تكون مختلفة في الثقافات المختلفة.
- إمكانية الوصول (Accessibility): تأكد من أن القيم الافتراضية يمكن الوصول إليها وفهمها من قبل المستخدمين ذوي الإعاقة. قدم تسميات واضحة ووصفية للقيم الافتراضية في واجهات المستخدم.
- المناطق الزمنية والتواريخ: عند العمل مع التواريخ والأوقات، استخدم المناطق الزمنية وتنسيقات التاريخ المناسبة لضمان عرض القيم الافتراضية بشكل صحيح للمستخدمين في مناطق مختلفة.
مثال: التوطين مع دمج القيم الفارغة
لنفترض أنك تريد عرض رسالة ترحيب افتراضية بلغات مختلفة بناءً على لغة المستخدم. يمكنك استخدام عامل دمج القيم الفارغة لتوفير رسالة افتراضية إذا لم تكن هناك رسالة مترجمة متوفرة.
function getWelcomeMessage(locale) {
const localizedMessages = {
en: "Welcome!",
fr: "Bienvenue !",
de: "Willkommen!"
};
const message = localizedMessages[locale] ?? "Welcome!"; // الافتراضي إلى الإنجليزية إذا لم يتم العثور على اللغة
return message;
}
console.log(getWelcomeMessage("fr")); // المخرجات: Bienvenue !
console.log(getWelcomeMessage("es")); // المخرجات: Welcome! (الافتراضي إلى الإنجليزية)
الخاتمة
يعد عامل دمج القيم الفارغة (??
) إضافة قيمة إلى لغة JavaScript. إنه يوفر طريقة أكثر دقة وموثوقية لتعيين القيم الافتراضية مقارنة بعامل OR (||
)، خاصة عند التعامل مع قيم مثل 0
أو السلاسل النصية الفارغة. من خلال فهم صياغته وسلوكه وحالات استخدامه، يمكنك كتابة كود أنظف وأكثر قابلية للصيانة يتعامل بدقة مع تعيينات القيمة الافتراضية. تذكر أن تضع في اعتبارك توافق المتصفح، وأسبقية العوامل، والاعتبارات العالمية عند استخدام عامل دمج القيم الفارغة في مشاريعك.
باتباع أفضل الممارسات الموضحة في هذا الدليل، يمكنك الاستفادة بشكل فعال من عامل دمج القيم الفارغة لتحسين جودة وموثوقية كود JavaScript الخاص بك، مما يجعله أكثر قوة وأسهل للفهم. تذكر دائمًا إعطاء الأولوية للوضوح وقابلية الصيانة في الكود الخاص بك، ويمكن أن يكون عامل دمج القيم الفارغة أداة قوية في تحقيق هذه الأهداف.