Rumah >hujung hadapan web >tutorial js >Cetek vs penyalinan dalam dalam javascript

Cetek vs penyalinan dalam dalam javascript

Jennifer Aniston
Jennifer Anistonasal
2025-02-09 08:28:10901semak imbas

Shallow vs. Deep Copying in JavaScript

Menyalin objek JavaScript tidak semudah yang kelihatannya. Memahami bagaimana objek dan rujukan berfungsi semasa proses ini adalah penting kepada pemaju web dan dapat menjimatkan waktu debugging. Ini menjadi semakin penting apabila anda menggunakan aplikasi yang besar, seperti yang dibina dalam React atau Vue.

Salinan cetek dan salinan dalam Rujuk bagaimana kita membuat salinan objek dalam JavaScript dan data apa yang kita buat dalam "Salin". Dalam artikel ini, kami akan menggali jauh ke dalam perbezaan antara kaedah ini, meneroka aplikasi praktikal mereka, dan mengungkap potensi perangkap yang mungkin timbul apabila menggunakannya.

mata utama

    Salinan cetek dalam JavaScript mencipta objek baru yang menyalin sifat objek yang ada, tetapi mengekalkan rujukan yang sama kepada nilai asal atau objek. Ini bermakna bahawa pengubahsuaian kepada objek bersarang dalam replika cetek juga mempengaruhi objek asal dan mana -mana replika cetek lain.
  • Sebaliknya, salinan dalam membuat salinan tepat objek yang ada, termasuk semua sifatnya dan mana -mana objek bersarang, bukan hanya rujukan. Ini menjadikan penyalinan mendalam bermanfaat apabila anda memerlukan dua objek berasingan yang tidak berkongsi rujukan, memastikan perubahan kepada satu objek tidak menjejaskan yang lain.
  • Walaupun replikasi yang mendalam memberikan manfaat ketepatan data, ia juga mungkin mempunyai beberapa kelemahan seperti kesan prestasi, peningkatan penggunaan memori, isu rujukan pekeliling, fungsi dan pengendalian objek khas, dan kerumitan pelaksanaan. Oleh itu, adalah penting untuk menilai sama ada replikasi yang mendalam diperlukan untuk setiap kes penggunaan tertentu.
apa itu "cetek" salinan

Salinan cetek merujuk kepada proses membuat objek baru, yang merupakan salinan objek sedia ada yang sifatnya merujuk kepada nilai berangka atau objek yang sama sebagai objek asal. Dalam JavaScript, ini biasanya dicapai menggunakan kaedah seperti

atau sintaks pengembangan (). Salinan cetek hanya mencipta rujukan baru kepada objek atau nilai sedia ada, dan tidak membuat salinan yang mendalam, yang bermaksud bahawa objek bersarang masih dirujuk, bukan pendua. Object.assign() {...originalObject} Mari kita lihat contoh kod berikut. Objek yang baru dibuat

adalah salinan

yang dicipta dengan memperluaskan pengendali, yang mempunyai beberapa akibat yang tidak dijangka. shallowCopyZoo zoo

Tetapi mari kita lihat apa sebenarnya yang ada dalam
<code class="language-javascript">let zoo = {
  name: "Amazing Zoo",
  location: "Melbourne, Australia",
  animals: [
    {
      species: "Lion",
      favoriteTreat: "?",
    },
    {
      species: "Panda",
      favoriteTreat: "?",
    },
  ],
};

let shallowCopyZoo = { ...zoo };
shallowCopyZoo.animals[0].favoriteTreat = "?";
console.log(zoo.animals[0].favoriteTreat); 
// "?",而不是 "?"</code>
. Ciri -ciri

dan shallowCopyZoo adalah nilai asal (rentetan), jadi nilai mereka disalin. Walau bagaimanapun, harta name adalah pelbagai objek, jadi apa yang disalin adalah rujukan kepada array itu, bukan array itu sendiri. location animals anda boleh menggunakan pengendali kesamaan yang ketat (

) untuk menguji ini dengan cepat (jika anda tidak mempercayai saya). Hanya apabila objek merujuk kepada objek yang sama, satu objek adalah sama dengan objek lain (lihat jenis data primitif dan jenis data rujukan). Perhatikan bahawa atribut

adalah sama dalam kedua -duanya, tetapi objek itu sendiri tidak sama. ===

