Obyekt havolalari va nusxalash
Obyektlar va primitivlar o'rtasidagi eng muhim farqlardan biri โ ular saqlanish va ko'chirilish usulida. Primitivlar to'liq qiymat bilan, obyektlar esa havola (reference) bilan ishlaydi. Bu farqni tushunmaslik ko'plab "g'alati" xatolarga sabab bo'ladi.
Primitivlar nusxalanadi
Primitiv turdagi o'zgaruvchi (satr, son, boolean) o'z qiymatini to'liq saqlaydi. Uni boshqa o'zgaruvchiga tenglashtirsak, qiymatning nusxasi ko'chiriladi โ ikki mustaqil qiymat hosil bo'ladi:
Obyektlar havola orqali saqlanadi
Obyekt o'zgaruvchisi obyektning o'zini emas, balki uning xotiradagi manzilini โ ya'ni "havola"ni saqlaydi. Buni quyidagicha tasavvur qiling: obyekt โ bir qutida, o'zgaruvchi esa โ o'sha qutiga yopishtirilgan qog'oz (manzil, kalit).
let user = {
name: "Jaloliddin"
};
// user o'zgaruvchisi obyektning "manzilini" saqlaydi,
// obyektning o'zini emas.
Xossaga murojaat qilganda (user.name), JavaScript avval havola bo'yicha obyektni topadi, keyin uning ichidagi xossani o'qiydi.
Havolani nusxalash
Obyekt o'zgaruvchisini nusxalasak, obyekt EMAS, balki havola nusxalanadi. Natijada ikkala o'zgaruvchi ham bitta va o'sha obyektga ishora qiladi:
Bu "ikkita kaliti bor bitta shkaf"ga o'xshaydi: bittasi bilan ochib narsa qo'ysak, ikkinchi kalit egasi ham o'sha narsani ko'radi. Obyekt bitta, unga ikkita havola bor.
let b = a obyektni nusxalamaydi; u faqat yana bitta havola yaratadi.Havola orqali taqqoslash
== va === operatorlari ikkita obyekt uchun bir xil ishlaydi: ular faqat ikkala havola bitta va o'sha obyektga ishora qilsagina true qaytaradi:
Ammo tashqi ko'rinishi bir xil, ammo mustaqil ikkita obyekt HAR DOIM teng emas:
Object.assign bilan nusxalash
Chinakam nusxa โ mustaqil, alohida obyekt โ kerak bo'lsa-chi? Buning uchun barcha xossalarni yangi obyektga ko'chirish kerak. Buni qo'lda for..in bilan qilsa bo'ladi, ammo tayyor usul bor: Object.assign.
Sintaksis: Object.assign(dest, ...sources). U sourcesdagi barcha xossalarni destga ko'chiradi va destni qaytaradi:
Object.assign bir nechta manbani ham birlashtira oladi. Bir xil nomli xossa bo'lsa, oxirgisi ustun keladi:
let clone = {...user};. U ham xuddi shunday sayoz nusxa yaratadi.Sayoz nusxa (shallow copy) muammosi
Object.assign (va spread) faqat bir daraja chuqurlikda nusxalaydi. Agar xossa qiymati o'zi obyekt bo'lsa, u nusxalanmaydi โ uning havolasi ko'chiriladi. Bunga sayoz nusxa (shallow copy) deyiladi:
Chuqur nusxa: structuredClone
Bunday muammoni bartaraf qilish uchun chuqur nusxa (deep clone) kerak โ barcha darajadagi ichki obyektlar ham nusxalanadi. Zamonaviy JavaScript'da buning uchun ichki structuredClone funksiyasi bor:
structuredClone istalgan chuqurlikdagi obyektlarni, hatto o'z-o'ziga ishora qiluvchi (siklik) obyektlarni ham to'g'ri nusxalay oladi.
structuredClone funksiya (metod) qiymatlarini nusxalay olmaydi โ bunday obyektni uzatsangiz xato beradi. Bunday murakkab hollarda tashqi kutubxonalar (masalan, lodash'ning _.cloneDeep) yordam beradi.Xulosa
- Primitivlar qiymat bilan, obyektlar havola bilan saqlanadi;
let b = aobyekt uchun faqat havolani nusxalaydi โ obyekt bitta bo'lib qoladi;==va===obyektlar uchun faqat bir xil havolani teng deb hisoblaydi;Object.assign({}, obj)yoki{...obj}โ sayoz nusxa yaratadi;- Sayoz nusxada ichki obyektlar hamon ulashilgan;
structuredClone(obj)โ chuqur nusxa yaratadi, barcha darajalarni mustaqil qiladi.