تذكير سريع
تعرّفت بدرس العوامل على ?? (الدمج الصفري) و?. (السلسلة الاختيارية) كطريقتين للتعامل بأمان مع قيم قد تكون null/undefined. هذا الدرس يبني عليهما بأدوات أحدث توفّر أسطرًا كثيرة من الكود المتكرر.
عوامل الإسناد المنطقي 🌟
ثلاثة عوامل تدمج عاملًا منطقيًا مع الإسناد = بخطوة واحدة، وتُسنِد فقط عند تحقّق شرط معيّن — بعكس += التي تُسنِد دائمًا.
&&= — أسنِد فقط إذا كانت القيمة الحالية صحيحة (truthy)
let settings = { theme: "dark" };
settings.theme &&= "light"; // theme كانت truthy فتغيّرت
console.log(settings.theme); // "light"
let empty = "";
empty &&= "قيمة جديدة"; // empty فارغة (falsy) فلا يحدث إسناد
console.log(empty); // ""
مكافئة لـ x && (x = y) لكن x تُقيَّم مرة واحدة فقط.
||= — أسنِد فقط إذا كانت القيمة الحالية خاطئة (falsy)
الاستخدام الأشهر: قيمة افتراضية تُملأ مرة واحدة فقط إن كانت فارغة:
function greet(config) {
config.greeting ||= "أهلًا بك"; // يملأ فقط إن كانت falsy (فارغة، undefined...)
console.log(config.greeting);
}
greet({}); // أهلًا بك
greet({ greeting: "مرحبًا" }); // مرحبًا (لم تتغيّر)
??= — أسنِد فقط إذا كانت القيمة الحالية عدمية (null أو undefined) 🌟
أدق من ||= لأنها لا تعتبر 0 أو "" أو false أسبابًا للإسناد:
let cart = { discount: 0 };
cart.discount ||= 10; // ⚠️ discount = 0 وهي falsy، فتُستبدل خطأً بـ 10!
console.log(cart.discount); // 10 — خطأ منطقي لو كان 0 قيمة صحيحة مقصودة
let cart2 = { discount: 0 };
cart2.discount ??= 10; // 0 ليست null/undefined، فلا إسناد
console.log(cart2.discount); // 0 — صحيح، خصم صفر مقصود
جدول مقارنة سريع
| العامل | يُسنِد إذا كانت القيمة الحالية | مثال شائع |
|---|---|---|
&&= | truthy | تحديث قيمة موجودة فعلًا فقط |
||= | falsy (0, "", false, null, undefined...) | قيمة افتراضية بسيطة |
??= | null أو undefined فقط | قيمة افتراضية دقيقة لا تصطدم بـ 0/"" الصحيحة |
🔑 قاعدة عملية: إذا كانت
0أو""أوfalseقيمًا صالحة منطقيًا بحالتك (سعر صفر، نص فارغ مقصود)، استخدم??=لا||=.
السلسلة الاختيارية المتقدمة
تعرّفت على ?. مع خصائص الكائنات (user?.address?.city). تدعم أيضًا حالتين إضافيتين:
استدعاء دالة اختياري: ?.()
مفيد عندما لا تعرف مسبقًا إن كانت دالة موجودة (callback اختياري، دالة بمكتبة قد لا تكون مفعّلة):
function process(data, onComplete) {
// ينفّذ onComplete فقط إن كانت موجودة فعلًا، بدون if منفصل
onComplete?.(data);
}
process("نتيجة", (r) => console.log("انتهى:", r)); // ينفّذ
process("نتيجة"); // لا يرمي خطأ رغم عدم تمرير دالة
فهرسة اختيارية: ?.[]
مفيدة مع مفاتيح ديناميكية أو مصفوفات قد تكون null/undefined:
let responses = null;
let firstKey = "ar";
console.log(responses?.[firstKey]); // undefined بدل خطأ
console.log(responses?.[0]); // نفس الفكرة مع مصفوفات
دمج ?? مع ?. — نمط شائع جدًا
function getDisplayName(user) {
return user?.profile?.nickname ?? "زائر";
}
console.log(getDisplayName(null)); // "زائر"
console.log(getDisplayName({ profile: {} })); // "زائر" (nickname غير موجودة)
console.log(getDisplayName({ profile: { nickname: "سو" } })); // "سو"
أخطاء شائعة
- ❌ استخدام
||=مع قيم falsy صالحة منطقيًا (مثل0كسعر أو خصم فعلي) → يستبدلها بالخطأ. استخدم??=. - ❌ الظن أن
&&=تنشئ الخاصية إن لم تكن موجودة → لا تفعل؛ إن كانتundefined(falsy) فلن يحدث إسناد أصلًا لأنها تتطلب truthy. - ❌ نسيان
()بعد?.عند استدعاء دالة اختيارية →fn?.وحدها لا تستدعي شيئًا؛ الصيغة الصحيحةfn?.(). - ❌ خلط
??بعوامل&&/||مباشرة بدون أقواس مثلa && b ?? c→ خطأ صياغة بجافاسكريبت؛ يجب أقواس توضيحية(a && b) ?? c.
خلاصة
عوامل الإسناد المنطقي (&&=, ||=, ??=) تختصر أنماط "أسنِد فقط إذا..." الشائعة، مع ??= كالأدق للقيم الافتراضية. السلسلة الاختيارية تمتد أيضًا لاستدعاء الدوال ?.() والفهرسة ?.[]، وتتألق أكثر عند دمجها مع ?? لقيمة احتياطية نهائية.
🎯 التالي: الاستيراد الديناميكي وTop-Level Await.