IlmHamroh
JavaScript Full-stack/8-qism. JavaScript asoslari61/61-dars17 daqiqa
Mundarija (37)

JavaScript'da obyektni nusxalash: sayoz va chuqur nusxa, structuredClone

Qisqacha: Spread ({ ...obj }), Object.assign va slice — sayoz nusxa: ular faqat birinchi qavatni nusxalaydi, ichma-ich obyektlar esa asl nusxa bilan umumiy bo'lib qoladi. To'liq mustaqil, chuqur nusxa uchun structuredClone(obj) ishlatiladi. U funksiyalarni nusxalay olmaydi, eski JSON.parse(JSON.stringify(obj)) usuli esa sana, undefined va NaN ni buzadi.

Bu darsda

  • Sayoz nusxa nima ekanini va uning ichma-ich obyektdagi tuzog'ini tushuntira olasiz.
  • Obyekt va massivni to'rt xil usulda sayoz nusxalay olasiz.
  • structuredClone bilan chuqur nusxa olasiz va u nimani nusxalay olmasligini bilasiz.
  • Eski JSON usuli nimalarni yo'qotishini tushunasiz.
  • Ichma-ich ma'lumotni asl nusxaga tegmasdan yangilay olasiz.

Oldin bilishingiz kerak: Havola semantikasi, Spread va rest operatori, Parametrda destructuring va options obyekti.

1. Nega bu kerak?

Siz o'quv markazi saytida profil tahrirlash oynasini yasayapsiz. Foydalanuvchi "Tahrirlash" tugmasini bosadi. Siz profilning nusxasini olasiz — foydalanuvchi o'sha nusxani o'zgartiradi. "Bekor qilish" bosilsa, nusxa tashlab yuboriladi, asl profil esa joyida qoladi.

Siz spread bilan nusxa oldingiz:

js
const profil = { ism: "Malika", manzil: { shahar: "Toshkent" } };

const qoralama = { ...profil };
qoralama.manzil.shahar = "Samarqand";

console.log(profil.manzil.shahar); // Samarqand

Foydalanuvchi hali hech narsani saqlamadi. Lekin asl profildagi shahar allaqachon o'zgarib ketdi! "Bekor qilish" endi hech narsani qaytarmaydi.

Bu — JavaScript'dagi eng ko'p uchraydigan yashirin xatolardan biri. Kod xato bermaydi, faqat ma'lumot "o'z-o'zidan" o'zgarib qoladi. Bu darsda buning sababini va to'g'ri yechimini ko'ramiz.

2. Eslatma: havola va nusxa

Havola semantikasi darsidan asosiy qoidani eslang. Obyekt o'zgaruvchining ichida emas, xotirada alohida turadi. O'zgaruvchida faqat unga havola — "manzil" saqlanadi.

js
const a = { ism: "Ali" };
const b = a;

b.ism = "Vali";
console.log(a.ism); // Vali
console.log(a === b); // true

const b = a — bu umuman nusxa emas. Ikki o'zgaruvchi bitta obyektga qarab turibdi. === obyektlarda qiymatni emas, havolani solishtiradi: true — "bu bitta obyekt" degani.

Nusxa olish — xotirada yangi obyekt yaratish demak. Savol esa shunda: yangi obyekt ichiga nima tushadi?

3. Sayoz nusxa (shallow copy)

3.1 Spread birinchi qavatni nusxalaydi

js
const asl = { ism: "Malika", yosh: 20 };
const nusxa = { ...asl };

nusxa.ism = "Dilnoza";

console.log(asl.ism); // Malika
console.log(nusxa.ism); // Dilnoza
console.log(asl === nusxa); // false

Bu yerda hammasi to'g'ri ishladi. { ...asl } yangi obyekt yaratdi (asl === nusxa — false). Nusxadagi ism ni o'zgartirish aslga ta'sir qilmadi.