<code class="language-javascript">let zoo = {
  name: "Amazing Zoo",
  location: "Melbourne, Australia",
  animals: [
    {
      species: "Lion",
      favoriteTreat: "?",
    },
    {
      species: "Panda",
      favoriteTreat: "?",
    },
  ],
};

let shallowCopyZoo = { ...zoo };
shallowCopyZoo.animals[0].favoriteTreat = "?";
console.log(zoo.animals[0].favoriteTreat); 
// "?",而不是 "?"</code>

Ini boleh menyebabkan masalah yang berpotensi dalam asas kod dan sangat sukar apabila berurusan dengan pengubahsuaian yang besar. Mengubah objek bersarang dalam replika cetek juga mempengaruhi objek asal dan mana -mana replika cetek lain kerana mereka semua berkongsi rujukan yang sama.

Salinan Deep

Salinan Deep adalah silap mata untuk membuat objek baru yang merupakan salinan tepat objek yang ada. Ini termasuk menyalin semua sifatnya dan mana -mana objek bersarang, bukannya rujukan. Pengklonan yang mendalam berguna apabila anda memerlukan dua objek berasingan yang tidak berkongsi rujukan, memastikan perubahan kepada satu objek tidak menjejaskan yang lain.

Pengaturcara sering menggunakan pengklonan yang mendalam apabila berurusan dengan objek keadaan aplikasi dalam aplikasi yang kompleks. Mewujudkan objek negara baru tanpa menjejaskan keadaan terdahulu adalah penting untuk mengekalkan kestabilan aplikasi dan dengan betul melaksanakan fungsi Undo/Redo.

cara menggunakan JSON.stringify() dan JSON.parse() untuk salinan dalam

Kaedah salinan yang popular dan bebas perpustakaan adalah menggunakan kaedah terbina dalam JSON.stringify() dan JSON.parse().

parse(stringify()) Kaedah ini tidak sempurna. Sebagai contoh, jenis data khas seperti Date akan ditukar kepada rentetan, dan nilai yang tidak ditentukan akan diabaikan. Seperti semua pilihan dalam artikel ini, anda harus mempertimbangkannya berdasarkan kes penggunaan khusus anda.

Dalam kod berikut, kami akan menggunakan kaedah ini untuk membuat fungsi deepCopy untuk mengklonkan objek dengan mendalam. Kemudian kami menyalin objek playerProfile dan mengubahsuai objek yang disalin tanpa menjejaskan objek asal. Ini menunjukkan nilai replikasi yang mendalam dalam mengekalkan objek bebas yang tidak berkongsi rujukan.

<code class="language-javascript">console.log(zoo.animals === shallowCopyZoo.animals)
// true

console.log(zoo === shallowCopyZoo)
// false</code>

perpustakaan untuk replikasi yang mendalam

Terdapat juga pelbagai perpustakaan pihak ketiga yang menyediakan penyelesaian replikasi yang mendalam.

    Fungsi
  • Lodash Library cloneDeep() boleh mengendalikan rujukan, fungsi, dan objek khas dengan betul.
  • Fungsi perpustakaan jQuery
  • Perpustakaan Immer extend() dibina untuk pemaju React-Redux dan menyediakan alat yang mudah untuk mengubahsuai objek. [deep = true]
  • Fungsi Salin Deep Vanilla JS
Jika atas sebab tertentu, anda tidak mahu menggunakan objek JSON atau perpustakaan pihak ketiga, anda juga boleh membuat fungsi salinan yang tersuai dalam vanila JavaScript. Fungsi ini secara rekursif melangkah ke atas sifat objek dan mewujudkan objek baru dengan sifat dan nilai yang sama.

Kelemahan Salinan Deep

<code class="language-javascript">const playerProfile = {
  name: 'Alice',
  level: 10,
  achievements: [
    {
      title: 'Fast Learner',
      emoji: '?'
    },
    {
      title: 'Treasure Hunter',
      emoji: '?'
    }
  ]
};

function deepCopy(obj) {
  return JSON.parse(JSON.stringify(obj));
}

const clonedProfile = deepCopy(playerProfile);

console.log(clonedProfile);
// 输出与playerProfile相同

