ÐпеÑаÑÐ¾Ñ Ð½Ñлевого ÑлиÑÐ½Ð¸Ñ (??)
ÐпеÑаÑÐ¾Ñ Ð½Ñлевого ÑлиÑÐ½Ð¸Ñ Ð¿ÑедÑÑавлÑÐµÑ Ñобой два вопÑоÑиÑелÑнÑÑ
знака ??.
Так как он обÑабаÑÑÐ²Ð°ÐµÑ null и undefined одинаковÑм обÑазом, Ñо Ð´Ð»Ñ ÑÑой ÑÑаÑÑи Ð¼Ñ Ð²Ð²ÐµÐ´Ñм ÑпеÑиалÑнÑй ÑеÑмин. ÐÐ»Ñ ÐºÑаÑкоÑÑи бÑдем говоÑиÑÑ, ÑÑо знаÑение «опÑеделено», еÑли оно не ÑавнÑеÑÑÑ Ð½Ð¸ null, ни undefined.
РезÑлÑÑÐ°Ñ Ð²ÑÑÐ°Ð¶ÐµÐ½Ð¸Ñ a ?? b бÑÐ´ÐµÑ ÑледÑÑÑим:
- еÑли
aопÑеделено, Ñоa, - еÑли
aне опÑеделено, Ñоb.
ÐнаÑе говоÑÑ, опеÑаÑÐ¾Ñ ?? возвÑаÑÐ°ÐµÑ Ð¿ÐµÑвÑй аÑгÑменÑ, еÑли он не null/undefined, инаÑе вÑоÑой.
ÐпеÑаÑÐ¾Ñ Ð½Ñлевого ÑлиÑÐ½Ð¸Ñ Ð½Ðµ ÑвлÑеÑÑÑ Ñем-Ñо пÑинÑипиалÑно новÑм. ÐÑо вÑего лиÑÑ ÑдобнÑй ÑинÑакÑиÑ, как из двÑÑ Ð·Ð½Ð°Ñений полÑÑиÑÑ Ð¾Ð´Ð½Ð¾, коÑоÑое «опÑеделено».
ÐÐ¾Ñ ÐºÐ°Ðº можно пеÑепиÑаÑÑ Ð²ÑÑажение result = a ?? b, иÑполÑзÑÑ Ñже знакомÑе нам опеÑаÑоÑÑ:
result = (a !== null && a !== undefined) ? a : b;
ТепеÑÑ Ð´Ð¾Ð»Ð¶Ð½Ð¾ бÑÑÑ Ð°Ð±ÑолÑÑно ÑÑно, ÑÑо Ð´ÐµÐ»Ð°ÐµÑ ??. ÐавайÑе поÑмоÑÑим, где ÑÑо Ð¼Ð¾Ð¶ÐµÑ Ð±ÑÑÑ Ð¿Ð¾Ð»ÐµÐ·Ð½Ð¾.
Ðак пÑавило, опеÑаÑÐ¾Ñ ?? нÑжен Ð´Ð»Ñ Ñого, ÑÑÐ¾Ð±Ñ Ð·Ð°Ð´Ð°ÑÑ Ð·Ð½Ð°Ñение по ÑмолÑÐ°Ð½Ð¸Ñ Ð´Ð»Ñ Ð¿Ð¾ÑенÑиалÑно неопÑеделÑнной пеÑеменной.
ÐапÑимеÑ, здеÑÑ Ð¼Ñ Ð¾ÑобÑазим user, еÑли ÐµÑ Ð·Ð½Ð°Ñение не null/undefined, в пÑоÑивном ÑлÑÑае Ðноним:
let user;
alert(user ?? "Ðноним"); // Ðноним (user не ÑÑÑеÑÑвÑеÑ)
Ð Ð²Ð¾Ñ Ð¿ÑимеÑ, когда user пÑиÑвоено знаÑение:
let user = "Ðван";
alert(user ?? "Ðноним"); // Ðван (user ÑÑÑеÑÑвÑеÑ)
ÐÑоме ÑÑого, можно запиÑаÑÑ Ð¿Ð¾ÑледоваÑелÑноÑÑÑ Ð¸Ð· опеÑаÑоÑов ??, ÑÑÐ¾Ð±Ñ Ð¿Ð¾Ð»ÑÑиÑÑ Ð¿ÐµÑвое знаÑение из ÑпиÑка, коÑоÑое не ÑвлÑеÑÑÑ null/undefined.
ÐопÑÑÑим, Ñ Ð½Ð°Ñ ÐµÑÑÑ Ð´Ð°Ð½Ð½Ñе полÑзоваÑÐµÐ»Ñ Ð² пеÑеменнÑÑ
firstName, lastName или nickName. ÐÑе они могÑÑ Ð½Ðµ ÑÑÑеÑÑвоваÑÑ, еÑли полÑзоваÑÐµÐ»Ñ ÑеÑил не вводиÑÑ ÑооÑвеÑÑÑвÑÑÑие знаÑение.
ÐÑ Ñ
оÑели Ð±Ñ Ð¾ÑобÑазиÑÑ Ð¸Ð¼Ñ Ð¿Ð¾Ð»ÑзоваÑелÑ, иÑполÑзÑÑ Ð¾Ð´Ð½Ñ Ð¸Ð· ÑÑиÑ
пеÑеменнÑÑ
, или показаÑÑ Â«Ðноним», еÑли вÑе они null/undefined.
ÐÐ»Ñ ÑÑого воÑполÑзÑемÑÑ Ð¾Ð¿ÐµÑаÑоÑом ??:
let firstName = null;
let lastName = null;
let nickName = "СÑпеÑкодеÑ";
// показÑÐ²Ð°ÐµÑ Ð¿ÐµÑвое знаÑение, коÑоÑое опÑеделено:
alert(firstName ?? lastName ?? nickName ?? "Ðноним"); // СÑпеÑкодеÑ
СÑавнение Ñ ||
ÐпеÑаÑÐ¾Ñ ÐÐÐ || можно иÑполÑзоваÑÑ Ð´Ð»Ñ Ñого же, ÑÑо и ??, как ÑÑо бÑло показано в пÑедÑдÑÑей главе.
ÐапÑимеÑ, еÑли в пÑиведÑнном вÑÑе коде замениÑÑ ?? на ||, Ñо бÑÐ´ÐµÑ ÑÐ¾Ñ Ð¶Ðµ ÑамÑй ÑезÑлÑÑаÑ:
let firstName = null;
let lastName = null;
let nickName = "СÑпеÑкодеÑ";
// показÑÐ²Ð°ÐµÑ Ð¿ÐµÑвое иÑÑинное знаÑение:
alert(firstName || lastName || nickName || "Ðноним"); // СÑпеÑкодеÑ
ÐÑÑоÑиÑеÑки ÑложилоÑÑ Ñак, ÑÑо опеÑаÑÐ¾Ñ ÐÐÐ || поÑвилÑÑ Ð¿ÐµÑвÑм. Ðн ÑÑÑеÑÑвÑÐµÑ Ñ Ñамого наÑала в JavaScript, поÑÑÐ¾Ð¼Ñ ÑазÑабоÑÑики долгое вÑÐµÐ¼Ñ Ð¸ÑполÑзовали его Ð´Ð»Ñ ÑакиÑ
Ñелей.
С дÑÑгой ÑÑоÑонÑ, ÑÑавниÑелÑно недавно в ÑзÑк бÑл добавлен опеÑаÑÐ¾Ñ Ð½Ñлевого ÑлиÑÐ½Ð¸Ñ ?? â как Ñаз поÑомÑ, ÑÑо многие бÑли недоволÑÐ½Ñ Ð¾Ð¿ÐµÑаÑоÑом ||.
Ðажное ÑазлиÑие Ð¼ÐµÐ¶Ð´Ñ Ð½Ð¸Ð¼Ð¸ заклÑÑаеÑÑÑ Ð² Ñом, ÑÑо:
||возвÑаÑÐ°ÐµÑ Ð¿ÐµÑвое иÑÑинное знаÑение.??возвÑаÑÐ°ÐµÑ Ð¿ÐµÑвое опÑеделÑнное знаÑение.
ÐÑоÑе говоÑÑ, опеÑаÑÐ¾Ñ || не ÑазлиÑÐ°ÐµÑ false, 0, пÑÑÑÑÑ ÑÑÑÐ¾ÐºÑ "" и null/undefined. ÐÐ»Ñ Ð½ÐµÐ³Ð¾ они вÑе одинаковÑ, Ñ.е. ÑвлÑÑÑÑÑ Ð»Ð¾Ð¶Ð½Ñми знаÑениÑми. ÐÑли пеÑвÑм аÑгÑменÑом Ð´Ð»Ñ Ð¾Ð¿ÐµÑаÑоÑа || бÑÐ´ÐµÑ Ð»Ñбое из пеÑеÑиÑленнÑÑ
знаÑений, Ñо в каÑеÑÑве ÑезÑлÑÑаÑа Ð¼Ñ Ð¿Ð¾Ð»ÑÑим вÑоÑой аÑгÑменÑ.
Ðднако на пÑакÑике ÑаÑÑо ÑÑебÑеÑÑÑ Ð¸ÑполÑзоваÑÑ Ð·Ð½Ð°Ñение по ÑмолÑÐ°Ð½Ð¸Ñ ÑолÑко Ñогда, когда пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ ÑвлÑеÑÑÑ null/undefined. ÐÐµÐ´Ñ Ð¸Ð¼ÐµÐ½Ð½Ð¾ Ñогда знаÑение дейÑÑвиÑелÑно неизвеÑÑно/не опÑеделено.
РаÑÑмоÑÑим ÑледÑÑÑий пÑимеÑ:
let height = 0;
alert(height || 100); // 100
alert(height ?? 100); // 0
height || 100пÑовеÑÑеÑheightна ложное знаÑение, оно Ñавно0, да, ложное.- поÑÑÐ¾Ð¼Ñ ÑезÑлÑÑаÑом
||ÑвлÑеÑÑÑ Ð²ÑоÑой аÑгÑменÑ, Ñ.е.100.
- поÑÑÐ¾Ð¼Ñ ÑезÑлÑÑаÑом
height ?? 100пÑовеÑÑеÑ, ÑÑо пеÑеменнаÑheightÑодеÑжиÑnull/undefined, а поÑколÑÐºÑ ÑÑо не Ñак,- Ñо ÑезÑлÑÑаÑом ÑвлÑеÑÑÑ Ñама пеÑеменнаÑ
height, Ñ.е.0.
- Ñо ÑезÑлÑÑаÑом ÑвлÑеÑÑÑ Ñама пеÑеменнаÑ
Ðа пÑакÑике нÑÐ»ÐµÐ²Ð°Ñ Ð²ÑÑоÑа ÑаÑÑо ÑвлÑеÑÑÑ Ð²Ð¿Ð¾Ð»Ð½Ðµ ноÑмалÑнÑм знаÑением, коÑоÑое не ÑледÑÐµÑ Ð·Ð°Ð¼ÐµÐ½ÑÑÑ Ð·Ð½Ð°Ñением по ÑмолÑаниÑ. Таким обÑазом, ?? здеÑÑ ÐºÐ°Ðº Ñаз ÑабоÑÐ°ÐµÑ Ñак, как нÑжно.
ÐÑиоÑиÑеÑ
ÐÑиоÑиÑÐµÑ Ð¾Ð¿ÐµÑаÑоÑа ?? Ñакой же, как и Ñ ||. Ðни оба ÑÐ°Ð²Ð½Ñ 3 в ÑаблиÑе на MDN.
ÐÑо ознаÑаеÑ, ÑÑо, как и ||, опеÑаÑÐ¾Ñ Ð½Ñлевого ÑлиÑÐ½Ð¸Ñ ?? вÑÑиÑлÑеÑÑÑ Ð´Ð¾ = и ?, но поÑле болÑÑинÑÑва дÑÑгиÑ
опеÑаÑий, ÑакиÑ
как +, *.
Так ÑÑо, в вÑÑажениÑÑ Ñакого вида понадобÑÑÑÑ Ñкобки:
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;
ÐÑполÑзование ?? вмеÑÑе Ñ && или ||
Ðо ÑообÑажениÑм безопаÑноÑÑи JavaScript запÑеÑÐ°ÐµÑ Ð¸ÑполÑзование опеÑаÑоÑа ?? вмеÑÑе Ñ && и ||, еÑли пÑиоÑиÑÐµÑ Ñвно не Ñказан пÑи помоÑи кÑÑглÑÑ
Ñкобок.
ÐÑполнение ÑледÑÑÑего кода пÑиведÑÑ Ðº ÑинÑакÑиÑеÑкой оÑибке:
let x = 1 && 2 ?? 3; // СинÑакÑиÑеÑÐºÐ°Ñ Ð¾Ñибка
ÐÑо, безÑÑловно, ÑпоÑное огÑаниÑение бÑло добавлено в ÑпеÑиÑикаÑÐ¸Ñ ÑзÑка Ñ ÑелÑÑ Ð¸Ð·Ð±ÐµÐ¶Ð°ÑÑ Ð¿ÑогÑаммнÑе оÑибки, когда лÑди наÑнÑÑ Ð¿ÐµÑеÑ
одиÑÑ Ñ || на ??.
ÐÑполÑзÑйÑе Ñкобки, ÑÑÐ¾Ð±Ñ Ð¾Ð±Ð¾Ð¹Ñи ÑÑо огÑаниÑение:
let x = (1 && 2) ?? 3; // РабоÑÐ°ÐµÑ Ð±ÐµÐ· оÑибок
alert(x); // 2
ÐпеÑаÑÐ¾Ñ Ð½Ñлевого пÑиÑÐ²Ð°Ð¸Ð²Ð°Ð½Ð¸Ñ (??=)
ÐÑедположим, нам необÑ
одимо пÑовеÑиÑÑ, Ñавна ли пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ null или undefined, и еÑли ÑÑо Ñак â пÑиÑвоиÑÑ ÑÑой пеÑеменной какое-либо дÑÑгое знаÑение.
ÐÐ¾Ñ ÐºÐ°Ðº Ð¼Ñ Ñделали Ð±Ñ ÑÑо ÑейÑаÑ:
let userAge = null;
if (userAge === null || userAge === undefined) {
userAge = 18;
}
ÐÑглÑÐ´Ð¸Ñ Ð³Ñомоздко, пÑавда? СÑÑеÑÑвÑÐµÑ Ð¾Ð¿ÐµÑаÑоÑ, более Ð¿Ð¾Ð´Ñ Ð¾Ð´ÑÑий Ð´Ð»Ñ Ð¿Ð¾Ð´Ð¾Ð±Ð½ÑÑ Ð·Ð°Ð´Ð°Ñ. ÐÐ¾Ñ ÐµÐ³Ð¾ ÑинÑакÑиÑ:
x ??= y
ÐпеÑаÑÐ¾Ñ ??= пÑиÑÐ²Ð¾Ð¸Ñ x знаÑение y ÑолÑко в Ñом ÑлÑÑае, еÑли x не опÑеделено (null/undefined).
ТепеÑÑ Ð¿Ð¾Ð¿ÑобÑем пеÑепиÑаÑÑ Ñже знакомÑй нам ÑÑÐ°Ð³Ð¼ÐµÐ½Ñ ÐºÐ¾Ð´Ð° иÑполÑзÑÑ Ð½Ð¾Ð²Ñй опеÑаÑоÑ:
let userAge = null;
userAge ??= 18;
alert(userAge) // 18
ÐбÑаÑиÑе внимание: еÑли Ð±Ñ userAge не бÑл Ñавен null/undefined, Ñо вÑÑажение ÑпÑава Ð¾Ñ ??= никогда Ð±Ñ Ð½Ðµ вÑполнилоÑÑ:
let userAge = 18;
userAge ??= alert("не ÑÑабоÑаеÑ");
userAge ??= 21;
userAge ??= null;
alert(userAge) // по-пÑÐµÐ¶Ð½ÐµÐ¼Ñ 18
ÐÑого
-
ÐпеÑаÑÐ¾Ñ Ð½Ñлевого ÑлиÑниÑ
??â ÑÑо бÑÑÑÑÑй ÑпоÑоб вÑбÑаÑÑ Ð¿ÐµÑвое «опÑеделÑнное» знаÑение из ÑпиÑка.ÐÑполÑзÑеÑÑÑ Ð´Ð»Ñ Ð¿ÑиÑÐ²Ð¾ÐµÐ½Ð¸Ñ Ð¿ÐµÑеменнÑм знаÑений по ÑмолÑаниÑ:
// бÑÐ´ÐµÑ height=100, еÑли пеÑÐµÐ¼ÐµÐ½Ð½Ð°Ñ height Ñавна null или undefined height = height ?? 100; -
ÐпеÑаÑоÑ
??Ð¸Ð¼ÐµÐµÑ Ð¾ÑÐµÐ½Ñ Ð½Ð¸Ð·ÐºÐ¸Ð¹ пÑиоÑиÑеÑ, лиÑÑ Ð½ÐµÐ¼Ð½Ð¾Ð³Ð¾ вÑÑе, Ñем Ñ?и=, поÑÑÐ¾Ð¼Ñ Ð¿Ñи иÑполÑзовании его в вÑÑажении, ÑкоÑее вÑего, поÑÑебÑÑÑÑÑ Ñкобки. -
ÐапÑеÑено иÑполÑзоваÑÑ Ð²Ð¼ÐµÑÑе Ñ
||или&&без Ñвно Ñказанного пÑиоÑиÑеÑа, Ñо еÑÑÑ Ð±ÐµÐ· Ñкобок. -
ÐÐ»Ñ Ð¿ÑиÑÐ²Ð¾ÐµÐ½Ð¸Ñ Ð¿ÐµÑеменной знаÑÐµÐ½Ð¸Ñ Ð² завиÑимоÑÑи Ð¾Ñ Ñого, «опÑеделена» она или неÑ, иÑполÑзÑеÑÑÑ Ð¾Ð¿ÐµÑаÑÐ¾Ñ Ð½Ñлевого пÑиÑваиваниÑ
??=.
ÐомменÑаÑии
<code>, Ð´Ð»Ñ Ð½ÐµÑколÑÐºÐ¸Ñ ÑÑÑок кода — Ñег<pre>, еÑли болÑÑе 10 ÑÑÑок — ÑÑÑÐ»ÐºÑ Ð½Ð° пеÑоÑниÑÑ (plnkr, JSBin, codepenâ¦)