Sayoz nusxa (shallow copy) — obyektning faqat birinchi qavatini nusxalash. Yangi obyekt yaratiladi va asl obyektdagi har bir xususiyat unga ko'chiriladi. Lekin xususiyatning qiymati obyekt bo'lsa, o'sha ichki obyekt nusxalanmaydi — faqat unga havola ko'chadi.

Hayotdan o'xshatish: omborxona ro'yxatini kseroksda ko'chirish. Varaqda "Stol — 3 ta" deb yozilgan qatorlar ham bor, "Asboblar — 7-shkafda" degan qator ham bor. Ksero nusxada ham xuddi shu yoziladi: "7-shkafda". Lekin shkafning o'zi ikkita bo'lib qolmaydi! Bitta varaq egasi shkafdan bolg'ani olsa, ikkinchi varaq egasi ham shkafni bo'sh ko'radi.

3.2 Tuzoq: ichma-ich obyekt

Endi birinchi bo'limdagi misolga qaytamiz va nima bo'lganini tekshiramiz:

js
const profil = { ism: "Malika", manzil: { shahar: "Toshkent" } };
const qoralama = { ...profil };

console.log(profil === qoralama); // false
console.log(profil.manzil === qoralama.manzil); // true

Tashqi obyektlar har xil (false). Lekin manzil ikkalasida ham bitta obyekt (true)! Spread manzil xususiyatini ko'chirdi — ya'ni ichki obyektga havolani ko'chirdi. Ichki obyektning o'zi esa nusxalanmadi.

3.3 Xotira sxemasi

Xotirani raqamlangan qutilar deb tasavvur qilaylik. { ...profil } dan keyin xotira shunday ko'rinadi:

Quti Ichida Kim qaraydi
#1 ism: "Malika", manzil: → #3 profil
#2 ism: "Malika", manzil: → #3 qoralama
#3 shahar: "Toshkent" #1 va #2 ikkalasi

Jadvalni o'qing: #1 va #2 — ikki alohida obyekt. Lekin ikkalasining manzil xususiyati bitta qutiga — #3 ga ishora qiladi.

Shuning uchun:

  • qoralama.ism = "Dilnoza" — faqat #2 qutini o'zgartiradi. Asl profil xavfsiz.
  • qoralama.manzil.shahar = "Samarqand" — avval #3 qutiga boradi, keyin uni o'zgartiradi. #3 esa profil niki ham. Shuning uchun asl profil ham o'zgaradi.

Maslahat: Qoida: son, satr, boolean kabi primitiv qiymatlar nusxada har doim mustaqil. Obyekt va massiv qiymatlar esa sayoz nusxada umumiy bo'lib qoladi.

3.4 Massivda ham xuddi shunday

Massiv ichida obyektlar bo'lsa, xuddi shu tuzoq takrorlanadi:

js
const savat = [
  { nomi: "Non", soni: 2 },
  { nomi: "Sut", soni: 1 },
];

const nusxa = [...savat];
nusxa[0].soni = 10;

console.log(savat[0].soni); // 10
console.log(savat === nusxa); // false
console.log(savat[0] === nusxa[0]); // true

Massivning o'zi yangi. Lekin uning ichidagi obyektlar — o'sha eskilari. Nusxa massivga yangi element qo'shsangiz (push), asl massiv o'zgarmaydi. Mavjud elementning ichini o'zgartirsangiz — ikkalasida ham o'zgaradi.

Tekshirib ko'ring: Konsolda nima chiqadi?

js
const kurs = { nomi: "JS", teglar: ["web", "frontend"] };
const nusxa = { ...kurs };

nusxa.nomi = "Python";
nusxa.teglar.push("backend");

console.log(kurs.nomi);
console.log(kurs.teglar.length);
Javob

JS va 3. nomi — satr, birinchi qavatda turadi, shuning uchun nusxada mustaqil. teglar esa massiv: sayoz nusxada ikkala obyekt bitta massivga qaraydi. Nusxa orqali push qilingan "backend" asl kursda ham paydo bo'ldi.

4. Sayoz nusxaning to'rt usuli