// 修改克隆的配置文件而不影响原始配置文件
clonedProfile.achievements.push({ title: 'Marathon Runner', emoji: '?' });
console.log(playerProfile.achievements.length); // 输出:2
console.log(clonedProfile.achievements.length); // 输出:3</code>
Walaupun replikasi yang mendalam memberikan manfaat yang besar untuk ketepatan data, adalah disyorkan untuk menilai sama ada replikasi yang mendalam diperlukan untuk setiap kes penggunaan tertentu. Dalam sesetengah kes, penyalinan cetek atau teknik lain untuk menguruskan rujukan objek mungkin lebih sesuai, dengan itu memberikan prestasi yang lebih baik dan mengurangkan kerumitan.

  1. Kesan prestasi: Replikasi yang mendalam boleh dikira secara mahal, terutamanya apabila berurusan dengan objek besar atau kompleks. Oleh kerana proses replikasi yang mendalam melangkah ke atas semua sifat bersarang, ia boleh mengambil banyak masa untuk menjejaskan prestasi permohonan anda secara negatif.
  2. Penggunaan memori: Mencipta hasil salinan yang mendalam di seluruh hierarki objek, termasuk semua objek bersarang. Ini boleh membawa kepada peningkatan penggunaan memori, yang boleh menjadi masalah dalam persekitaran yang terkawal memori atau ketika memproses dataset yang besar.
  3. rujukan bulat: Penyalinan dalam boleh menyebabkan masalah apabila objek mengandungi rujukan bulat (iaitu, apabila sifat objek merujuk kepada dirinya sendiri secara langsung atau tidak langsung). Rujukan gelung boleh menyebabkan gelung tak terhingga atau kesilapan limpahan stack semasa penyalinan yang mendalam, dan mengendalikannya memerlukan logik tambahan untuk mengelakkan masalah ini.
  4. Fungsi dan pengendalian objek khas: Salinan dalam tidak boleh mengendalikan fungsi atau objek dengan ciri -ciri khas seperti yang diharapkan (contohnya, Date, RegExp, elemen dom). Sebagai contoh, apabila menyalin objek yang mendalam yang mengandungi fungsi, rujukan kepada fungsi boleh disalin, tetapi penutupan fungsi dan konteks terikatnya tidak akan disalin. Begitu juga, objek dengan ciri -ciri khas mungkin kehilangan sifat dan tingkah laku unik mereka apabila ditiru secara mendalam.
  5. Kerumitan pelaksanaan: Menulis fungsi salinan dalam adat boleh menjadi rumit, dan kaedah terbina dalam seperti JSON.parse(JSON.stringify(obj)) juga mempunyai beberapa batasan, seperti tidak dapat mengendalikan fungsi dengan betul, rujukan bulat, atau objek khas. Walaupun terdapat beberapa perpustakaan pihak ketiga seperti Lodash _.cloneDeep() yang mengendalikan replikasi yang mendalam dengan lebih cekap, menambah kebergantungan luaran untuk replikasi yang mendalam mungkin tidak selalu ideal.

Kesimpulan

Terima kasih kerana meluangkan masa untuk membaca artikel ini. Replikasi cetek dan mendalam jauh lebih kompleks daripada mana -mana pemula yang mungkin berfikir. Walaupun terdapat banyak perangkap dalam setiap pendekatan, meluangkan masa untuk mengkaji semula dan mempertimbangkan pilihan ini akan memastikan bahawa aplikasi dan data anda menyimpan apa yang anda mahu.

Soalan Lazim mengenai Replikasi Cetek dan Deep dalam JavaScript (FAQ)

Apakah perbezaan utama antara replikasi cetek dan mendalam dalam JavaScript?

Perbezaan utama antara replikasi cetek dan mendalam adalah cara mereka mengendalikan sifat sebagai objek. Dalam salinan cetek, objek yang disalin berkongsi rujukan yang sama kepada objek bersarang sebagai objek asal. Ini bermakna perubahan kepada objek bersarang akan ditunjukkan dalam objek asal dan objek salinan. Replikasi yang mendalam, sebaliknya, mencipta contoh baru objek bersarang, yang bermaksud perubahan kepada objek bersarang dalam objek yang direplikasi tidak mempengaruhi objek asal.

Bagaimanakah pengendali pengembangan berfungsi dalam salinan cetek?

