IlmHamroh
JavaScript Full-stack/8-qism. JavaScript asoslari15/61-dars14 daqiqa
Mundarija (28)

JavaScript ?? va ?. operatorlari: nullish coalescing, optional chaining va mantiqiy tayinlash

Qisqacha: Nullish coalescing operatori ?? chap tomon faqat null yoki undefined bo'lsa zaxira qiymatni oladi. U || dan farqli ravishda 0 va "" ni saqlab qoladi. Optional chaining ?. esa qiymat null yoki undefined bo'lsa, xato bermay undefined qaytaradi. Mantiqiy tayinlash (??=, ||=, &&=) — shu operatorlarning tayinlash bilan birlashgan qisqa shakli.

Bu darsda

  • ?? bilan 0 va "" ni yo'qotmaydigan default qiymat bera olasiz.
  • ?? va || farqini tushuntira olasiz va qachon qaysi biri kerakligini bilasiz.
  • ?. bilan "yo'q" qiymatdan xatosiz ma'lumot o'qiy olasiz.
  • ??=, ||= va &&= mantiqiy tayinlash operatorlarini ishlata olasiz.
  • Bu operatorlar bilan bog'liq uchta sintaksis xatosini taniysiz.

Oldin bilishingiz kerak: Mantiqiy operatorlar va qisqa tutashuv, undefined va null, Arifmetik va tayinlash operatorlari.

1. Nega bu kerak?

O'tgan darsdagi choyxona misolini eslang. Mijoz shakarsiz choy xohladi va 0 ni tanladi. || esa baribir 2 qoshiq soldi:

js
const tanlanganShakar = 0;

console.log(tanlanganShakar || 2); // 2

Sababi: || hamma falsy qiymatni "yo'q" deb hisoblaydi. 0 esa falsy. Lekin bu yerda 0 — "yo'q" emas, mijozning aniq tanlovi.

Bizga boshqa savol beradigan operator kerak. "Qiymat falsymi?" emas, "qiymat umuman bormi?" deb so'raydigan. Ya'ni faqat null yoki undefined bo'lganda zaxiraga o'tadigan.

Ikkinchi muammo ham bor. "Yo'q" qiymatning ichidan ma'lumot o'qimoqchi bo'lsangiz, dastur xato berib to'xtaydi. Bu darsda ikkala muammoning yechimini ko'ramiz.

2. ?? — nullish coalescing

2.1 Faqat null va undefined uchun zaxira

Nullish — "null yoki undefined" degani. Inglizcha "nullga o'xshash" ma'nosida. null va undefined — ikkalasi ham nullish, boshqa hech bir qiymat nullish emas.

Nullish coalescing operatori (??) — chap tomon nullish bo'lsa, o'ng tomonni qaytaradi. Aks holda chap tomonning o'zini. Uni undefined va null darsida qisqa ko'rgan edik — endi to'liq o'rganamiz. "Coalescing" — "birlashtirish" degani, lekin nomni eslab qolish shart emas. Ko'pchilik uni shunchaki "ikki so'roq" deydi.

O'xshatish: pochta qutisi. || qutini ochganda ichida bo'sh konvert bo'lsa ham "xat yo'q" deydi. ?? esa faqat quti umuman bo'sh bo'lsa "xat yo'q" deydi. Bo'sh konvert ham — xat.

Choyxona misolini tuzatamiz:

js
const tanlanganShakar = 0;
const shakar = tanlanganShakar ?? 2;

console.log(shakar); // 0

Endi mijoz shakarsiz choy oladi. 0 nullish emas, shuning uchun ?? uni o'zgartirmadi.

Mijoz hech narsa tanlamagan bo'lsa-chi? Unda qiymat undefined bo'ladi va zaxira ishlaydi:

js
let tanlanganShakar;
const shakar = tanlanganShakar ?? 2;

console.log(shakar); // 2

2.2 ?? va ||: yonma-yon

Farqni bitta jadvalda ko'ramiz. Har bir qatorda x || "zaxira" va x ?? "zaxira" natijasi:

x qiymati "yoki" bilan ?? bilan
null "zaxira" "zaxira"
undefined "zaxira" "zaxira"
0 "zaxira" 0
"" "zaxira" ""
false "zaxira" false
NaN "zaxira" NaN
"Ali" "Ali" "Ali"

Ko'ryapsizmi? Farq faqat o'rtadagi to'rt qatorda — 0, "", false va NaN da. Ular falsy, lekin nullish emas.

Kodda tekshiramiz:

js
console.log(0 || 100); // 100
console.log(0 ?? 100); // 0
console.log(false || "zaxira"); // zaxira
console.log(false ?? "zaxira"); // false
console.log(null ?? "zaxira"); // zaxira

Bo'sh satr bilan ham xuddi shunday. ?? uni saqlab qoladi:

js
const izoh = "";

console.log("Izoh:", izoh ?? "izoh yo'q"); // Izoh:
console.log("Izoh:", izoh || "izoh yo'q"); // Izoh: izoh yo'q

Birinchi qatorda "Izoh:" dan keyin hech narsa yo'q — bo'sh satr o'zgarmay chiqdi.

O'zingiz to'ldiring: 0 ?? 7 ning natijasi [:0], undefined ?? 7 niki esa [:7].

2.3 Qachon ??, qachon ||?

Ikkalasi ham kerak — vazifasi har xil.

Vaziyat Tanlov
0, "" yoki false — haqiqiy qiymat ??
Bo'sh satr ham "yo'q" deb hisoblansin ||