Spread yagona usul emas. Real kodda to'rttasini ham uchratasiz. Hammasi bir xil darajada — sayoz nusxa oladi.

4.1 Obyekt uchun: spread va Object.assign

Object.assign(nishon, manba) — manba obyektdagi hamma xususiyatni nishon obyektga ko'chiradi va nishonni qaytaradi. Nishon sifatida bo'sh {} bersangiz — natija yangi nusxa bo'ladi:

js
const narxlar = { choy: 5000, non: 4000 };

const nusxa1 = { ...narxlar };
const nusxa2 = Object.assign({}, narxlar);

console.log(nusxa2); // { choy: 5000, non: 4000 }
console.log(nusxa2 === narxlar); // false

Object.assign spread paydo bo'lishidan (2018) oldingi usul. Eski kodda va ba'zi kutubxonalarda ko'p uchraydi. Yangi kodda spread qisqaroq va o'qilishi osonroq.

4.2 Massiv uchun: spread, slice va Array.from

js
const mevalar = ["olma", "anor", "uzum"];

const n1 = [...mevalar];
const n2 = mevalar.slice();
const n3 = Array.from(mevalar);

console.log(n3); // [ 'olma', 'anor', 'uzum' ]
console.log(n1 === mevalar, n2 === mevalar); // false false
  • slice() argumentsiz chaqirilsa, massivni boshidan oxirigacha kesadi — ya'ni to'liq nusxa beradi.
  • Array.from(x) — x dan yangi massiv yasaydi. U massivga o'xshagan boshqa narsalardan ham massiv yasay oladi (masalan, satrdan: Array.from("salom")). Bu imkoniyat keyingi qismlarda kerak bo'ladi.
Usul Nima uchun Nusxa turi
{ ...obj } Obyekt Sayoz
Object.assign({}, obj) Obyekt Sayoz
[...arr], arr.slice() Massiv Sayoz
Array.from(arr) Massiv Sayoz

Jadvaldagi oxirgi ustunga e'tibor bering: to'rttasi ham sayoz. Ichma-ich obyekt bo'lsa, ularning birortasi ham sizni tuzoqdan qutqarmaydi.

Diqqat: Object.assign birinchi argumentni o'zgartiradi. Object.assign(profil, { yosh: 21 }) deb yozsangiz, nusxa olinmaydi — asl profil ning o'zi o'zgaradi. Nusxa kerak bo'lsa, birinchi argument har doim bo'sh {} bo'lsin.

5. Chuqur nusxa: structuredClone

5.1 Hamma qavatni nusxalash

Chuqur nusxa (deep copy) — obyektni ichidagi barcha ichma-ich obyektlari bilan birga, har qavatda yangidan nusxalash. Natija asl nusxa bilan hech qanday umumiy qismga ega bo'lmaydi.

Ombor o'xshatishida: ro'yxatni ko'chiribgina qolmay, yangi shkaf olib, ichiga asboblarning ham nusxasini qo'yish.

Zamonaviy JavaScript'da buning uchun tayyor funksiya bor — structuredClone:

js
const profil = { ism: "Malika", manzil: { shahar: "Toshkent" } };

const qoralama = structuredClone(profil);
qoralama.manzil.shahar = "Samarqand";

console.log(profil.manzil.shahar); // Toshkent
console.log(profil.manzil === qoralama.manzil); // false

Muammo hal bo'ldi. Endi manzil ham alohida nusxalandi: asl profil daxlsiz.

structuredClone 2022-yildan beri barcha zamonaviy brauzerlarda va Node 17+ da bor. Hech narsa o'rnatish yoki import qilish kerak emas.

5.2 U nimalarni nusxalay oladi

structuredClone faqat oddiy obyekt va massivlarni emas, ko'p boshqa turlarni ham to'g'ri nusxalaydi:

js
const buyurtma = {
  id: 7,
  sana: new Date("2026-09-27"),
  izoh: undefined,
  chegirma: NaN,
  taomlar: [{ nomi: "Osh", soni: 2 }],
};

