العربية

أتقن عامل دمج القيم الفارغة (??) في 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، بينما يتحقق عامل 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 لا يمكنه تحديد الترتيب المقصود للعمليات. بإضافة الأقواس، نخبر المحرك صراحة بتقييم عامل دمج القيم الفارغة أولاً. المثال الثاني صالح؛ ومع ذلك، فإن المخرجات مختلفة لأن تعبير || يتم تقييمه أولاً.

توافق المتصفحات

يعد عامل دمج القيم الفارغة (??) ميزة جديدة نسبيًا، لذا من المهم مراعاة توافق المتصفحات، خاصة إذا كنت تستهدف المتصفحات القديمة. تدعم معظم المتصفحات الحديثة عامل دمج القيم الفارغة، بما في ذلك:

إذا كنت بحاجة إلى دعم المتصفحات القديمة، فيمكنك استخدام مترجم مثل Babel لتحويل الكود الخاص بك إلى إصدار متوافق من JavaScript. سيقوم Babel بتحويل عامل ?? إلى كود JavaScript مكافئ يعمل في البيئات القديمة.

أفضل الممارسات

فيما يلي بعض أفضل الممارسات لاستخدام عامل دمج القيم الفارغة بفعالية:

الاعتبارات العالمية

عند التطوير لجمهور عالمي، ضع في اعتبارك النقاط التالية المتعلقة بتعيينات القيمة الافتراضية:

مثال: التوطين مع دمج القيم الفارغة

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

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 الخاص بك، مما يجعله أكثر قوة وأسهل للفهم. تذكر دائمًا إعطاء الأولوية للوضوح وقابلية الصيانة في الكود الخاص بك، ويمكن أن يكون عامل دمج القيم الفارغة أداة قوية في تحقيق هذه الأهداف.