?? uchun misollar: narx (0 — bepul), soni (0 ta), ovoz balandligi (0 — o'chirilgan), "bildirishnoma yoqilganmi?" (false).

|| uchun misol: foydalanuvchi ismini bo'sh qoldirdi. Uni "Mehmon" deb chaqirish mantiqan to'g'ri — bo'sh ism bilan salomlashish g'alati.

Shubha bo'lsa — ?? ni tanlang. U faqat haqiqiy "yo'qlik"ka javob beradi va kutilmagan almashtirish qilmaydi.

2.4 Zanjir va qisqa tutashuv

?? ham zanjir bo'la oladi. Birinchi nullish bo'lmagan qiymat olinadi:

js
let shaxsiyNarx;
const aksiyaNarxi = null;
const odatiyNarx = 12000;

console.log(shaxsiyNarx ?? aksiyaNarxi ?? odatiyNarx); // 12000

?? ham && va || kabi qisqa tutashuv qiladi. Chap tomon nullish bo'lmasa, o'ng tomon umuman bajarilmaydi:

js
"Ali" ?? console.log("Bu chiqmaydi");
null ?? console.log("Bu chiqadi");

Konsolda:

text
Bu chiqadi

Tekshirib ko'ring: const chegirma = 0; bo'lsa, console.log(chegirma ?? 5000) va console.log(chegirma || 5000) nima chiqaradi?

Javob

Birinchisi 0, ikkinchisi 5000. ?? faqat null va undefined da zaxiraga o'tadi, 0 esa ular qatoriga kirmaydi. || esa 0 ni falsy deb, zaxirani oldi. Agar "chegirma yo'q" ma'nosida 0 qo'yilgan bo'lsa, || xato natija beradi.

3. ?. — optional chaining

3.1 Obyektni eslaymiz

?. obyekt bilan ishlaydi. Obyektni ma'lumot turlari darsida ko'rgan edik: bir nechta qiymatni nomlari bilan birga saqlaydigan quti. Eslab olamiz (to'liq — obyektlar darsida):

js
const buyurtma = { taom: "Plov", narx: 35000 };

console.log(buyurtma.taom); // Plov
console.log(buyurtma.narx); // 35000
console.log(buyurtma.ichimlik); // undefined
  • Jingalak qavs { } ichida nom: qiymat juftliklari yoziladi, vergul bilan ajratiladi.
  • Har bir juftlik — xususiyat (property). taom va narx — buyurtma ning xususiyatlari.
  • Xususiyat nuqta bilan olinadi: buyurtma.taom — "buyurtmaning taomi".
  • Yo'q xususiyatni so'rasangiz, xato chiqmaydi — shunchaki undefined keladi.

Hozircha shu yetarli.

3.2 Muammo: "yo'q"ning ichiga qarash

Endi mijoz hali hech narsa buyurtma qilmagan. Buyurtma o'rnida null turibdi:

js
const buyurtma = null;

console.log(buyurtma.taom);
console.log("Bu qator ishlamaydi");
text
TypeError: Cannot read properties of null (reading 'taom')

Tarjimasi: "null ning xususiyatlarini o'qib bo'lmaydi (taom ni o'qishda)". null — quti emas, "hech narsa". Hech narsaning ichida taom bo'lmaydi. JavaScript xato beradi va dastur shu joyda to'xtaydi — keyingi qator ham ishlamaydi.

undefined bilan ham xuddi shunday: Cannot read properties of undefined. Bu xatoni undefined va null darsida ko'rgan edik — JavaScript'da eng ko'p uchraydigan xatolardan biri. Endi uning oldini olishni o'rganamiz.

3.3 Yechim: ?.

Optional chaining (?.) — "ixtiyoriy zanjir". Nuqta o'rniga ?. yozasiz. Chap tomon nullish bo'lsa, JavaScript o'ng tomonga qaramaydi va darhol undefined qaytaradi. Aks holda oddiy nuqta kabi ishlaydi.

js
const buyurtma = null;

console.log(buyurtma?.taom); // undefined
console.log("Dastur davom etyapti");

Konsolda:

text
undefined
Dastur davom etyapti

Xato yo'q! ?. "buyurtma bormi?" deb so'radi. Javob "yo'q" bo'lgani uchun taom ni qidirmadi.

?. va ?? birga ajoyib ishlaydi. undefined o'rniga tushunarli matn chiqaramiz:

js
let buyurtma = null;
console.log(buyurtma?.taom ?? "Hali yo'q"); // Hali yo'q

buyurtma = { taom: "Manti", narx: 30000 };
console.log(buyurtma?.taom ?? "Hali yo'q"); // Manti

Birinchi holatda buyurtma?.taom — undefined, shuning uchun ?? zaxirani oldi. Ikkinchisida buyurtma bor va ?. oddiy nuqta kabi ishladi.

Diqqat: ?. faqat o'zidan chapdagi qiymatni tekshiradi. Obyekt bor bo'lsa-yu, xususiyat yo'q bo'lsa — ?. shart emas, oddiy nuqta ham undefined beradi (yuqoridagi ichimlik misolini eslang). Xato faqat nuqtadan oldingi qiymat null yoki undefined bo'lganda chiqadi.

3.4 ?. ning boshqa shakllari

?. yana ikki ko'rinishda uchraydi. Ular hali o'tilmagan mavzular bilan bog'liq, shuning uchun hozir faqat tanib olsangiz yetarli:

js
royxat?.[0]      // ro'yxat bo'lsa — birinchi element
xabarYubor?.()   // funksiya bo'lsa — uni chaqir
  • ?.[ ] — massivlar bilan: massiv null bo'lsa, xato o'rniga undefined.
  • ?.() — funksiyalar bilan: funksiya yo'q bo'lsa, chaqirmaydi va undefined qaytaradi.

Qoida uchalasida bir xil: ?. dan chapdagi narsa nullish bo'lsa — to'xta, undefined qaytar.

Maslahat: ?. ni hamma joyga qo'yib chiqmang. Qiymat albatta bo'lishi kerak bo'lgan joyda u xatoni yashiradi. Dastur jim undefined bilan ishlashda davom etadi. Siz esa xatoni kechroq, boshqa joyda topasiz. Shuning uchun ?. ni faqat qiymat yo'q bo'lishi normal holat bo'lgan joyda ishlating.

Tekshirib ko'ring: const mijoz = undefined; bo'lsa, console.log(mijoz?.ism) va console.log(mijoz.ism) nima qiladi?

Javob

Birinchisi undefined chiqaradi: ?. chap tomon nullish ekanini ko'rib, to'xtadi. Ikkinchisi xato beradi: TypeError: Cannot read properties of undefined (reading 'ism'), chunki oddiy nuqta undefined ning ichiga qarashga urindi.

4. Mantiqiy tayinlash: ||=, &&=, ??=

4.1 += ni eslang

Tayinlash operatorlari darsida += ni ko'rgansiz: narx += 1000 — bu narx = narx + 1000 ning qisqa shakli.

Mantiqiy operatorlarning ham shunday qisqa shakli bor. Ular mantiqiy tayinlash operatorlari (logical assignment) deb ataladi:

Operator Ma'nosi Qachon yozadi
a ??= b a ?? (a = b) a nullish bo'lsa
a ||= b a || (a = b) a falsy bo'lsa
a &&= b a && (a = b) a truthy bo'lsa

Oddiy tilda:

  • ??= — "qiymat yo'q bo'lsa, shuni qo'y".
  • ||= — "qiymat falsy bo'lsa, shuni qo'y".
  • &&= — "qiymat bor bo'lsa, uni yangisiga almashtir".

4.2 ??= — standart qiymat qo'yish

Ilova sozlamalari. Foydalanuvchi tilni tanlamagan bo'lsa — o'zbekcha bo'lsin:

js
let til; // hali tanlanmagan
til ??= "uz";

console.log(til); // uz

til — undefined, shuning uchun "uz" yozildi. Agar foydalanuvchi allaqachon "ru" ni tanlagan bo'lsa, ??= unga tegmaydi.

Endi ??= va ||= farqini ko'ramiz. Ovoz balandligi 0 — foydalanuvchi ovozni ataylab o'chirgan:

js
let ovoz = 0;
ovoz ??= 50;
console.log(ovoz); // 0

ovoz ||= 50;
console.log(ovoz); // 50

??= 0 ni hurmat qildi. ||= esa uni "yo'q" deb, 50 ga almashtirdi — foydalanuvchining tanlovi yo'qoldi. Xuddi ?? va || dagi farq.

4.3 &&= — faqat qiymat bo'lsa yangilash

&&= kamroq uchraydi. U "qiymat bor bo'lsa, uni o'zgartir; yo'q bo'lsa — tegma" degani.

Bayram kuni har bir mijozning bonusi 5000 so'mga oshadi. Lekin bonusi yo'q (null) mijozga bonus berilmaydi:

js
let aliBonusi = 20000;
let valiBonusi = null;

aliBonusi &&= aliBonusi + 5000;
valiBonusi &&= valiBonusi + 5000;

console.log(aliBonusi); // 25000
console.log(valiBonusi); // null

valiBonusi falsy, shuning uchun o'ng tomon bajarilmadi. Oddiy valiBonusi = valiBonusi + 5000 yozganimizda nima bo'lardi? null + 5000 — 5000, ya'ni Vali kutilmaganda bonus olardi.

4.4 Nozik detal: keraksiz tayinlash bo'lmaydi

a ||= b va a = a || b deyarli bir xil. Lekin farq bor: ||= tayinlashni faqat kerak bo'lganda bajaradi. Bu qisqa tutashuvning natijasi.

Buni const bilan ko'rish mumkin. const ga qayta qiymat yozib bo'lmaydi. Lekin tayinlash kerak bo'lmasa, xato ham chiqmaydi:

js
const shahar = "Toshkent";
shahar ||= "Samarqand";

console.log(shahar); // Toshkent

shahar truthy — tayinlash umuman bajarilmadi, xato yo'q. Qiymat falsy bo'lsa esa tayinlashga urinadi:

js
const shahar = "";
shahar ||= "Samarqand";
text
TypeError: Assignment to constant variable.

Tarjimasi: "o'zgarmas o'zgaruvchiga qiymat tayinlash". Xulosa: mantiqiy tayinlash operatorlarini let bilan ishlating — ular o'zgaruvchini o'zgartirish uchun.

Tekshirib ko'ring: let soni = 0; bo'lsa, soni ??= 10; va soni ||= 10; dan keyin soni qiymati qanday bo'ladi (har birini alohida bajarsak)?

Javob

soni ??= 10 dan keyin — 0, chunki 0 nullish emas. soni ||= 10 dan keyin — 10, chunki 0 falsy. Qiymat nol bo'lishi mumkin bo'lgan joyda ??= xavfsizroq.

5. Ko'p uchraydigan xatolar

5.1 ?? ni || yoki && bilan qavssiz aralashtirish

js
const ism = null;
const taxallus = "";
const murojaat = ism ?? taxallus || "Mehmon";
text
SyntaxError: Unexpected token '||'

Tarjimasi: "kutilmagan belgi: ||". Nega aynan ||? JavaScript'da ?? ni || yoki && bilan qavssiz birga yozish taqiqlangan. Chunki qaysi biri avval bajarilishi odamlar uchun chalkash. JavaScript ism ?? taxallus ni o'qib, keyin || ni ko'rdi va to'xtadi.

Tuzatish — qavs bilan niyatingizni aniq ko'rsating:

js
const ism = null;
const taxallus = "";
const murojaat = (ism ?? taxallus) || "Mehmon";

console.log(murojaat); // Mehmon

5.2 ?. ni tayinlashning chap tomoniga yozish

?. faqat o'qish uchun. U bilan qiymat yozib bo'lmaydi:

js
let buyurtma = null;
buyurtma?.taom = "Lag'mon";
text
SyntaxError: Invalid left-hand side in assignment

Tarjimasi: "tayinlashning chap tomoni noto'g'ri". = ning chap tomonida qiymat yoziladigan aniq joy bo'lishi kerak. buyurtma?.taom esa undefined bo'lib qolishi mumkin — undefined ga yozib bo'lmaydi.

5.3 E'lon qilinmagan o'zgaruvchi bilan ?.

?. faqat null va undefined dan himoya qiladi. Umuman e'lon qilinmagan nomdan himoya qilmaydi:

js
console.log(mijozz?.ism);
text
ReferenceError: mijozz is not defined

Tarjimasi: "mijozz aniqlanmagan". Bu yerda nom xato yozilgan — ikkita z. ?. bunday xatoni yashirmaydi, va bu yaxshi: nomdagi xatoni darhol ko'rasiz.

5.4 ?? o'rniga || yozib, 0 ni yo'qotish

Narx, soni, ball, foiz — nol bo'lishi mumkin bo'lgan har qanday son uchun || zaxira xavfli. Bunday joyda doim ?? yoki ??= ishlating.

6. Mashqlar

1-mashq (oson): ?? yoki ||?

Ishga tushirmasdan natijani yozing, keyin tekshiring.

js
console.log(null ?? "A");
console.log(0 ?? "B");
console.log(0 || "C");
console.log(false ?? "D");
console.log(undefined || "E");
console.log("Nodira" ?? "F");
Yechim
js
console.log(null ?? "A"); // A
console.log(0 ?? "B"); // 0
console.log(0 || "C"); // C
console.log(false ?? "D"); // false
console.log(undefined || "E"); // E
console.log("Nodira" ?? "F"); // Nodira

?? faqat null va undefined da o'ng tomonga o'tadi. 0 va false — nullish emas, shuning uchun ular o'zi qaytdi. || esa 0 ni falsy deb tashlab ketdi.

2-mashq (o'rta): Ilova sozlamalari

Foydalanuvchi sozlamalari:

js
let ovoz = 0;      // ataylab o'chirilgan
let tema;          // tanlanmagan
let shrift = null; // tozalangan

Uchala o'zgaruvchiga ??= bilan standart qiymat bering: ovoz — 50, tema — "yorug'", shrift — 16. Keyin uchalasini console.log("Ovoz:", ovoz) kabi chiqaring.

Qaysi biri o'zgarmay qoladi va nega?

Yechim
js
let ovoz = 0;
let tema;
let shrift = null;

ovoz ??= 50;
tema ??= "yorug'";
shrift ??= 16;

console.log("Ovoz:", ovoz); // Ovoz: 0
console.log("Tema:", tema); // Tema: yorug'
console.log("Shrift:", shrift); // Shrift: 16

ovoz o'zgarmadi: 0 — nullish emas, bu foydalanuvchining tanlovi. tema (undefined) va shrift (null) standart qiymat oldi. Agar ||= ishlatganingizda, ovoz 50 ga qaytib qolardi.

3-mashq (qiyin): Yetkazib berish narxi

Onlayn do'konda yetkazib berish narxi yetkazish obyektida saqlanadi. Ba'zan yetkazish ma'lumoti umuman kelmaydi (null). Bunda odatiy narx — 15000 so'm. Narx 0 bo'lsa — yetkazish bepul, va 0 saqlanib qolishi kerak.

js
let yetkazish = { narx: 0 };
  1. ?. va ?? bilan narxni oling va chiqaring. Natija 0 bo'lishi kerak.
  2. yetkazish ni null qilib, xuddi shu ifodani yana chiqaring. Natija 15000 bo'lishi kerak.
  3. Xuddi shu ifodani ?? o'rniga || bilan yozib, birinchi holatda nima chiqishini tekshiring. Qaysi biri to'g'ri?

Ishora: xususiyat nuqta bilan olinadi (yetkazish.narx), ?. esa nuqtaning xavfsiz ko'rinishi.

Yechim
js
let yetkazish = { narx: 0 };
console.log(yetkazish?.narx ?? 15000); // 0
console.log(yetkazish?.narx || 15000); // 15000

yetkazish = null;
console.log(yetkazish?.narx ?? 15000); // 15000
  • Birinchi qator: yetkazish bor, narx 0. ?? uni saqladi — to'g'ri, yetkazish bepul.
  • Ikkinchi qator: || 0 ni falsy deb, 15000 qo'ydi — mijoz bepul yetkazish o'rniga pul to'laydi. Bu xato.
  • Uchinchi qator: yetkazish — null. ?. xato bermay undefined qaytardi, ?? esa zaxirani oldi.

Agar ?. o'rniga oddiy nuqta yozganingizda, uchinchi qator TypeError berardi.

7. Real ishda

  • Serverdan kelgan ma'lumot. Ilova serverdan foydalanuvchi ma'lumotini oladi. Ba'zi maydonlar bo'lmasligi mumkin. javob?.foydalanuvchi?.ism ?? "Noma'lum" kabi qator real loyihalarda juda ko'p. Server bilan ishlashni kursning keyingi qismlarida o'rganamiz.
  • Sozlamalar. Kutubxonalar sozlamalarni ??= bilan to'ldiradi: foydalanuvchi bergan qiymat saqlanadi, berilmagani standart qiymat oladi.
  • Brauzerlar. ?? va ?. 2020-yilda (ES2020), mantiqiy tayinlash 2021-yilda (ES2021) tilga qo'shilgan. Barcha zamonaviy brauzerlar va Node.js ularni qo'llaydi. Eski kodlarda ularning o'rniga x !== null && x !== undefined kabi uzun tekshiruvlarni ko'rishingiz mumkin.
  • Intervyu. "?? va || farqi nima?" — juda mashhur savol. Javob: "|| hamma falsy qiymatda zaxiraga o'tadi, ?? faqat null va undefined da. Shuning uchun 0 || 5 — 5, 0 ?? 5 esa — 0."

Xulosa

  • a ?? b — a faqat null yoki undefined bo'lsa b ni oladi. 0, "" va false saqlanib qoladi.
  • || — "falsymi?" deb so'raydi, ?? — "umuman bormi?" deb so'raydi. Son uchun zaxira bersangiz — ??.
  • a?.b — a nullish bo'lsa, xato o'rniga undefined qaytaradi. Shakllari: ?., ?.[ ], ?.().
  • ??=, ||=, &&= — mantiqiy tayinlash. Tayinlash faqat kerak bo'lganda bajariladi.
  • ?? ni ||/&& bilan birga yozganda qavs majburiy. ?. bilan qiymat yozib bo'lmaydi.

Keyingi dars: Ternary, vergul, void va operatorlar ustuvorligi — bitta qatorda ikki qiymatdan birini tanlash va operatorlar qaysi tartibda bajarilishini o'rganamiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript ?? va ?. operatorlari: nullish coalescing, optional chaining va mantiqiy tayinlash — IlmHamroh