const nusxa = structuredClone(buyurtma);

console.log(nusxa.sana.getFullYear()); // 2026
console.log("izoh" in nusxa); // true
console.log(nusxa.chegirma); // NaN
console.log(nusxa.taomlar[0] === buyurtma.taomlar[0]); // false

new Date("2026-09-27") — sana saqlaydigan obyekt, getFullYear() esa undan yilni oladi. Sanalarni alohida darsda o'rganamiz, hozir faqat "bu sana" deb biling. Muhimi: nusxada ham u haqiqiy sana bo'lib qoldi. undefined qiymatli xususiyat va NaN ham joyida.

structuredClone yana Map, Set (keyinroq o'rganadigan ma'lumot tuzilmalari) va hatto o'z-o'ziga havola qilgan obyektlarni ham to'g'ri nusxalaydi.

5.3 Nimani nusxalay olmaydi

Funksiyani nusxalay olmaydi. Obyektda funksiya (yoki metod) bo'lsa, xato beradi:

js
const talaba = { ism: "Jasur", salomBer: () => "Salom!" };

const nusxa = structuredClone(talaba);

Node'da:

text
DOMException [DataCloneError]: () => "Salom!" could not be cloned.

Tarjimasi: "Nusxalash xatosi: () => "Salom!" nusxalanmaydi". JavaScript xabarga funksiyaning kodini qo'yib, aynan qaysi qiymat to'sqinlik qilganini ko'rsatadi. Funksiya uzun bo'lsa, xabar ham bir necha qatorga cho'ziladi. DataCloneError — "ma'lumotni klonlash xatosi". DOMException — brauzer standartidan kelgan xato turi, uni hozir chuqur bilish shart emas. Brauzer konsolida xabar biroz boshqacha: DataCloneError: Failed to execute 'structuredClone' on 'Window': ... could not be cloned. Ma'nosi bir xil.

Nega aynan funksiya? structuredClone faqat ma'lumotni nusxalaydi. Funksiya esa ma'lumot emas, bajariladigan kod. Uni boshqa joyga to'g'ri ko'chirishning umumiy usuli yo'q.

Yana ikki narsa nusxalanmaydi:

  • DOM elementlari — sahifadagi HTML elementlarning JavaScript'dagi ko'rinishi. Ularni keyingi qismda o'rganamiz. structuredClone ga tugma yoki <div> bersangiz, xuddi shu DataCloneError chiqadi.
  • Klass nusxalari xato bermaydi, lekin nusxa oddiy obyektga aylanadi — metodlari yo'qoladi. Klasslarni kursning keyingi qismida o'rganamiz, hozir bilish shart emas.

Maslahat: Amaliy qoida: ma'lumotni (son, satr, massiv, oddiy obyekt) funksiyalardan alohida saqlang. Shunda uni har doim bemalol nusxalay olasiz. React va boshqa vositalardagi "holat" (state) aynan shunday toza ma'lumot bo'ladi.

Tekshirib ko'ring: Qaysi obyektni structuredClone xatosiz nusxalaydi?

A) { ism: "Ali", baholar: [5, 4, 5] } B) { ism: "Ali", hisobla: () => 5 } C) { ism: "Ali", tugilgan: new Date("2005-03-21") }

Javob

A va C. A — oddiy satr va massiv. C — sana, structuredClone uni to'g'ri nusxalaydi. B da esa funksiya bor (arrow ham funksiya), shuning uchun DataCloneError chiqadi.

6. Eski usul: JSON.parse(JSON.stringify(obj))

6.1 Qanday ishlaydi

structuredClone paydo bo'lishidan oldin dasturchilar boshqa hiyla ishlatardi. Uni eski kodda va internetdagi eski javoblarda ko'p uchratasiz:

js
const asl = { ism: "Malika", manzil: { shahar: "Toshkent" } };
const nusxa = JSON.parse(JSON.stringify(asl));

nusxa.manzil.shahar = "Samarqand";
console.log(asl.manzil.shahar); // Toshkent

