۲۰ ژوئیه ۲۰۲۳

عملگر Nullish coalescing '??'

به تازگی اضافه شده است
این قسمت به تازگی به زبان اضافه شده است. مرورگرهای قدیمی ممکن است به پلیفیل نیاز داشته باشند.

عملگر nullish coalescing با دو علامت سوال ?? نوشته می‌شود.

به دلیل اینکه این عملگر با null و undefined به طور یکسان رفتار می‌کند، ما در این فصل از یک اصطلاح خاص استفاده می‌کنیم. می‌گوییم که یک عبارت “تعریف شده” است هرگاه که نه null باشد و نه undefined.

نتیجه‌ی a ?? b:

  • اگر a تعریف شده باشد، پس برابر با a است،
  • اگر a تعریف شده نباشد، پس برابر با b است.

به عبارتی دیگر، ?? اولین آرگومان را اگر null/undefined نباشد برمی‌گرداند. در غیر این صورت، آرگومان دوم برگردانده می‌شود.

عملگر nullish coalescing چیز کاملا جدیدی نیست. این عملگر تنها یک سینتکس برای گرفتن اولین مقدار “تعریف شده” از بین دو مقدار است.

ما می‌توانیم result = a ?? b را با استفاده از اپراتورهایی که از قبل می‌شناسیم دوباره به این شکل بنویسیم:

result = (a !== null && a !== undefined) ? a : b;

حال باید کاملا روشن باشد که ?? چه کاری انجام می‌دهد. بیایید ببینیم این عملگر کجا کمک‌مان می‌کند.

یک مورد متداول برای استفاده از ?? تعیین کردن مقداری پیش‌فرض برای متغیر است.

برای مثال، اینجا اگر مقدار user برابر با null/undefined نباشد آن را نشان می‌دهیم، در غیر این صورت Anonymous نشان داده می‌شود:

let user;

alert(user ?? "Anonymous"); // Anonymous (است undefined برابر با user)

در این مثال یک اسم به user تخصیص داده شده است:

let user = "John";

alert(user ?? "Anonymous"); // John (نیست null/udefined برابر با user)

همچنین می‌توانیم از توالی ?? برای انتخاب کردن اولین مقدار در یک لیست که null/undefined نباشد استفاده کنیم.

فرض کنیم که داده‌ی کاربری را در متغیرهای firstName، lastName یا nickName ذخیره کرده‌ایم. اگر کاربر تصمیم به وارد نکردن مقداری گرفته باشد، ممکن است همه آنها تعریف شده نباشند.

ما می‌خواهیم اسم کاربر را با استفاده از این متغیرها نمایش دهیم، یا اگر همه آن‌ها null/undefined باشند، “Anonymous” را نمایش دهیم.

بیایید برای این کار از عملگر ?? استفاده کنیم:

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// اولین مقدار تعریف شده را نمایش می‌دهد:
alert(firstName ?? lastName ?? nickName ?? "Anonymous"); // Supercoder

مقایسه با ||

عملگرِ “یا” || می‌تواند درست مانند عملگر ?? استفاده شود، همانطور که در بخش قبلی توضیح داده شد.

برای مثال ما می‌توانیم عملگر ?? را با عملگر || در کد بالا جایگزین کنیم و همان نتیجه را بگیریم:

let firstName = null;
let lastName = null;
let nickName = "Supercoder";

// :را نشان می‌دهد truthy اولین مقدار
alert(firstName || lastName || nickName || "Anonymous"); // Supercoder

از لحاظ تاریخی، عملگرِ یا || از اول وجود داشت. این عملگر از اولین روزهای جاوااسکریپت وجود داشت، بنابراین توسعه دهندگان به مدت طولانی برای چنین کارهایی از این عملگر استفاده می‌کردند.

از طرفی دیگر، عملگر nullish coalescing ?? به تازگی به جاوااسکریپت اضافه شد و دلیل آن هم این بود که افراد خیلی از || راضی نبودند.

مهم‌ترین تفاوت بین آنها موارد زیر هستند:

  • عملگر || اولین مقدار truthy را برمی‌گرداند.
  • عملگر ?? اولین مقدار تعریف شده را برمی‌گرداند.

