[ Web Proxy ]
URL:
Viewing: https://uz.javascript.info/object-copy [Back]  [Original]

Obyekt havolalari va nusxalash
UZ

Ushbu ochiq manbali loyihani butun dunyo bo'ylab odamlar uchun taqdim etmoqchimiz.

Ushbu qo'llanmaning mazmuni sizning tilingizga tarjima qilishga yordam bering!

    Javascript.info saytidan qidirish:
    O'quv qo'llanmasidan qidiring:
    Light themeDark theme
    DanskEnglishEspaolFranaisIndonesiaItalianoTrkeOzbek

    Obyekt havolalari va nusxalash

    Obyektlar va primitivlar ortasidagi asosiy farqlardan biri shundaki, obyektlar havola boyicha saqlanadi va nusxalanadi, primitivlar esa: satrlar, raqamlar, boolean va hokazo har doim toliq qiymat sifatida nusxalanadi.

    Qiymat nusxalanganda nima sodir bolishini biroz chuqurroq korsak, buni tushunish oson.

    Satr kabi primitiv bilan boshlaylik.

    Bu yerda biz message ning nusxasini phrase ga qoyamiz:

    let message = "Salom!";
    let phrase = message;

    Natijada bizda ikkita mustaqil ozgaruvchi bor, har biri "Salom!" satrini saqlaydi.

    []

    Aniq natija, togrimi?

    Obyektlar bunday emas.

    Obyektga tayinlangan ozgaruvchi obyektning ozini emas, balki uning xotiradagi manzilini boshqacha qilib aytganda, unga havolani saqlaydi.

    Bunday ozgaruvchining misolini koramiz:

    let user = {
      name: "John",
    };

    Va u xotirada qanday saqlanishi:

    []

    Obyekt xotirada biror joyda saqlanadi (rasmning ong tomonida), user ozgaruvchisi (chap tomonda) esa unga havola qiladi.

    user kabi obyekt ozgaruvchisini obyektning manzili yozilgan qogoz varaq deb tasavvur qilishimiz mumkin.

    Obyekt bilan amallarni bajarganimizda, masalan user.name xossasini olganimizda, JavaScript dvigateli osha manzilda nima borligini koradi va haqiqiy obyektda operatsiyani bajaradi.

    Endi bu nima uchun muhimligi.

    Obyekt ozgaruvchisi nusxalanganda, havola nusxalanadi, lekin obyektning ozi takrorlanmaydi.

    Masalan:

    let user = { name: "John" };
    
    let admin = user; // havolani nusxalash

    Endi bizda ikkita ozgaruvchi bor, har biri bir xil obyektga havola qiladi:

    []

    Korib turganingizdek, hali ham bitta obyekt bor, lekin endi unga havola qiluvchi ikkita ozgaruvchi bor.

    Obyektga kirish va uning tarkibini ozgartirish uchun har qanday ozgaruvchidan foydalanishimiz mumkin:

    let user = { name: 'John' };
    
    let admin = user;
    
    admin.name = 'Pete'; // "admin" havolasi orqali o'zgartirildi
    
    alert(user.name); // 'Pete', o'zgarishlar "user" havolasidan ko'rinadi

    Bu xuddi bizda ikkita kaliti bolgan shkaf bolgandek va ulardan birini (admin) ishlatib unga kirib ozgarishlar qildik. Keyin, agar boshqa kalitni (user) ishlatsak, biz hali ham bir xil shkafdamiz va ozgartirilgan tarkibga kira olamiz.

    Havola boyicha solishtirish

    Ikki obyekt faqat bir xil obyekt bolsagina teng hisoblanadi.

    Masalan, bu yerda a va b bir xil obyektga havola qiladi, shuning uchun ular teng:

    let a = {};
    let b = a; // havolani nusxalash
    
    alert(a == b); // true, ikkala o'zgaruvchi bir xil obyektga havola qiladi
    alert(a === b); // true

    Va bu yerda ikkita mustaqil obyekt teng emas, garchi ular oxshash korinsa ham (ikkalasi ham bosh):

    let a = {};
    let b = {}; // ikkita mustaqil obyekt
    
    alert(a == b); // false

    obj1 > obj2 kabi solishtirishlar uchun yoki primitiv bilan solishtirish obj == 5 uchun, obyektlar primitivlarga aylantiriladi. Obyekt aylantirishlari qanday ishlashini tez orada organamiz, lekin rostini aytganda, bunday solishtirishlar juda kam kerak boladi odatda ular dasturlash xatosi natijasida paydo boladi.

    Const obyektlarni ozgartirish mumkin

    Obyektlarni havola sifatida saqlashning muhim yon tasiri shundaki, const sifatida elon qilingan obyektni ozgartirish mumkin.

    Masalan:

    const user = {
      name: "John"
    };
    
    user.name = "Pete"; // (*)
    
    alert(user.name); // Pete

    (*) qatori xato keltirib chiqarishi kerak bolgandek tuyuladi, lekin bunday emas. user qiymati doimiy, u har doim bir xil obyektga havola qilishi kerak, lekin osha obyektning xossalari erkin ozgarishi mumkin.

    Boshqacha qilib aytganda, const user faqat biz user=... ni butunlay ornatishga harakat qilganimizda xato beradi.

    Shuni aytish kerakki, agar biz haqiqatan ham doimiy obyekt xossalarini yaratishimiz kerak bolsa, bu ham mumkin, lekin butunlay boshqa usullardan foydalanib. Buni Xususiyat bayroqlari va tavsiflovchilar bobida eslatamiz.

    Klonlash va birlashtirish, Object.assign

    Shunday qilib, obyekt ozgaruvchisini nusxalash bir xil obyektga yana bir havola yaratadi.

    Lekin agar bizga obyektni takrorlash kerak bolsa-chi?

    Biz yangi obyekt yaratishimiz va mavjud obyektning tuzilmasini takrorlashimiz mumkin, uning xossalari boylab iteratsiya qilib va ularni primitiv darajada nusxalash orqali.

    Quyidagicha:

    let user = {
      name: "John",
      age: 30
    };
    
    let clone = {}; // yangi bo'sh obyekt
    
    // keling, user ning barcha xossalarini unga nusxalaylik
    for (let key in user) {
      clone[key] = user[key];
    }
    
    // endi clone bir xil tarkibga ega to'liq mustaqil obyekt
    clone.name = "Pete"; // undagi ma'lumotni o'zgartirdik
    
    alert( user.name ); // asl obyektda hali ham John

    Shuningdek, biz Object.assign usulidan ham foydalanishimiz mumkin.

    Sintaksis:

    Object.assign(dest, ...sources);
    • Birinchi argument dest maqsadli obyekt.
    • Keyingi argumentlar manba obyektlar royxati.

    U barcha manba obyektlarning xossalarini maqsadli dest ga nusxalaydi va keyin natija sifatida uni qaytaradi.

    Masalan, bizda user obyekt bor, unga bir nechta ruxsatlar qoshamiz:

    let user = { name: "John" };
    
    let permissions1 = { canView: true };
    let permissions2 = { canEdit: true };
    
    // permissions1 va permissions2 ning barcha xossalarini user ga nusxalaydi
    Object.assign(user, permissions1, permissions2);
    
    // endi user = { name: "John", canView: true, canEdit: true }
    alert(user.name); // John
    alert(user.canView); // true
    alert(user.canEdit); // true

    Agar nusxalangan xossa nomi allaqachon mavjud bolsa, u qayta yoziladi:

    let user = { name: "John" };
    
    Object.assign(user, { name: "Pete" });
    
    alert(user.name); // endi user = { name: "Pete" }

    Shuningdek, biz Object.assign dan oddiy obyekt klonlash uchun ham foydalanishimiz mumkin:

    let user = {
      name: "John",
      age: 30
    };
    
    let clone = Object.assign({}, user);
    
    alert(clone.name); // John
    alert(clone.age); // 30

    Bu yerda u user ning barcha xossalarini bosh obyektga nusxalaydi va uni qaytaradi.

    Obyektni klonlashning boshqa usullari ham bor, masalan spread sintaksisi clone = {...user} dan foydalanish, oquv qollanmasida keyinroq yoritilgan.

    Ichma-ich klonlash

    Hozirgacha biz user ning barcha xossalari primitiv deb faraz qildik. Lekin xossalar boshqa obyektlarga havolalar bolishi mumkin.

    Quyidagicha:

    let user = {
      name: "John",
      sizes: {
        height: 182,
        width: 50,
      },
    };
    
    alert(user.sizes.height); // 182

    Endi clone.sizes = user.sizes ni nusxalash yetarli emas, chunki user.sizes obyekt va havola boyicha nusxalanadi, shuning uchun clone va user bir xil sizes ni bolishadi:

    let user = {
      name: "John",
      sizes: {
        height: 182,
        width: 50,
      },
    };
    
    let clone = Object.assign({}, user);
    
    alert(user.sizes === clone.sizes); // true, bir xil obyekt
    
    // user va clone sizes ni bo'lishadi
    user.sizes.width = 60; // bir joydan xossani o'zgartirish
    alert(clone.sizes.width); // 60, natijani boshqa joydan olish

    Buni tuzatish va user bilan clone ni haqiqatan ham alohida obyektlar qilish uchun biz user[key] ning har bir qiymatini tekshiradigan va agar u obyekt bolsa, uning tuzilmasini ham takrorlaydigan klonlash tsiklidan foydalanishimiz kerak. Bu chuqur klonlash yoki tuzilmaviy klonlash deb ataladi. Chuqur klonlashni amalga oshiradigan structuredClone usuli mavjud.

    structuredClone

    structuredClone(object) chaqiruvi object ni barcha ichma-ich xossalar bilan klonlaydi.

    Misolimizda qanday foydalanishni koramiz:

    let user = {
      name: "John",
      sizes: {
        height: 182,
        width: 50
      }
    };
    
    let clone = structuredClone(user);
    
    alert( user.sizes === clone.sizes ); // false, turli obyektlar
    
    // user va clone endi butunlay bog'liq emas
    user.sizes.width = 60;    // bir joydan xossani o'zgartirish
    alert(clone.sizes.width); // 50, bog'liq emas

    structuredClone usuli obyektlar, massivlar, primitiv qiymatlar kabi kopchilik malumot turlarini klonlay oladi.

    U shuningdek obyekt xossasi obyektning oziga havola qilgan (bevosita yoki havolalar zanjiri orqali) aylanma havolalarni ham qollab-quvvatlaydi.

    Masalan:

    let user = {};
    // keling, aylanma havola yarataylik:
    // user.me user ning o'ziga havola qiladi
    user.me = user;
    
    let clone = structuredClone(user);
    alert(clone.me === clone); // true

    Korib turganingizdek, clone.me user ga emas, clone ga havola qiladi! Shunday qilib, aylanma havola ham togri klonlandi.

    Garchi, structuredClone muvaffaqiyatsiz bolgan holatlar ham bor.

    Masalan, obyektda funksiya xossasi bolganda:

    // xato
    structuredClone({
      f: function () {},
    });

    Funksiya xossalari qollab-quvvatlanmaydi.

    Bunday murakkab holatlarni hal qilish uchun bizga klonlash usullarining kombinatsiyasidan foydalanish, maxsus kod yozish yoki gildirakni qayta ixtiro qilmaslik uchun mavjud implementatsiyani olish kerak bolishi mumkin, masalan lodash JavaScript kutubxonasidagi _.cloneDeep(obj).

    Xulosa

    Obyektlar havola boyicha tayinlanadi va nusxalanadi. Boshqacha qilib aytganda, ozgaruvchi obyekt qiymati ni emas, balki qiymat uchun havola (xotiradagi manzil) ni saqlaydi. Shunday qilib, bunday ozgaruvchini nusxalash yoki uni funksiya argumenti sifatida uzatish obyektning ozini emas, osha havolani nusxalaydi.

    Nusxalangan havolalar orqali barcha amallar (xossalar qoshish/olib tashlash kabi) bir xil obyektda amalga oshiriladi.

    Haqiqiy nusxa (klon) yaratish uchun biz sayoz nusxa (ichma-ich obyektlar havola boyicha nusxalanadi) uchun Object.assign dan yoki chuqur klonlash funksiyasi structuredClone dan yoki _.cloneDeep(obj) kabi maxsus klonlash implementatsiyasidan foydalanishimiz mumkin.

    O'quv qo'llanma xaritasi

    Izohlar

    izoh berishdan oldin buni o'qing
    • Agar sizda nimani yaxshilash kerakligi haqida takliflaringiz bo'lsa - iltimos, GitHub muammosini yuboring yoki izoh berish o'rniga so'rov yuboring.
    • Agar siz maqolada biror narsani tushunolmasangiz - iltimos, batafsilroq ma'lumot bering.
    • Bir nechta so'z so'zlarini kiritish uchun <code> yorlig'ini ishlating, bir nechta satrlar uchun - ularni <pre> yorlig'i bilan o'rab qo'ying, 10 satrdan ortiq bo'lsa - sandbox (plnkr, jsbin, codepen)

    Web Proxy Viewer  |  New URL  |  Original Page