JSON formatini birinchi qismlarda ko'rgansiz — u ma'lumotni matn ko'rinishida saqlaydi. JSON.stringify(obj) obyektni JSON matniga aylantiradi. JSON.parse(matn) esa matndan butunlay yangi obyekt yasaydi. Ikkalasini JSON darsida batafsil o'rganamiz.

Ya'ni obyekt avval matnga "eritiladi", keyin matndan qaytadan "quyiladi". Natijada eski obyekt bilan hech qanday havola qolmaydi.

6.2 Nimani yo'qotadi

Muammo shundaki, JSON faqat oddiy turlarni biladi. Qolganlari yo'l-yo'lakay buziladi:

js
const buyurtma = {
  sana: new Date("2026-09-27"),
  izoh: undefined,
  chegirma: NaN,
  hisobla() {
    return 0;
  },
};

const nusxa = JSON.parse(JSON.stringify(buyurtma));
console.log(nusxa);
console.log(typeof nusxa.sana);

Konsolda:

text
{ sana: '2026-09-27T00:00:00.000Z', chegirma: null }
string

Xato chiqmadi — va aynan shu xavfli. Natijani solishtiramiz:

Asl qiymat JSON nusxada structuredClone da
Sana (Date) Satr bo'lib qoldi Sana
undefined Xususiyat yo'qoldi undefined
Funksiya Xususiyat yo'qoldi DataCloneError
NaN, Infinity null O'zi

Sana satrga aylangani keyinroq kutilmagan xato beradi. Masalan, nusxa.sana.getFullYear() chaqirsangiz:

text
TypeError: nusxa.sana.getFullYear is not a function

"nusxa.sana.getFullYear — funksiya emas". Chunki nusxa.sana endi oddiy satr, satrda esa bunday metod yo'q. Xato nusxa olingan joyda emas, ancha keyin chiqadi — sababini topish qiyin.

Yana bir farq: JSON usuli o'z-o'ziga havola qilgan obyektda TypeError: Converting circular structure to JSON beradi. structuredClone bunday obyektni ham bemalol nusxalaydi.

Maslahat: Yangi kodda chuqur nusxa uchun structuredClone ishlating. JSON usulini faqat ma'lumot aniq oddiy bo'lsa (son, satr, boolean, massiv, obyekt) va eski muhitda ishlash kerak bo'lsa qo'llang.

6.3 Kutubxonalar haqida bir og'iz

Eski loyihalarda _.cloneDeep(obj) ni ham ko'rasiz. Bu — lodash kutubxonasining chuqur nusxa funksiyasi (lodash — npm'dagi mashhur yordamchi funksiyalar to'plami). Bugun ko'p holatda uning o'rniga o'rnatilgan structuredClone yetarli.

7. Qaysi birini tanlash kerak?

Vaziyat Tanlov
Faqat birinchi qavat bor Spread { ...obj } / [...arr]
Ichma-ich, to'liq mustaqil nusxa kerak structuredClone
Ichida funksiya bor Ma'lumotni funksiyadan ajrating
Bitta ichki qiymatni yangilash Immutable yangilash (pastda)

Chuqur nusxani "har ehtimolga qarshi" hamma joyda ishlatmang. Katta obyektni har safar to'liq nusxalash sekin va xotirani ko'p egallaydi. Ko'pincha kerak bo'lgani — keyingi bo'limdagi usul.

8. Ichma-ich ma'lumotni immutable yangilash

8.1 Faqat o'zgaradigan yo'lni nusxalash

Profil ichida faqat shaharni o'zgartirish kerak. Butun profilni chuqur nusxalash shart emas. O'zgaradigan "yo'l"dagi har bir qavatni spread bilan nusxalash yetarli:

js
const profil = {
  ism: "Malika",
  manzil: { shahar: "Toshkent", tuman: "Chilonzor" },
  kurslar: ["JS", "Python"],
};

const yangi = {
  ...profil,
  manzil: { ...profil.manzil, shahar: "Samarqand" },
};

