عملگر 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;
-
عملگر
??
اولویت بسیار پایینی دارد و فقط از?
و=
بالاتر است، پس هنگام استفاده از آن در یک عبارت اضافه کردن پرانتز را در نظر بگیرید. -
استفاده کردن از این عملگر همراه با
||
یا&&
بدون استفاده کردن از پرانتز ممنوع است.