Mundarija (37)
- Bu darsda
- 1. Nega bu kerak?
- 2. Xotirada nima sodir bo'ladi?
- 2.1 Primitiv: qiymatning o'zi qutida
- 2.2 Obyekt: qutida faqat manzil
- 2.3 = havolani nusxalaydi
- 2.4 Massiv ham obyekt
- 3. Qayta tayinlash va o'zgartirish: ikki xil amal
- 3.1 O'zgartirish (mutatsiya): b.x = ...
- 3.2 Qayta tayinlash: b = ...
- 3.3 const obyektni muzlatmaydi
- 4. Funksiyaga obyekt berish
- 4.1 Primitiv parametr — asliga tegmaydi
- 4.2 Obyekt parametr — asli o'zgaradi
- 4.3 Parametrni qayta tayinlash — tashqariga ta'sir qilmaydi
- 4.4 Bu — side effect
- 5. === havolani taqqoslaydi
- 5.1 Bir xil ko'rinish — boshqa obyekt
- 5.2 includes ham havolani qidiradi
- 6. Kutilmagan o'zgarishlar: uch tuzoq
- 6.1 Bitta obyektni qayta-qayta qo'shish
- 6.2 find natijasi — nusxa emas
- 6.3 Massiv nusxasi, lekin ichidagi obyektlar umumiy
- 7. Haqiqiy nusxa qanday olinadi?
- 7.1 Massiv nusxasi
- 7.2 Obyekt nusxasi
- 7.3 Ichma-ich obyekt: sayoz nusxa yetmaydi
- 8. Ko'p uchraydigan xatolar
- 8.1 = ni nusxa deb o'ylash
- 8.2 Obyektlarni === bilan solishtirish
- 8.3 Funksiya argumentini jimgina o'zgartirish
- 9. Mashqlar
- 1-mashq (oson): Natijani oldindan ayting
- 2-mashq (o'rta): Funksiyani toza qiling
- 3-mashq (qiyin): Ichidagi qiymatlar bo'yicha solishtirish
- 10. Real ishda
- Xulosa
JavaScript havola semantikasi: nega nusxa o'zgarib ketdi?
Qisqacha: JavaScript'da primitiv (son, satr, boolean) o'zgaruvchida qiymatning o'zi bo'lib saqlanadi. Obyekt va massiv esa xotiraning alohida joyida turadi, o'zgaruvchida faqat unga havola saqlanadi. Shuning uchun
const b = aobyektni nusxalamaydi: ikki o'zgaruvchi bitta obyektga qaraydi va biri o'zgartirsa, ikkinchisi ham o'zgarganini ko'radi.===ham obyekt ichini emas, havolani taqqoslaydi.
Bu darsda
- Primitiv va obyekt xotirada qanday saqlanishini jadval bilan tushuntira olasiz.
- Qayta tayinlash (
b = ...) va o'zgartirish (b.x = ...) farqini bilasiz. - Funksiyaga obyekt berilganda asl obyekt nega o'zgarishini tushunasiz va buning oldini olasiz.
- Obyektlarni
===bilan solishtirish nima uchunfalseberishini tushuntira olasiz. - Obyekt va massivning haqiqiy nusxasini ola olasiz.
Oldin bilishingiz kerak: Ma'lumot turlari xaritasi, Pure funksiya va side effect, Element qo'shish va olib tashlash, Obyekt bo'ylab yurish.
1. Nega bu kerak?
Oldingi darsda Object.entries va Object.fromEntries bilan obyektning o'zgartirilgan nusxasini yasadik. O'shanda "asl obyekt o'zgarmadi — nega bu muhimligini keyingi darsda ko'ramiz" degan edik. Mana o'sha dars.
Tasavvur qiling: siz onlayn do'kon uchun admin panel yozyapsiz. Admin mahsulotni tahrirlash oynasini ochadi. Siz "asl nusxaga tegmasin, admin nusxada ishlasin" deb shunday yozasiz:
const mahsulot = { nom: "Choynak", narx: 120000 };
const tahrir = mahsulot; // "nusxa" oldik
tahrir.narx = 99000; // admin narxni o'zgartirdi
// Admin "Bekor qilish" tugmasini bosdi...
console.log(mahsulot.narx); // 99000Admin bekor qildi, lekin do'kondagi narx baribir 99 000 bo'lib qoldi! Xato xabari yo'q, qizil yozuv yo'q. Ertaga mijozlar choynakni arzon narxda sotib olishadi.
Ma'lumot turlari darsida bu hodisa bilan qisqacha tanishgan edik. Endi uni tubigacha tushunamiz: xotirada aslida nima bo'ladi, qayerda xavf bor va haqiqiy nusxa qanday olinadi.
2. Xotirada nima sodir bo'ladi?
2.1 Primitiv: qiymatning o'zi qutida
let va const darsida o'zgaruvchini yorliqli quti deb tasavvur qilgan edik. Primitiv qiymatlar uchun bu rasm aynan to'g'ri: qutida qiymatning o'zi yotadi.
let narx = 5000;
let yangiNarx = narx;
yangiNarx = 7000;
console.log(narx); // 5000
console.log(yangiNarx); // 7000let yangiNarx = narx qatori 5000 sonining nusxasini yangi qutiga soldi. Xotirada shunday ko'rinadi:
| O'zgaruvchi | Qutida nima bor |
|---|---|
narx |
5000 |
yangiNarx |
5000 → keyin 7000 |
Ikki quti — ikki alohida son. Birini o'zgartirish ikkinchisiga ta'sir qilmaydi. Buni qiymat bo'yicha nusxalash (copy by value) deb ataganmiz. Satr, boolean, null, undefined — barcha primitivlar shunday ishlaydi.
2.2 Obyekt: qutida faqat manzil
Obyekt boshqacha saqlanadi. U katta bo'lishi mumkin, o'sib-kichrayishi mumkin. Shuning uchun JavaScript obyektni xotiraning alohida joyiga qo'yadi. O'zgaruvchi qutisiga esa faqat o'sha joyning manzili yoziladi.
Bu manzil havola (reference) deb ataladi. Havola — "obyekt qayerda turibdi" degan ko'rsatkich.
const mahsulot = { nom: "Choynak", narx: 120000 };Xotirada (manzilni #1 deb belgilaymiz — haqiqiy manzilni JavaScript o'zi tanlaydi va sizga ko'rsatmaydi):
| O'zgaruvchi | Qutida nima bor |
|---|---|
mahsulot |
havola → #1 |
| Manzil | Obyekt |
|---|---|
#1 |
{ nom: "Choynak", narx: 120000 } |
2.3 = havolani nusxalaydi
Endi 1-bo'limdagi xatoga qaytamiz. const tahrir = mahsulot qatori nima qiladi? U mahsulot qutisidagi narsani nusxalaydi. Qutida esa obyekt emas, havola bor edi. Demak havola nusxalandi:
| O'zgaruvchi | Qutida nima bor |
|---|---|
mahsulot |
havola → #1 |
tahrir |
havola → #1 |
Ikki quti, lekin ikkalasida bitta manzil. Obyekt esa xotirada hamon bitta. Sxemada:
mahsulot ──┐
├──► #1: { nom: "Choynak", narx: 120000 }
tahrir ────┘tahrir.narx = 99000 qatori "#1 manzilidagi obyektning narxini o'zgartir" degani. mahsulot.narx ni o'qiganda ham JavaScript #1 ga boradi — va o'zgargan narxni topadi.
Ma'lumot turlari darsidagi o'xshatishni eslang: Telegram guruhiga havola. Siz do'stingizga guruh havolasini yubordingiz. Endi ikkalangiz bitta guruhga kirasiz. Do'stingiz guruhga xabar yozsa, siz ham ko'rasiz — chunki guruh bitta, havola ikkita.
Buni havola bo'yicha nusxalash (copy by reference) deyiladi.
2.4 Massiv ham obyekt
Massiv obyektning bir turi, shuning uchun u ham havola bilan saqlanadi:
const xaridlar = ["non", "sut"];
const royxat = xaridlar;
royxat.push("tuxum");
console.log(xaridlar); // [ 'non', 'sut', 'tuxum' ]Biz faqat royxat ga qo'shdik, lekin xaridlar ham o'zgardi. Element qo'shish darsida ko'rgan push massivni joyida o'zgartiradi — va bu joy ikki o'zgaruvchi uchun ham bitta.
| Tur | Nima saqlanadi | b = a dan keyin |
|---|---|---|
| Primitiv | Qiymatning o'zi | Ikki mustaqil qiymat |
| Obyekt, massiv | Havola (manzil) | Bitta obyektga ikki havola |
Tekshirib ko'ring: Konsolda nima chiqadi?
jsconst a = { ball: 50 }; const b = a; b.ball = b.ball + 10; console.log(a.ball);
Javob
60. b = a obyektni emas, havolani nusxaladi. a ham, b ham bitta obyektga qaraydi. b.ball ni o'zgartirish — o'sha yagona obyektni o'zgartirish.
3. Qayta tayinlash va o'zgartirish: ikki xil amal
Bu darsning eng muhim bo'limi. Havola bilan ishlaganda ikki xil amal bor va ular butunlay boshqa natija beradi.
3.1 O'zgartirish (mutatsiya): b.x = ...
Nuqta yoki kvadrat qavs orqali ichini o'zgartirsangiz, siz havola ko'rsatgan obyektni o'zgartirasiz. Bu mutatsiya — massiv darsidan tanish so'z. Obyekt bitta bo'lgani uchun, unga qaragan hamma o'zgaruvchi o'zgarishni ko'radi. push, pop, delete ham mutatsiya.
3.2 Qayta tayinlash: b = ...
O'zgaruvchiga butunlay yangi qiymat bersangiz, siz faqat shu qutidagi havolani almashtirasiz. Obyektga tegmaysiz:
const asl = { shahar: "Toshkent" };
let nusxa = asl;
nusxa = { shahar: "Buxoro" }; // yangi obyekt, yangi havola
console.log(asl.shahar); // Toshkent
console.log(nusxa.shahar); // BuxoroQayta tayinlashdan keyin xotirada endi ikki alohida obyekt bor, har biriga bittadan havola:
asl ─────► #1: { shahar: "Toshkent" }
nusxa ───► #2: { shahar: "Buxoro" }nusxa endi boshqa obyektga qaraydi. asl esa eski joyida — unga hech narsa bo'lmadi.
Telegram o'xshatishida: do'stingiz eski guruhdan chiqib, boshqa guruh havolasini ochdi. Endi u yozgan xabarlar siz turgan guruhga tushmaydi.
| Amal | Misol | Nimani o'zgartiradi | Boshqa havolalarga ta'siri |
|---|---|---|---|
| O'zgartirish | b.narx = 5 |
Obyektning ichini | Bor |
| Qayta tayinlash | b = { narx: 5 } |
Faqat b qutisini |
Yo'q |
O'zingiz to'ldiring: let x = { son: 1 }; let y = x; y.son = 2; dan keyin x.son — [:2]. let x = { son: 1 }; let y = x; y = { son: 2 }; dan keyin esa x.son — [:1].
3.3 const obyektni muzlatmaydi
Endi const ning nega obyekt ichini o'zgartirishga yo'l qo'yishi tushunarli bo'ladi. const qutini qotiradi: undagi havolani boshqasiga almashtirib bo'lmaydi. Havola ko'rsatgan obyektni esa qotirmaydi:
const mijoz = { ism: "Ali" };
mijoz.ism = "Vali"; // ✅ obyekt ichi — mumkin
console.log(mijoz.ism); // ValiQayta tayinlashga urinsangiz esa:
const mijoz = { ism: "Ali" };
mijoz = { ism: "Vali" };TypeError: Assignment to constant variable.Tarjimasi: "o'zgarmas (const) o'zgaruvchiga qiymat berish". const quti ichidagi havolani almashtirishni taqiqladi. Lekin 3.1 dagi mutatsiyani taqiqlamaydi.
Maslahat: Obyekt ichini ham haqiqatan "muzlatish" kerak bo'lsa,
Object.freezebor. Uni Obyektni himoyalash darsida o'rganamiz.
Tekshirib ko'ring:
const ballar = [80, 90];dan keyinballar.push(100)ishlaydimi?ballar = [100]chi?
Javob
ballar.push(100) ishlaydi — bu mutatsiya, massiv ichini o'zgartiradi, const bunga qarshi emas. ballar = [100] esa TypeError: Assignment to constant variable. beradi — bu qayta tayinlash, const aynan shuni taqiqlaydi.
4. Funksiyaga obyekt berish
4.1 Primitiv parametr — asliga tegmaydi
Parametrlar darsida ko'rganingizdek, funksiya chaqirilganda argument parametrga yoziladi. Aslida bu ham = bilan nusxalashning o'zi:
function oshir(son) {
son = son + 1;
return son;
}
let hisob = 10;
oshir(hisob);
console.log(hisob); // 10son ga 10 ning nusxasi yozildi. Funksiya o'z nusxasini o'zgartirdi, hisob esa 10 ligicha qoldi.
4.2 Obyekt parametr — asli o'zgaradi
Endi obyekt beramiz:
function chegirmaQil(buyurtma) {
buyurtma.narx = buyurtma.narx * 0.9;
}
const meningBuyurtmam = { taom: "osh", narx: 40000 };
chegirmaQil(meningBuyurtmam);
console.log(meningBuyurtmam.narx); // 36000buyurtma parametriga obyektning havolasi yozildi. Funksiya ichidagi buyurtma va tashqaridagi meningBuyurtmam — bitta obyektga qaraydi:
meningBuyurtmam ──┐
├──► #1: { taom: "osh", narx: 40000 }
buyurtma ─────────┘ (funksiya ichida)Funksiya #1 ning narxini o'zgartirdi — tashqarida ham narx o'zgardi. Massiv bersangiz ham shunday: funksiya ichidagi push tashqaridagi massivga element qo'shadi.
4.3 Parametrni qayta tayinlash — tashqariga ta'sir qilmaydi
3-bo'limdagi qoida funksiyada ham ishlaydi:
function almashtir(buyurtma) {
buyurtma = { taom: "lag'mon", narx: 30000 };
}
const meningBuyurtmam = { taom: "osh", narx: 40000 };
almashtir(meningBuyurtmam);
console.log(meningBuyurtmam.taom); // oshbuyurtma = {...} faqat funksiya ichidagi qutini boshqa obyektga yo'naltirdi. Tashqaridagi meningBuyurtmam eski obyektga qarab turibdi.
Maslahat: Intervyuda ko'p so'raladi: "JavaScript'da obyekt funksiyaga qiymat bo'yicha beriladimi yoki havola bo'yicha?" Aniq javob: JavaScript har doim qiymatni nusxalaydi. Faqat obyekt uchun bu qiymat — havolaning o'zi. Shuning uchun ichini o'zgartirsangiz — tashqarida ko'rinadi 4.2-bob, parametrni qayta tayinlasangiz — ko'rinmaydi 4.3-bob. Inglizcha bu "call by sharing" deb ham ataladi.
4.4 Bu — side effect
Pure funksiya darsida side effect turlari orasida "massiv yoki obyektni o'zgartirish" ham bor edi. Endi nega xavfli ekanini ko'rdingiz: chegirmaQil hech narsa qaytarmaydi. Lekin u chaqiruvchining obyektini jimgina o'zgartirdi. Kodni o'qigan odam chegirmaQil(meningBuyurtmam) qatoridan buni sezmasligi mumkin.
Toza yo'l — asliga tegmasdan, yangi obyekt qaytarish:
function chegirmaQil(buyurtma) {
return {
taom: buyurtma.taom,
narx: buyurtma.narx * 0.9,
};
}
const meningBuyurtmam = { taom: "osh", narx: 40000 };
const chegirmali = chegirmaQil(meningBuyurtmam);
console.log(meningBuyurtmam.narx); // 40000
console.log(chegirmali.narx); // 36000Endi funksiya toza: kirgan obyektni faqat o'qiydi, natijani yangi obyektda qaytaradi. Asl buyurtma ham, yangisi ham qo'lingizda.
Tekshirib ko'ring:
function tozala(r) { r.push("tayyor"); }vaconst vazifalar = [];bo'lsa,tozala(vazifalar)dan keyinvazifalar.lengthnechchi?
Javob
1. Funksiyaga massivning havolasi berildi. r.push — mutatsiya, u o'sha yagona massivga element qo'shdi. Shuning uchun tashqaridagi vazifalar da ham bitta element bor.
5. === havolani taqqoslaydi
5.1 Bir xil ko'rinish — boshqa obyekt
const a = { ism: "Ali" };
const b = { ism: "Ali" };
const c = a;
console.log(a === b); // false
console.log(a === c); // truea va b ichi bir xil, lekin === false berdi. Sababi: har bir { ... } yozuvi xotirada yangi obyekt yaratadi. a — #1 ga, b — #2 ga qaraydi. === esa obyekt ichini emas, havolalarni taqqoslaydi: "ikkalasi bitta obyektmi?"
a va c esa bitta obyektga qaraydi — shuning uchun true.
Hayotdan o'xshatish: egizaklar. Ular bir xil kiyinishi, bir xil ko'rinishi mumkin. Lekin baribir ikki xil odam. === "bir xil ko'rinadimi?" deb emas, "bu o'sha odammi?" deb so'raydi.
Tenglik darsidagi Object.is ham obyektlar uchun xuddi shunday ishlaydi. Massivlar ham: [] === [] — false.
5.2 includes ham havolani qidiradi
Massivda obyekt qidirishda bu ayniqsa chalg'itadi:
const savat = [{ nom: "olma" }, { nom: "nok" }];
console.log(savat.includes({ nom: "olma" })); // falseSavatda olma bor, lekin includes topmadi. U === bilan solishtiradi, biz esa unga yangi obyekt berdik. Bunday yangi obyekt massivda yo'q.
To'g'ri yo'l — xususiyat bo'yicha qidirish. Buni massivda qidirish darsidagi some yoki find qiladi:
const savat = [{ nom: "olma" }, { nom: "nok" }];
const olmaBor = savat.some((m) => m.nom === "olma");
console.log(olmaBor); // trueBu yerda m.nom === "olma" — ikki satr solishtiriladi. Satr primitiv, shuning uchun qiymat bo'yicha taqqoslanadi.
Tekshirib ko'ring:
const x = [1, 2];bo'lsa,x === xvax === [1, 2]nima beradi?
Javob
true va false. x === x — bitta havola o'zi bilan solishtirildi. [1, 2] esa yangi massiv yaratadi, u boshqa manzilda turadi.
6. Kutilmagan o'zgarishlar: uch tuzoq
6.1 Bitta obyektni qayta-qayta qo'shish
Jadval uchun uch qator yasamoqchimiz:
const qator = {};
const jadval = [];
for (let i = 1; i <= 3; i++) {
qator.raqam = i;
jadval.push(qator);
}
console.log(jadval); // [ { raqam: 3 }, { raqam: 3 }, { raqam: 3 } ]1, 2, 3 kutgandik — hammasi 3! Sikl ichida biz yangi obyekt yaratmadik. Har safar o'sha bitta qator obyektining havolasini qo'shdik. Massivda uchta havola, obyekt esa bitta — oxirgi qiymati 3.
Tuzatish: obyektni sikl ichida yarating. Har aylanishda { ... } yangi obyekt beradi:
const jadval = [];
for (let i = 1; i <= 3; i++) {
jadval.push({ raqam: i });
}
console.log(jadval); // [ { raqam: 1 }, { raqam: 2 }, { raqam: 3 } ]6.2 find natijasi — nusxa emas
const talabalar = [
{ ism: "Ali", ball: 70 },
{ ism: "Malika", ball: 90 },
];
const topilgan = talabalar.find((t) => t.ism === "Ali");
topilgan.ball = 100;
console.log(talabalar[0].ball); // 100find topgan obyektning havolasini qaytaradi. topilgan va talabalar[0] — bitta obyekt. Ba'zan aynan shu kerak (ro'yxatdagi talabaning balini yangilash). Lekin "topib olib, alohida ishlayman" deb o'ylasangiz — asl ro'yxat buziladi.
6.3 Massiv nusxasi, lekin ichidagi obyektlar umumiy
Kesish darsida massiv nusxasini slice() bilan olishni ko'rgansiz. Nusxa haqiqatan yangi massiv:
const talabalar = [
{ ism: "Ali", ball: 70 },
{ ism: "Malika", ball: 90 },
];
const nusxa = talabalar.slice();
nusxa.push({ ism: "Jasur", ball: 60 });
nusxa[0].ball = 100;
console.log(talabalar.length); // 2
console.log(talabalar[0].ball); // 100push faqat nusxaga ta'sir qildi — uzunlik 2 ligicha qoldi. Lekin nusxa[0].ball = 100 asl massivdagi Alini ham o'zgartirdi! Sababi: slice() massivni nusxaladi, lekin ichidagi obyektlarni emas. Yangi massiv ichida — eski obyektlarning havolalari.
| O'zgaruvchi | Massiv ichida nima bor |
|---|---|
talabalar |
havola #1 (Ali), havola #2 (Malika) |
nusxa |
havola #1 (Ali), havola #2 (Malika), havola #3 (Jasur) |
Faqat birinchi qavat nusxalandi. Buni sayoz nusxa (shallow copy) deyiladi. Bu mavzuni Sayoz va chuqur nusxalash darsida to'liq o'rganamiz.
7. Haqiqiy nusxa qanday olinadi?
7.1 Massiv nusxasi
Massivning o'zini nusxalash uchun ikki tanish yo'l bor (kesish darsidan):
const xaridlar = ["non", "sut"];
const n1 = xaridlar.slice();
const n2 = [...xaridlar];
n1.push("tuxum");
console.log(xaridlar); // [ 'non', 'sut' ]
console.log(n1 === xaridlar); // false[...xaridlar] — spread yozuvi: "massiv elementlarini yangi massivga yoy". Uni Spread va rest darsida batafsil o'rganamiz.
7.2 Obyekt nusxasi
Oldingi darsdagi entries → fromEntries naqshi aynan yangi obyekt yasaydi:
const asl = { nom: "Choynak", narx: 120000 };
const nusxa = Object.fromEntries(Object.entries(asl));
nusxa.narx = 99000;
console.log(asl.narx); // 120000
console.log(nusxa === asl); // falseIshlaydi, lekin uzun. Real kodda buning uchun spread yozuvi ishlatiladi — { ...asl }. U obyektning barcha xususiyatlarini yangi obyektga "yoyadi". Yoniga o'zgargan xususiyatni ham qo'shish mumkin:
const asl = { nom: "Choynak", narx: 120000 };
const yangi = { ...asl, narx: 99000 };
console.log(asl); // { nom: 'Choynak', narx: 120000 }
console.log(yangi); // { nom: 'Choynak', narx: 99000 }Hozircha bu yozuvni tanib qoling. U qanday ishlashini va qoidalarini Spread va rest darsida o'rganamiz. 1-bo'limdagi admin panel muammosi aynan shu bilan hal qilinadi: const tahrir = { ...mahsulot }.
7.3 Ichma-ich obyekt: sayoz nusxa yetmaydi
Spread ham, fromEntries ham, slice ham — sayoz nusxa. Ichma-ich obyekt bo'lsa, ichkisi umumiy qoladi:
const asl = { nom: "Choynak", tafsilot: { rang: "oq" } };
const nusxa = { ...asl };
nusxa.tafsilot.rang = "qora";
console.log(asl.tafsilot.rang); // qoraBarcha qavatlarni nusxalaydigan tayyor funksiya bor — structuredClone:
const asl = { nom: "Choynak", tafsilot: { rang: "oq" } };
const nusxa = structuredClone(asl);
nusxa.tafsilot.rang = "qora";
console.log(asl.tafsilot.rang); // oqBu chuqur nusxa (deep copy). Uning chegaralari va qachon ishlatish kerakligi — Sayoz va chuqur nusxalash darsida.
| Nima kerak | Usul | Qaysi darsda |
|---|---|---|
| Massiv nusxasi | arr.slice(), [...arr] |
Kesish va birlashtirish, Spread va rest |
| Obyekt nusxasi | { ...obj } |
Spread va rest |
| Ichma-ich hammasi | structuredClone(obj) |
Sayoz va chuqur nusxalash |
8. Ko'p uchraydigan xatolar
8.1 = ni nusxa deb o'ylash
1-bo'limdagi const tahrir = mahsulot — eng ko'p uchraydigan xato. Obyekt yoki massivda = — bu ikkinchi nom, nusxa emas.
8.2 Obyektlarni === bilan solishtirish
const eski = { ism: "Ali", yosh: 20 };
const yangi = { ism: "Ali", yosh: 20 };
if (eski === yangi) {
console.log("O'zgarish yo'q");
} else {
console.log("Ma'lumot o'zgardi!");
}Konsolda:
Ma'lumot o'zgardi!Ichi bir xil, lekin kod "o'zgardi" dedi. Ikki xil obyektni ichidagi qiymatlar bo'yicha solishtirish uchun xususiyatlarni birma-bir tekshirish kerak (3-mashqda o'zingiz yozasiz).
8.3 Funksiya argumentini jimgina o'zgartirish
function teskariNavbat(nomlar) {
nomlar.reverse();
return nomlar;
}
const navbat = ["Ali", "Malika", "Jasur"];
const teskari = teskariNavbat(navbat);
console.log(navbat); // [ 'Jasur', 'Malika', 'Ali' ]Funksiya faqat natija qaytaradi deb o'ylagandik. Lekin reverse mutatsiya qiladi — asl navbat ham teskari bo'lib qoldi. Tuzatish: avval nusxa oling — nomlar.slice().reverse().
9. Mashqlar
1-mashq (oson): Natijani oldindan ayting
Kodni ishga tushirmasdan, har bir console.log nima chiqarishini yozing. Keyin tekshiring.
let a = "choy";
let b = a;
b = "qahva";
const x = { ichimlik: "choy" };
const y = x;
y.ichimlik = "qahva";
console.log(a);
console.log(b);
console.log(x.ichimlik);
console.log(x === y);Yechim
Konsolda:
choy
qahva
qahva
truea — satr, primitiv: b = a qiymat nusxasini oldi, keyin b qayta tayinlandi. a o'zgarmadi. x esa obyekt: y = x havolani nusxaladi, y.ichimlik = ... — mutatsiya, shuning uchun x.ichimlik ham "qahva". x === y — true, chunki ikkalasi bitta obyektga qaraydi.
2-mashq (o'rta): Funksiyani toza qiling
Bu funksiya xodimga bonus qo'shadi, lekin asl obyektni o'zgartirib yuboradi:
function bonusQosh(xodim, summa) {
xodim.oylik = xodim.oylik + summa;
return xodim;
}Uni shunday qayta yozingki, u asl obyektga tegmasin va yangi obyekt qaytarsin. So'ng const nodira = { ism: "Nodira", oylik: 5000000 }; bilan sinab ko'ring: nodira.oylik 5 000 000 ligicha qolsin, yangi obyektda esa 5 500 000 bo'lsin.
Ishora: 4.4-bo'limdagi chegirmaQil kabi — return { ism: ..., oylik: ... }. Xohlasangiz, 7.2 dagi { ...xodim, oylik: ... } yozuvini ham sinab ko'ring.
Yechim
function bonusQosh(xodim, summa) {
return {
ism: xodim.ism,
oylik: xodim.oylik + summa,
};
}
const nodira = { ism: "Nodira", oylik: 5000000 };
const yangi = bonusQosh(nodira, 500000);
console.log(nodira.oylik); // 5000000
console.log(yangi.oylik); // 5500000
console.log(nodira === yangi); // falseFunksiya xodim ni faqat o'qidi va natijani yangi obyektda qaytardi. Spread bilan: return { ...xodim, oylik: xodim.oylik + summa }; — bu variant boshqa xususiyatlarni (masalan, lavozim) ham ko'chiradi.
3-mashq (qiyin): Ichidagi qiymatlar bo'yicha solishtirish
tengmi(a, b) funksiyasini yozing. U ikki tekis obyektni (ichida boshqa obyekt yo'q) ichidagi qiymatlar bo'yicha solishtirsin:
- kalitlar soni har xil bo'lsa —
false; aning biror kaliti uchuna[kalit] !== b[kalit]bo'lsa —false;- aks holda —
true.
Sinab ko'ring: { ism: "Ali", yosh: 20 } va { yosh: 20, ism: "Ali" } → true; { ism: "Ali" } va { ism: "Vali" } → false.
Ishora: kalitlar soni — oldingi darsdagi Object.keys(...).length. Kalitlar bo'ylab for...of bilan yuring va farq topilishi bilan erta qaytish bilan false qaytaring.
Yechim
function tengmi(a, b) {
const aKalitlar = Object.keys(a);
if (aKalitlar.length !== Object.keys(b).length) {
return false;
}
for (const kalit of aKalitlar) {
if (a[kalit] !== b[kalit]) {
return false;
}
}
return true;
}
const t1 = { ism: "Ali", yosh: 20 };
const t2 = { yosh: 20, ism: "Ali" };
console.log(t1 === t2); // false
console.log(tengmi(t1, t2)); // true
console.log(tengmi({ ism: "Ali" }, { ism: "Vali" })); // false
console.log(tengmi({ ism: "Ali" }, { ism: "Ali", yosh: 1 })); // false=== havolalarni solishtirib false berdi, tengmi esa ichini solishtirib true berdi. Kalitlar tartibi muhim emas: biz a ning har kaliti bo'yicha b dan qiymat so'radik.
Kalitlar sonini tekshirmasak, oxirgi misol true berib qo'yardi. Bu funksiya sayoz: ichma-ich obyektlarni baribir havola bo'yicha solishtiradi.
10. Real ishda
- React. React ekranni qachon yangilashni havolaga qarab hal qiladi. Obyektni joyida o'zgartirsangiz (
user.ism = "Vali"), havola o'sha-o'sha qoladi va React o'zgarishni ko'rmaydi — ekran yangilanmaydi. Shuning uchun React'da har doim yangi obyekt yasaladi:{ ...user, ism: "Vali" }. Bu boshlovchilarning React'dagi eng ko'p uchraydigan xatolaridan biri. - Server. Node.js serverida umumiy sozlama obyektini bitta so'rov ichida o'zgartirib qo'yish boshqa foydalanuvchilarning so'rovlariga ham ta'sir qiladi. Bunday xatoni topish soatlab vaqt oladi.
Intervyuda deyarli har doim so'raladi: "{} === {} nima beradi va nega?", "Obyekt funksiyaga qanday uzatiladi?", "Obyektni qanday nusxalaysiz?" Endi uchalasiga ham javob bera olasiz.
Maslahat: Havolasi qolmagan obyekt nima bo'ladi? JavaScript uni avtomatik ravishda xotiradan o'chiradi — bu ishni garbage collector ("axlat yig'uvchi") bajaradi. Bu qanday ishlashini Xotira boshqaruvi darsida o'rganamiz.
Xulosa
- Primitiv o'zgaruvchida qiymatning o'zi saqlanadi; obyekt va massiv o'zgaruvchisida esa havola (manzil).
b = aobyektni emas, havolani nusxalaydi — ikki o'zgaruvchi bitta obyektga qaraydi.b.x = ...(mutatsiya) umumiy obyektni o'zgartiradi;b = ...(qayta tayinlash) faqatbni boshqa joyga yo'naltiradi.- Funksiyaga berilgan obyektni o'zgartirish — side effect; toza yo'l — yangi obyekt qaytarish.
===obyekt ichini emas, havolani taqqoslaydi:{} === {}—false.consthavolani qotiradi, obyekt ichini emas. Nusxa:slice(),[...arr],{ ...obj }; ichma-ich uchunstructuredClone.
Keyingi dars: Obyekt destructuring — obyektdan kerakli xususiyatlarni bitta qatorda alohida o'zgaruvchilarga ajratib olishni o'rganamiz.
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!