console.log(profil.manzil.shahar);
console.log(yangi.manzil);
console.log(yangi.kurslar === profil.kurslar);

Konsolda:

text
Toshkent
{ shahar: 'Samarqand', tuman: 'Chilonzor' }
true

Qatorma-qator:

  • ...profil — tashqi qavat nusxalandi: yangi obyekt.
  • manzil: { ...profil.manzil, shahar: "Samarqand" } — manzil ham yangi obyekt. Undagi eski xususiyatlar ko'chirildi, keyin shahar ustidan yozildi.
  • kurslar ga tegmadik — u ikkala obyektda umumiy qoldi (true).

Oxirgi qator xato emas, balki afzallik. kurslar o'zgarmadi, demak uni nusxalashga hojat yo'q. O'zgargan qismi yangi, o'zgarmagani eskisi bilan umumiy.

Immutable yangilash (immutable — "o'zgarmas") — asl ma'lumotga tegmasdan, o'zgarishlar kiritilgan yangi nusxa yasash. Asl ma'lumotni joyida o'zgartirish esa mutatsiya deyiladi.

8.2 Massiv ichidagi obyektni yangilash

Savatdagi ikkinchi mahsulot sonini 3 ga o'zgartiramiz:

js
const savat = [
  { nomi: "Non", soni: 2 },
  { nomi: "Sut", soni: 1 },
];

const yangiSavat = [...savat];
yangiSavat[1] = { ...savat[1], soni: 3 };

console.log(savat[1].soni); // 1
console.log(yangiSavat[1].soni); // 3
console.log(yangiSavat[0] === savat[0]); // true

Avval massivning sayoz nusxasi olindi. Keyin o'zgaradigan element o'rniga yangi obyekt qo'yildi. Birinchi mahsulot umumiy qoldi — u o'zgarmagan.

Massivlarni bunday yangilashning qisqaroq usullari (map, with) bor. Ularni map darsida va nusxa bilan o'zgartirish darsida ko'ramiz.

8.3 Bu nega muhim: React haqida bir gap

React — sayt interfeysini yasaydigan eng mashhur kutubxona, unga kursda alohida qism bor. U ma'lumot o'zgarganini === bilan tekshiradi. Obyekt joyida o'zgartirilsa, havola o'sha-o'sha qoladi — React o'zgarishni sezmaydi va ekran yangilanmaydi. Yangi obyekt yasalsa, havola o'zgaradi va ekran yangilanadi.

Shu sababli React bilan ishlaganda siz har kuni aynan profil misolidagi naqshni yozasiz. To'liq amaliyot — ichma-ich ma'lumotni immutable yangilash darsida.

Tekshirib ko'ring: Bo'sh joyni to'ldiring. const s = { til: "uz", ovoz: { baland: 5 } } obyektida faqat baland ni 8 ga o'zgartiramiz: const y = { ...s, ovoz: { , baland: 8 } };. Shundan keyin s.ovoz.baland ning qiymati bo'ladi.

9. Ko'p uchraydigan xatolar

9.1 "Spread qildim — endi mustaqil"

Eng ko'p uchraydigan xato. Spread faqat birinchi qavatni nusxalaydi. Obyekt ichida obyekt yoki massiv bo'lsa, ular umumiy qoladi. Tekshirish usuli: asl.ichki === nusxa.ichki — true chiqsa, ichki qism umumiy.

9.2 Tayinlashni nusxa deb o'ylash

js
const asl = { ism: "Ali" };
const nusxa = asl;
nusxa.ism = "Vali";

console.log(asl.ism); // Vali

= hech narsani nusxalamaydi, faqat havolani ko'chiradi. Nusxa uchun kamida { ...asl } kerak.

9.3 Metodli obyektni structuredClone qilish

text
DOMException [DataCloneError]: () => "Salom!" could not be cloned.

Obyektda funksiya bor. Yechim: nusxalashdan oldin faqat ma'lumot qismini ajrating yoki spread ishlating (u funksiyani havola sifatida ko'chiradi).