Pengendali pengembangan (...) dalam JavaScript biasanya digunakan untuk menyalin cetek. Ia menyalin semua sifat yang boleh dibaca satu objek kepada yang lain. Walau bagaimanapun, ia hanya menyalin atribut peringkat pertama dan rujukan kepada objek bersarang. Oleh itu, perubahan kepada objek bersarang akan menjejaskan objek asal dan objek yang disalin.

Bolehkah saya menggunakan kaedah JSON untuk menyalin dalam?

Ya, anda boleh menggunakan kaedah JSON untuk melakukan penyalinan dalam dalam JavaScript. Gabungan kaedah JSON.stringify() dan JSON.parse() mencipta salinan objek yang mendalam. JSON.stringify() Menukar objek ke rentetan, JSON.parse() menghancurkan rentetan kembali ke objek baru. Walau bagaimanapun, kaedah ini mempunyai beberapa batasan kerana ia tidak menyalin kaedah dan tidak sesuai untuk objek JavaScript khas seperti Date, RegExp, Map, Set, dll.

Apakah batasan replikasi cetek?

Salinan cetek hanya mereplikasi atribut peringkat pertama dan rujukan kepada objek bersarang. Oleh itu, jika objek asal mengandungi objek bersarang, perubahan kepada objek bersarang itu akan mempengaruhi objek asal dan objek yang disalin. Ini boleh membawa kepada keputusan dan kesilapan yang tidak dijangka dalam kod.

Object.assign() Bagaimanakah kaedah berfungsi dalam salinan cetek?

Kaedah

Object.assign() digunakan untuk menyalin nilai semua sifat yang boleh dibaca satu atau lebih objek sumber ke objek sasaran. Ia mengembalikan objek sasaran. Walau bagaimanapun, ia melakukan penyalinan cetek, yang bermaksud ia hanya menyalin sifat peringkat pertama dan rujukan kepada objek bersarang.

Apakah cara terbaik untuk menyalin objek dalam JavaScript?

Cara terbaik untuk menyalin objek dalam JavaScript bergantung kepada keperluan khusus kod tersebut. Jika objek anda tidak mengandungi kaedah atau objek JavaScript khas, anda boleh menggunakan gabungan kaedah JSON.stringify() dan JSON.parse(). Untuk objek yang lebih kompleks, anda mungkin mahu menggunakan perpustakaan seperti Lodash, yang menyediakan fungsi pengklonan yang mendalam.

Bolehkah saya menggunakan pengendali pengembangan untuk menyalin dalam?

Tidak, pengendali pengembangan dalam JavaScript hanya melakukan penyalinan cetek. Ia menyalin atribut peringkat pertama dan rujukan kepada objek bersarang. Untuk melakukan replikasi yang mendalam, anda perlu menggunakan kaedah atau perpustakaan lain.

Apakah kesan prestasi replikasi yang mendalam?

Replikasi yang mendalam mungkin mengambil lebih banyak sumber daripada replikasi cetek, terutamanya untuk objek besar. Ini kerana salinan dalam mencipta contoh baru untuk semua objek bersarang, yang boleh mengambil lebih banyak memori dan kuasa pemprosesan.

Bagaimana menangani rujukan bulat dalam replikasi yang mendalam?

Kaedah salinan yang mendalam seperti

JSON.stringify() dan JSON.parse() jangan mengendalikan rujukan bulat dan akan membuang ralat. Rujukan bulat berlaku apabila sifat objek merujuk kepada objek itu sendiri. Untuk mengendalikan rujukan bulat, anda perlu menggunakan perpustakaan yang menyokongnya, seperti Lodash.

Kenapa saya perlu mengambil berat tentang perbezaan antara salinan cetek dan salinan dalam?

Memahami perbezaan antara replikasi cetek dan mendalam adalah penting untuk menguruskan data dalam JavaScript. Ia mempengaruhi bagaimana objek anda berinteraksi antara satu sama lain. Sekiranya anda tidak berhati -hati, penyalinan cetek boleh menyebabkan keputusan dan kesilapan yang tidak dijangka, kerana perubahan kepada objek bersarang mempengaruhi objek asal dan disalin. Salinan yang mendalam, sebaliknya, memastikan objek salinan anda sepenuhnya bebas dari objek asal.

Atas ialah kandungan terperinci Cetek vs penyalinan dalam dalam javascript. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn