... di mana setiap objek juga memiliki referensi ke objek lain dalam array yang sama?
Ketika saya pertama kali datang dengan masalah ini saya hanya memikirkan sesuatu seperti
var clonedNodesArray = nodesArray.clone()
akan ada dan mencari info tentang cara mengkloning objek dalam javascript. Saya memang menemukan pertanyaan tentang StackOverflow (dijawab oleh @JohnResig yang sama) dan dia menunjukkan bahwa dengan jQuery Anda bisa melakukannya
var clonedNodesArray = jQuery.extend({}, nodesArray);
untuk mengkloning suatu objek. Saya mencoba ini, ini hanya menyalin referensi objek dalam array. Jadi kalau saya
nodesArray[0].value = "red"
clonedNodesArray[0].value = "green"
nilai dari kedua nodesArray [0] dan cloningNodesArray [0] akan berubah menjadi "hijau". Lalu saya mencoba
var clonedNodesArray = jQuery.extend(true, {}, nodesArray);
yang dalam menyalin Obyek, tetapi saya mendapat " terlalu banyak rekursi " dan " control stack overflow " pesan dari Firebug dan Opera Dragonfly.
Bagaimana Anda melakukannya? Apakah ini sesuatu yang seharusnya tidak dilakukan? Apakah ada cara yang dapat digunakan kembali untuk melakukan ini dalam Javascript?
sumber
Selama objek Anda mengandung konten JSON-serializable (tidak ada fungsi, tidak
Number.POSITIVE_INFINITY
, dll.) Tidak perlu ada loop untuk mengkloning array atau objek. Berikut ini adalah solusi satu garis vanila murni.Untuk meringkas komentar di bawah ini, keuntungan utama dari pendekatan ini adalah bahwa ia juga mengkloning isi array, bukan hanya array itu sendiri. Kelemahan utama adalah batasnya hanya bekerja pada konten JSON-serializable, dan kinerjanya (yang secara signifikan lebih buruk daripada
slice
pendekatan berbasis).sumber
null
danundefined
akan menjadi masalah, karena JSON tidak mendukungnya). Lebih jauh, ini adalah operasi yang jauh lebih efisien daripadaold_array.slice(0);
, yang seharusnya bekerja lebih baik dan lebih cepat.Saya memecahkan kloning array objek dengan Object.assign
atau bahkan lebih pendek dengan sintaksis spread
sumber
{}
dengannew Dinosaur()
.Jika yang Anda butuhkan hanyalah salinan dangkal, cara yang sangat mudah adalah:
sumber
0
, Anda bisa menelepon.slice()
setidaknya di chromeslice
akan menjadi array baru tetapi akan berisi referensi ke objek array asli.Cara terbaik dan terbaru untuk melakukan klon ini adalah sebagai berikut:
Menggunakan
...
operator penyebaran ES6.Inilah Contoh yang paling sederhana:
Dengan cara ini kami menyebarkan array ke nilai individual dan meletakkannya di array baru dengan operator [].
Berikut ini contoh yang lebih panjang yang menunjukkan berbagai cara kerjanya:
sumber
Ini bekerja untuk saya:
Dan jika Anda membutuhkan salinan objek dalam array:
sumber
sumber
JSON.parse(JSON.stringify(origArray));
JSON.parse(JSON.stringify(origArray));
jelas merupakan solusi paling sederhana.Peta akan membuat array baru dari yang lama (tanpa referensi ke yang lama) dan di dalam peta Anda membuat objek baru dan beralih ke properti (kunci) dan menetapkan nilai dari objek Array lama ke properti yang sesuai dengan objek baru.
Ini akan membuat array objek yang persis sama.
sumber
Saya mungkin memiliki cara sederhana untuk melakukan ini tanpa harus melakukan rekursi yang menyakitkan dan tidak mengetahui semua detail objek yang dipertanyakan. Menggunakan jQuery, cukup konversikan objek Anda menjadi JSON menggunakan jQuery
$.toJSON(myObjectArray)
, lalu ambil string JSON Anda dan evaluasi kembali ke suatu objek. BAM! Selesai, dan selesai! Masalah terpecahkan. :)sumber
eval
.eval()
sama sekali. Ini risiko keamanan.Saya menjawab pertanyaan ini karena sepertinya tidak ada solusi yang sederhana dan eksplisit untuk masalah "kloning array objek dalam Javascript":
Solusi ini mengulangi nilai-nilai array, kemudian mengulangi kunci objek, menyimpan yang terakhir ke objek baru, dan kemudian mendorong objek baru itu ke array baru.
Lihat jsfiddle . Catatan: sederhana
.slice()
atau[].concat()
tidak cukup untuk objek dalam array.sumber
Extend JQuery berfungsi dengan baik, hanya Anda perlu menentukan bahwa Anda mengkloning array daripada objek ( perhatikan [] alih-alih {} sebagai parameter ke metode extended ):
sumber
Metode ini sangat sederhana dan Anda dapat memodifikasi klon Anda tanpa mengubah array asli.
sumber
[...oldArray]
danoldArray.slice(0)
melakukan salinan yang dangkal satu tingkat. Jadi ini sangat berguna, tetapi bukan klon penuh dalam yang sebenarnya.lodash.clonedeep
dari npmSeperti Daniel Lew sebutkan, grafik siklik memiliki beberapa masalah. Jika saya punya masalah ini saya akan menambahkan khusus
clone()
metode ke objek bermasalah atau ingat objek yang sudah saya salin.Saya akan melakukannya dengan variabel
copyCount
yang bertambah 1 setiap kali Anda menyalin kode Anda. Objek yang memilikicopyCount
proses copy yang lebih rendah dari saat ini disalin. Jika tidak, salinan yang sudah ada harus dirujuk. Ini membuatnya perlu untuk menghubungkan dari aslinya ke salinannya.Masih ada satu masalah: Memori. Jika Anda memiliki referensi ini dari satu objek ke objek lain, kemungkinan peramban tidak dapat membebaskan objek-objek tersebut, karena mereka selalu dirujuk dari suatu tempat. Anda harus membuat langkah kedua di mana Anda mengatur semua referensi-salinan ke Null. (Jika Anda melakukan ini, Anda tidak harus memiliki
copyCount
tetapi booleanisCopied
akan cukup, karena Anda dapat mengatur ulang nilai di pass kedua.)sumber
Array.slice dapat digunakan untuk menyalin array atau bagian dari array .. http://www.devguru.com/Technologies/Ecmascript/Quickref/Slice.html Ini akan bekerja dengan string dan angka .. - mengubah string dalam satu array tidak akan mempengaruhi yang lain - tetapi objek masih hanya disalin oleh referensi sehingga perubahan ke objek yang direferensikan dalam satu array akan mempengaruhi array lainnya.
Berikut ini adalah contoh dari manajer undo JavaScript yang dapat bermanfaat untuk ini: http://www.ridgway.co.za/archive/2007/11/07/simple-javascript-undo-manager-for-dtos.aspx
sumber
Pendekatan saya:
memberi saya klon yang bagus, bersih, dalam dari array asli - dengan tidak ada objek yang dirujuk kembali ke aslinya :-)
sumber
lodash memiliki
cloneDeep
fungsi untuk tujuan ini:sumber
Jika Anda ingin menerapkan klon dalam, gunakan JSON.parse (JSON.stringify ({} atau []) Anda)
sumber
forget eval () (adalah fitur JS yang paling banyak disalahgunakan dan membuat kodenya lambat) dan slice (0) (hanya berfungsi untuk tipe data sederhana)
Ini solusi terbaik bagi saya:
sumber
Saya cukup frustrasi dengan masalah ini. Tampaknya masalah muncul ketika Anda mengirim Array umum ke metode $ .extend. Jadi, untuk memperbaikinya, saya menambahkan sedikit centang, dan berfungsi dengan baik dengan array umum, array jQuery, dan objek apa pun.
Meminta menggunakan:
sumber
Ini sangat menyalin array, objek, nilai null dan skalar lainnya, dan juga sangat menyalin setiap properti pada fungsi non-asli (yang sangat jarang tetapi mungkin). (Untuk efisiensi, kami tidak mencoba menyalin properti non-numerik pada array.)
sumber
Saya menggunakan metode ECMAScript 6 Object.assign baru :
argumen pertama dari metode ini adalah array yang akan diperbarui, kami melewatkan objek kosong karena kami ingin memiliki objek baru.
kita juga bisa menggunakan sintaks ini, yang sama tetapi lebih pendek:
sumber
Kita dapat menemukan metode Array rekursif sederhana untuk mengkloning array multidimensi. Sementara objek dalam array bersarang tetap referensi ke objek yang sesuai dalam array sumber, array tidak akan.
sumber
Dalam JavaScript, array dan salin objek mengubah nilai asal, jadi Salinan yang dalam adalah solusi untuk ini.
Salinan dalam berarti benar-benar membuat array baru dan menyalin nilai-nilai, karena apa pun yang terjadi padanya tidak akan pernah memengaruhi yang asli.
JSON.parse
danJSON.stringify
merupakan cara terbaik dan sederhana untuk menyalin. TheJSON.stringify()
Metode mualaf nilai JavaScript untuk JSON string.TheJSON.parse()
metode mem-parsing string JSON, membangun nilai JavaScript atau objek yang dijelaskan oleh string.// Klon Dalam
Untuk lebih jelasnya: Baca Di Sini
sumber
dengan jQuery:
sumber
Kode berikut akan melakukan penyalinan dalam objek dan array secara rekursif :
Sumber
sumber
arguments.callee
tidak tersedia dalam mode ketat dan memiliki masalah kinerja sebaliknya.Beberapa cara elegan untuk kloning dalam javascript
https://mootools.net/core/docs/1.6.0/Types/Object
https://scotch.io/bar-talk/copying-objects-in-javascript
1) Metode Javascript vanilla untuk kloning objek
2) Eksploitasi pintar dari pustaka JSON untuk objek klon-dalam
3) Menggunakan fungsi $ .extend () jQuery
4) Menggunakan fungsi klon () Mootools untuk mengkloning objek
sumber
Saya pikir berhasil menulis metode generik kloning mendalam setiap struktur JavaScript terutama menggunakan
Object.create
yang didukung di semua browser modern. Kodenya seperti ini:sumber
Object.create
akan memperlakukanitem
sebagai prototipe objek, tetapi itu berbeda dari kloning. Jikaitem
diubah, perubahan akan tercermin dalam "klon" dan sebaliknya. Pendekatan ini tidak berhasil.Untuk mengkloning objek juga saya hanya akan menyarankan ECMAScript 6
reduce()
:Tapi terus terang saya lebih suka jawaban @dinodsaurus. Saya hanya menempatkan versi ini di sini sebagai opsi lain, tetapi secara pribadi saya akan menggunakan
map()
seperti yang disarankan oleh @dododsaurus.sumber
Tergantung jika Anda memiliki Garis Bawah atau Babel di sini adalah Tolok Ukur dari berbagai cara kloning dalam array.
https://jsperf.com/object-rest-spread-vs-clone/2
Sepertinya babel adalah yang tercepat.
sumber
sumber