9.4 JSON usulidan keyin "... is not a function"

text
TypeError: nusxa.sana.getFullYear is not a function

JSON nusxada sana satrga aylangan. structuredClone ga o'ting.

9.5 Object.assign ga birinchi argument sifatida aslni berish

js
const asl = { ism: "Ali", yosh: 20 };
const nusxa = Object.assign(asl, { yosh: 21 });

console.log(asl.yosh); // 21
console.log(nusxa === asl); // true

Object.assign birinchi argumentni o'zgartiradi va uning o'zini qaytaradi. To'g'risi: Object.assign({}, asl, { yosh: 21 }) yoki { ...asl, yosh: 21 }.

10. Mashqlar

1-mashq (oson): Natijani toping

Kodni ishga tushirmasdan, konsolda nima chiqishini ayting. Keyin tekshiring.

js
const kitob = { nomi: "Alpomish", muallif: { ism: "Xalq" } };
const nusxa = { ...kitob };

nusxa.nomi = "Kuntug'mish";
nusxa.muallif.ism = "Fozil Yo'ldosh o'g'li";

console.log(kitob.nomi);
console.log(kitob.muallif.ism);
Yechim
js
const kitob = { nomi: "Alpomish", muallif: { ism: "Xalq" } };
const nusxa = { ...kitob };

nusxa.nomi = "Kuntug'mish";
nusxa.muallif.ism = "Fozil Yo'ldosh o'g'li";

console.log(kitob.nomi); // Alpomish
console.log(kitob.muallif.ism); // Fozil Yo'ldosh o'g'li

nomi — birinchi qavatdagi satr, nusxada mustaqil. muallif esa ichma-ich obyekt: sayoz nusxada ikkalasi bitta obyektga qaraydi.