به عبارتی دیگر، عملگر || تفاوت بین false، 0، یک رشته خالی "" و null/undefined را تشخیص نمی‌دهد. آنها همگی شبیه یکدیگر هستند – مقدارهای falsy. اگر هر کدام از اینها اولین آرگومان عملگر || باشند، ما آرگومان دوم را به عنوان نتیجه دریافت می‌کنیم.

اما در عمل، ممکن است بخواهیم مقداری پیش فرض را فقط در صورتی که متغیر null/undefined باشد استفاده کنیم. یعنی زمانی که مقدار واقعا ناشناخته یا تخصیص داده نشده باشد.

برای مثال، کد زیر را در نظر بگیرید:

let height = 0;

alert(height || 100); // 100
alert(height ?? 100); // 0
  • عبارت height || 100 متغیر height را برای اینکه مقداری falsy است یا نه بررسی می‌کند، که در واقع falsy است.
    • بنابراین نتیجه‌ی عملگر || آرگومان دوم است، 100.
  • عبارت height ?? 100 متغیر height را برای اینکه null/undefined است یا نه بررسی می‌کند، که هیچکدام نیست.
    • بنابراین نتیجه متغیر height “همانطور که هست” است، یعنی 0.

در عمل، مقدار صفر height معمولا یک مقدار قابل قبول است، که نباید با مقدار پیش فرض جابجا شود. پس عملگر ?? کار درست را اینجا انجام می‌دهد.

اولویت

اولویت عملگر ?? برابر با عملگر || است. اولویت آن‌ها در جدول MDN برابر با 3 است.

این یعنی که درست مانند ||، عملگر nullish coalescing ?? قبل از = و ? ارزیابی می‌شود، اما بعد از بیشتر عملیات‌ها مانند +، - ارزیابی می‌شود.

پس شاید ما نیاز داشته باشیم که در عباراتی مانند کد پایین پرانتز را اضافه کنیم:

let height = null;
let width = null;

// مهم: از پرانتز استفاده کنید
let area = (height ?? 100) * (width ?? 50);

alert(area); // 5000

در غیر این صورت، اگر پرانتز را حذف کنیم، چون * اولویت بالاتری نسبت به ?? دارد پس اول اجرا می‌شود و به نتیجه نادرستی منجر می‌شود.

// بدون پرانتز
let area = height ?? 100 * width ?? 50;

// اینگونه کار می‌کند (احتمالا چیزی که ما می‌خوانیم نیست)...
let area = height ?? (100 * width) ?? 50;

استفاده از ?? همراه با || و &&

به دلایل امنیتی، جاوااسکریپت استفاده از ?? را همراه با عملگرهای && و || منع می‌کند، مگر اینکه اولویت استفاده صراحتا با پرانتز مشخص شده باشد.

کد زیر یک خطای سینتکس به ما خواهد داد:

let x = 1 && 2 ?? 3; // Syntax error

این محدودیت قطعا قابل بحث است و با این هدف به خصوصیات زبان اضافه شد که وقتی افراد از || به ?? روی می‌آورند، از اشتباهات برنامه نویسی جلوگیری شود.

از پرانتز برای این کار استفاده کنید:

let x = (1 && 2) ?? 3; // به درستی کار می‌کند

alert(x); // 2

خلاصه

  • عملگر nullish coalescing ?? راه کوتاهی برای انتخاب اولین مقدار “تعریف شده” از یک لیست را فراهم می‌کند.

    از آن برای تعیین کردن مقدار پیش‌فرض برای متغیرها استفاده می‌شود:

    // را تنظیم کن height=100 ،بود undefined یا null برابر با height اگر
    height = height ?? 100;
  • عملگر ?? اولویت بسیار پایینی دارد و فقط از ? و = بالاتر است، پس هنگام استفاده از آن در یک عبارت اضافه کردن پرانتز را در نظر بگیرید.

  • استفاده کردن از این عملگر همراه با || یا && بدون استفاده کردن از پرانتز ممنوع است.

نقشه آموزش