2-mashq (o'rta): Qoralamani tuzating

Quyidagi kodda qoralama ni o'zgartirish asl sozlama ni ham buzyapti. Bitta qatorni o'zgartirib, xatoni tuzating: sozlama.bildirishnoma.email true bo'lib qolsin. structuredClone ni ishlating.

js
const sozlama = {
  til: "uz",
  bildirishnoma: { email: true, sms: false },
};

const qoralama = { ...sozlama };
qoralama.bildirishnoma.email = false;

console.log(sozlama.bildirishnoma.email); // false
Yechim
js
const sozlama = {
  til: "uz",
  bildirishnoma: { email: true, sms: false },
};

const qoralama = structuredClone(sozlama);
qoralama.bildirishnoma.email = false;

console.log(sozlama.bildirishnoma.email); // true
console.log(qoralama.bildirishnoma.email); // false

structuredClone bildirishnoma ni ham alohida nusxaladi. Endi qoralama ni istalgancha o'zgartirsangiz ham, asl sozlama daxlsiz.

3-mashq (qiyin): Immutable yangilash

baholarniYangila(talaba, fan, baho) funksiyasini yozing. U talaba obyektini o'zgartirmasdan, baholar ichidagi fan ga baho qo'yilgan yangi obyekt qaytarsin. structuredClone ishlatmang — faqat spread. Kalitni o'zgaruvchidan olish uchun computed kalit [fan]: baho kerak bo'ladi.

js
const talaba = {
  ism: "Nodira",
  baholar: { matematika: 4, fizika: 5 },
  guruh: { nomi: "JS-12" },
};

Tekshiring: asl talaba.baholar.matematika 4 bo'lib qolsin, guruh esa yangi obyektda eski obyekt bilan umumiy bo'lsin.

Yechim
js
function baholarniYangila(talaba, fan, baho) {
  return {
    ...talaba,
    baholar: { ...talaba.baholar, [fan]: baho },
  };
}

const talaba = {
  ism: "Nodira",
  baholar: { matematika: 4, fizika: 5 },
  guruh: { nomi: "JS-12" },
};

const yangi = baholarniYangila(talaba, "matematika", 5);

console.log(talaba.baholar.matematika); // 4
console.log(yangi.baholar); // { matematika: 5, fizika: 5 }
console.log(yangi.guruh === talaba.guruh); // true

Faqat o'zgaradigan yo'l nusxalandi: tashqi obyekt va baholar. guruh ga tegmadik, shuning uchun u umumiy qoldi. Funksiya toza funksiya: kirgan obyektni o'zgartirmaydi, yangi natija qaytaradi.

11. Real ishda

  • React va Redux: holatni (state) yangilashda har doim shu darsdagi immutable naqsh ishlatiladi. Joyida o'zgartirish — React'da ekran yangilanmasligining eng ko'p sababi.
  • Formalar va "Bekor qilish": tahrirlashdan oldin structuredClone bilan qoralama olinadi.
  • Undo (ortga qaytarish): har bir o'zgarishdan oldingi holat saqlanadi. Sayoz nusxada bu tarix "o'z-o'zidan" buzilib ketadi.
  • Web Worker va postMessage: brauzer ma'lumotni boshqa oqimga yuborganda aynan structuredClone algoritmini ishlatadi. Funksiya yuborib bo'lmasligi ham shundan.

Intervyuda "Shallow va deep copy farqi nima?" savoli deyarli har doim beriladi. Yaxshi javob: sayoz nusxa faqat birinchi qavatni ko'chiradi, ichki obyektlar havola bilan umumiy qoladi; chuqur nusxa hamma qavatni ko'chiradi — zamonaviy usul structuredClone, JSON usuli esa sana va undefined ni yo'qotadi.

Xulosa

  • const b = a — nusxa emas, bitta obyektga ikkinchi havola.
  • Spread, Object.assign({}, obj), slice(), Array.from — sayoz nusxa: ichki obyektlar umumiy qoladi.
  • structuredClone(obj) — chuqur nusxa: sana, Map, Set ham to'g'ri; funksiya va DOM elementida DataCloneError.
  • JSON.parse(JSON.stringify(obj)) — eski usul: sana satrga aylanadi, undefined va funksiya yo'qoladi, NaN → null.
  • Ichma-ich yangilashda faqat o'zgaradigan yo'lni spread bilan nusxalang — bu React'ning kundalik naqshi.

08-qism yakuni: endi nimalarni bilasiz

Tabriklaymiz — "JavaScript asoslari" qismi tugadi! 61 dars oldin siz JavaScript'da bitta qator ham yozmagan edingiz. Endi esa:

  • O'zgaruvchi, ma'lumot turlari va operatorlar bilan ishlaysiz. == va === farqini, yashirin tur o'zgarishlarini tushunasiz.
  • Matn va sonlar bilan ishlaysiz: qidirish, kesish, formatlash, aniq pul hisobi.
  • if, switch va sikllar bilan dastur mantiqini qurasiz.
  • Funksiya yozasiz: parametr, return, arrow, callback, scope, rekursiya.
  • Massiv va obyektlarni yaratasiz, aylanasiz, destructuring va spread qilasiz, to'g'ri nusxalaysiz.
  • Xatoni o'qiysiz va DevTools bilan kodni qadamma-qadam tekshirasiz.

Bu — har qanday JavaScript dasturining "tili". Lekin hozircha kodingiz faqat konsolda yashaydi.

Keyingi qism — "JavaScript brauzerda va debugging". Unda JavaScript'ni sahifaga ulaymiz: tugma bosilganda nimadir sodir bo'ladi, forma to'ldiriladi, ro'yxat ekranda chiziladi. Shu qismda birinchi haqiqiy interaktiv ilovangizni — vazifalar ro'yxatini yasaysiz. Bu qismda o'rgangan obyekt, massiv va immutable yangilash u yerda har qadamda kerak bo'ladi.

Keyingi dars: Brauzer muhiti: window, document va skript yuklanishi — brauzer JavaScript'ga qanday imkoniyatlar berishini va skript sahifaga qachon yuklanishini o'rganamiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript'da obyektni nusxalash: sayoz va chuqur nusxa, structuredClone — IlmHamroh