Saat menyalin array dalam JavaScript ke array lain:
var arr1 = ['a','b','c'];
var arr2 = arr1;
arr2.push('d'); //Now, arr1 = ['a','b','c','d']
Saya menyadari bahwa arr2
mengacu pada array yang sama dengan arr1
, bukan array baru yang independen. Bagaimana saya bisa menyalin array untuk mendapatkan dua array independen?
javascript
arrays
Dan
sumber
sumber
slice
dansplice
operasi dan operator penyebaran baru danArray.from
memiliki implementasi yang jauh lebih lambat. Lihatlah perfjs.fnfovar arr2 = arr1.splice();
untuk salinan yang mendalam, tetapi teknik ini tidak akan bekerja jika elemen dalam array mengandung struktur literal (yaitu[]
atau{}
) atau benda prototipe (yaitufunction () {}
,new
, dll). Lihat jawaban saya di bawah ini untuk solusi lebih lanjut.let arr2 = [...arr1];
developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Jawaban:
Gunakan ini:
Pada dasarnya,
slice()
operasi mengkloning array dan mengembalikan referensi ke array baru.Perhatikan juga bahwa:
Untuk referensi, string, dan angka (dan bukan objek sebenarnya),
slice()
salin referensi objek ke dalam array baru. Baik array asli dan baru merujuk ke objek yang sama. Jika objek yang direferensikan berubah, perubahan tersebut dapat dilihat oleh array baru dan asli.Primitif seperti string dan angka tidak dapat diubah, sehingga perubahan pada string atau angka tidak dimungkinkan.
sumber
.slice()
dengan.splice()
, yang memberi Anda array kosong. Perbedaan besar.Dalam Javascript, teknik salin dalam bergantung pada elemen dalam array. Ayo mulai dari sana.
Tiga jenis elemen
Elemen dapat berupa: nilai literal, struktur literal, atau prototipe.
Dari elemen-elemen ini kita dapat membuat tiga jenis array.
Teknik penyalinan dalam tergantung pada tiga jenis array
Berdasarkan jenis elemen dalam array, kita dapat menggunakan berbagai teknik untuk menyalin dalam.
Array literal-nilai (type1)
The
[...myArray]
,myArray.splice(0)
,myArray.slice()
, danmyArray.concat()
teknik dapat digunakan untuk array salinan yang mendalam dengan nilai-nilai literal (boolean, nomor, dan string) saja; di mana operator Spread[...myArray]
memiliki kinerja terbaik ( https://measurethat.net/Benchmarks/Show/4281/0/spread-array-performance-vs-slice-splice-concat ).Array literal-nilai (type1) dan literal-struktur (type2)
The
JSON.parse(JSON.stringify(myArray))
Teknik dapat digunakan untuk nilai-nilai copy dalam literal (boolean, nomor, string) dan struktur literal (array, objek), tetapi tidak prototipe benda.Semua array (type1, type2, type3) Teknik
jQuery
$.extend(myArray)
dapat digunakan untuk menyalin semua tipe array. Perpustakaan seperti Underscore dan Lo-dash menawarkan fungsi salin yang serupa ke jQuery$.extend()
, namun memiliki kinerja yang lebih rendah. Lebih mengejutkan,$.extend()
memiliki kinerja lebih tinggi daripadaJSON.parse(JSON.stringify(myArray))
teknik http://jsperf.com/js-deep-copy/15 .Dan untuk pengembang yang menghindar dari perpustakaan pihak ketiga (seperti jQuery), Anda dapat menggunakan fungsi kustom berikut; yang memiliki kinerja lebih tinggi dari $. memperpanjang, dan menyalin semua array.
Jadi untuk menjawab pertanyaan ...
Pertanyaan
Menjawab
Karena
arr1
merupakan array nilai literal (boolean, angka, atau string), Anda dapat menggunakan teknik penyalinan dalam apa pun yang dibahas di atas, di mana operator spread...
memiliki kinerja tertinggi.sumber
arr1
. Sangat jarang hal itu terjadi. Menggunakansplice
melenyapkanarr1
, jadi itu bukan salinan sama sekali. MenggunakanJSON
akan gagal jika salah satu nilai dalam array adalah Functions atau memiliki prototipe (seperti aDate
).[0,"1",{2:3},function random() {return 4;}, [[5,6,7],[8,9,10],[11,12,13]]]
dan array lainnya.Anda dapat menggunakan spread array
...
untuk menyalin array.const itemsCopy = [...items];
Juga jika ingin membuat array baru dengan yang sudah ada menjadi bagian darinya:
Spread array sekarang didukung di semua browser utama tetapi jika Anda membutuhkan dukungan yang lebih lama gunakan skrip atau babel dan kompilasi ke ES5.
Info lebih lanjut tentang spread
sumber
Tidak perlu jQuery ... Contoh Kerja
Ini menyalin array dari posisi awal
0
hingga akhir array.Penting untuk dicatat bahwa ini akan berfungsi seperti yang diharapkan untuk tipe primitif (string, angka, dll.), Dan juga untuk menjelaskan perilaku yang diharapkan untuk tipe referensi ...
Jika Anda memiliki larik tipe Referensi, katakanlah tipe
Object
. Array akan disalin, tetapi kedua array akan berisi referensi ke yang samaObject
. Jadi dalam hal ini akan terlihat seperti array disalin oleh referensi meskipun array sebenarnya disalin.sumber
var arr2 = JSON.stringify(arr1); arr2 = JSON.parse(arr2);
Alternatif
slice
adalahconcat
, yang dapat digunakan dalam 2 cara. Yang pertama mungkin lebih mudah dibaca karena perilaku yang dimaksud sangat jelas:Metode kedua adalah:
Cohen (dalam komentar) menunjukkan bahwa metode yang terakhir ini memiliki kinerja yang lebih baik .
Cara kerjanya adalah bahwa
concat
metode ini menciptakan array baru yang terdiri dari elemen-elemen dalam objek yang dipanggil diikuti oleh elemen-elemen dari setiap array yang diteruskan kepadanya sebagai argumen. Jadi ketika tidak ada argumen yang dilewatkan, itu hanya menyalin array.Lee Penkman, juga di komentar, menunjukkan bahwa jika ada kesempatan
array1
adalahundefined
, Anda dapat mengembalikan array kosong sebagai berikut:Atau, untuk metode kedua:
Perhatikan bahwa Anda juga dapat melakukan ini dengan
slice
:var array2 = (array1 || []).slice();
.sumber
[].concat(array1)
mengembalikan[array1]
misalnya jika itu tidak ditentukan, Anda akan mendapatkan[undefined]
. Saya kadang-kadang melakukannyavar array2 = [].concat(array1 || []);
Inilah yang saya lakukan setelah mencoba banyak pendekatan:
Ini akan membuat salinan dalam baru yang tidak terkait dengan yang pertama (bukan salinan dangkal).
Juga ini jelas tidak akan mengkloning acara dan fungsi, tetapi hal baiknya Anda dapat melakukannya dalam satu baris, dan itu dapat digunakan untuk segala jenis objek (array, string, angka, objek ...)
sumber
Date
, atau memang, apa pun yang memiliki prototipe. Selain itu,undefined
s dapat dikonversi kenull
s.Beberapa metode yang disebutkan bekerja dengan baik ketika bekerja dengan tipe data sederhana seperti angka atau string, tetapi ketika array berisi objek lain metode ini gagal. Ketika kami mencoba untuk meneruskan objek apa pun dari satu array ke array lainnya, ia dilewatkan sebagai referensi, bukan objek.
Tambahkan kode berikut dalam file JavaScript Anda:
Dan cukup gunakan
Itu akan berhasil.
sumber
.slice()
masih berfungsi dengan baik bahkan jika Anda memiliki objek dalam array Anda: jsfiddle.net/edelman/k525gDari ES2015,
sumber
Saya pribadi berpikir bahwa Array . Dari solusi yang lebih mudah dibaca. Omong-omong, berhati-hatilah dengan dukungan browsernya.
sumber
.slice()
solusi adalah benar-benar unintuitive. Terima kasih untuk ini.Penting!
Sebagian besar jawaban di sini berfungsi untuk kasus-kasus tertentu .
Jika Anda tidak peduli tentang penggunaan benda dalam dan bersarang ( ES6 ):
let clonedArray = [...array]
tetapi jika Anda ingin melakukan klon yang dalam gunakan ini sebagai gantinya:
let cloneArray = JSON.parse(JSON.stringify(array))
Untuk pengguna lodash:
let clonedArray = _.clone(array)
dokumentasidan
let clonedArray = _.cloneDeep(array)
dokumentasisumber
Jika Anda berada di lingkungan ECMAScript 6 , menggunakan Spread Operator, Anda bisa melakukannya dengan cara ini:
sumber
Menambahkan ke solusi array.slice (); perlu diketahui bahwa jika Anda memiliki sub-array array multidimensi akan disalin oleh referensi. Apa yang dapat Anda lakukan adalah untuk loop dan mengiris () setiap sub-array secara individual
hal yang sama berlaku untuk array objek, mereka akan disalin dengan referensi, Anda harus menyalinnya secara manual
sumber
Nilai-nilai primitif selalu dilewati oleh nilainya (disalin). Namun nilai gabungan dilewatkan dengan referensi.
Jadi bagaimana kita menyalin arr ini?
Salin Array di ES6
Salin dan Array di ES5
Mengapa `biarkan arrCopy = arr` tidak melewati nilai?
Melewati satu variabel ke variabel lain pada nilai Compound seperti Object / Array berperilaku berbeda. Menggunakan operator asign pada nilai-nilai copand kami meneruskan referensi ke objek. Inilah sebabnya mengapa nilai kedua array berubah ketika menghapus / menambahkan elemen arr.
Pengecualian:
Ketika Anda menetapkan nilai baru ke variabel, Anda mengubah referensi itu sendiri dan itu tidak mempengaruhi Objek / Array asli.
Baca lebih banyak
sumber
Seperti yang kita ketahui dalam array dan objek Javascript adalah dengan referensi, tetapi cara apa yang bisa kita lakukan menyalin array tanpa mengubah array asli nanti?
Berikut ini beberapa cara untuk melakukannya:
Bayangkan kita memiliki larik ini dalam kode Anda:
1) Looping melalui array dalam suatu fungsi dan mengembalikan array baru, seperti ini:
2) Menggunakan metode slice, slice adalah untuk mengiris bagian dari array, itu akan mengiris beberapa bagian dari array Anda tanpa menyentuh aslinya, dalam slice, jika tidak menentukan awal dan akhir array, itu akan mengiris keseluruhan array dan pada dasarnya membuat salinan penuh array, sehingga kita dapat dengan mudah mengatakan:
3) Juga metode kontak, ini untuk menggabungkan dua array, tetapi kita bisa menentukan satu array dan kemudian ini pada dasarnya membuat salinan nilai-nilai dalam array yang dihubungi baru:
4) Juga metode string dan parse, itu tidak disarankan, tetapi bisa menjadi cara mudah untuk menyalin Array dan Objek:
5) metode Array.from, ini tidak didukung secara luas, sebelum digunakan periksa dukungan di browser yang berbeda:
6) Cara ECMA6, juga tidak sepenuhnya didukung, tetapi babelJs dapat membantu Anda jika Anda ingin melakukan transile:
sumber
Sekarang Anda dapat melakukan salah satu dari yang berikut ini untuk membuat salinan array.
ATAU
ATAU
ATAU
ATAU
Sekarang, jika saya mengubah,
Kemudian, a adalah [1,2,3,5] tetapi b masih [1,2,3] karena memiliki referensi yang berbeda.
Tetapi saya pikir, dalam semua metode di atas Array.from lebih baik dan dibuat terutama untuk menyalin array.
sumber
Saya pribadi lebih suka dengan cara ini:
sumber
Dalam kasus khusus saya, saya perlu memastikan array tetap utuh sehingga ini bekerja untuk saya:
sumber
Buat salinan array / objek multidimensi:
Terima kasih kepada James Padolsey untuk fungsi ini.
Sumber: Di sini
sumber
Dan, tidak perlu menggunakan trik mewah. Yang perlu Anda lakukan adalah membuat salinan arr1 dengan melakukan ini.
Sekarang
arr1
danarr2
dua variabel array berbeda disimpan di tumpukan terpisah. Lihat ini di jsfiddle .sumber
var arr2 = [arr1];
).Ketika kita ingin menyalin array menggunakan operator penugasan (
=
) itu tidak membuat salinan itu hanya menyalin pointer / referensi ke array. Sebagai contoh:Seringkali ketika kita mengubah data, kita ingin mempertahankan struktur data awal kita (misalnya Array). Kami melakukan ini dengan membuat salinan yang tepat dari array kami sehingga yang ini dapat diubah sementara yang awal tetap utuh.
Cara menyalin array:
Hati-hati saat array atau objek bersarang !:
Ketika array bersarang nilai disalin oleh referensi. Berikut adalah contoh bagaimana hal ini dapat menyebabkan masalah:
Jadi jangan gunakan metode ini ketika ada objek atau array di dalam array yang ingin Anda salin. yaitu Gunakan metode ini hanya pada array primitif.
Jika Anda ingin mendalami penggunaan array javascript
JSON.parse
bersamaJSON.stringify
, seperti ini:Kinerja penyalinan:
Jadi yang mana yang kita pilih untuk kinerja yang optimal. Ternyata metode yang paling verbose,
for
loop memiliki kinerja tertinggi. Gunakanfor
loop untuk menyalin intensif CPU (array besar / banyak).Setelah itu
.slice()
metode ini juga memiliki kinerja yang layak dan juga kurang bertele-tele dan lebih mudah bagi programmer untuk diimplementasikan. Saya sarankan untuk digunakan.slice()
untuk menyalin array Anda sehari-hari yang tidak terlalu intensif CPU. Juga hindari menggunakanJSON.parse(JSON.stringify(arr))
(banyak overhead) jika tidak diperlukan klon dalam dan kinerja adalah masalah.Uji kinerja sumber
sumber
Jika array Anda mengandung elemen tipe data primitif seperti int, char, atau string dll, maka Anda dapat menggunakan salah satu metode yang mengembalikan salinan array asli seperti .slice () atau .map () atau operator spread ( terima kasih kepada ES6).
atau
atau
TETAPI jika array Anda mengandung elemen kompleks seperti objek (atau array) atau lebih banyak objek bersarang , maka, Anda harus memastikan bahwa Anda membuat salinan semua elemen dari tingkat atas ke tingkat terakhir selain referensi bagian dalam objek akan digunakan dan itu berarti mengubah nilai dalam object_elements di new_array masih akan mempengaruhi old_array. Anda dapat memanggil metode penyalinan ini di setiap level sebagai membuat COPY DALAM dari old_array.
Untuk penyalinan dalam, Anda dapat menggunakan metode yang disebutkan di atas untuk tipe data primitif di setiap tingkat tergantung pada jenis data atau Anda dapat menggunakan metode mahal ini (disebutkan di bawah) untuk membuat salinan dalam tanpa melakukan banyak pekerjaan.
Ada banyak metode lain di luar sana yang dapat Anda gunakan tergantung pada kebutuhan Anda. Saya hanya telah disebutkan beberapa dari mereka untuk memberikan gambaran umum tentang apa yang terjadi ketika kita mencoba untuk menyalin array ke yang lain dengan nilai .
sumber
Jika Anda ingin membuat salinan baru dari suatu objek atau array, Anda harus secara eksplisit menyalin properti objek atau elemen-elemen array, misalnya:
Anda dapat mencari informasi lebih lanjut di Google tentang nilai-nilai primitif yang tidak berubah dan referensi objek yang bisa berubah.
sumber
Menggunakan jQuery deep copy dapat dilakukan sebagai berikut:
sumber
Anda juga dapat menggunakan operator penyebaran ES6 untuk menyalin Array
sumber
Berikut beberapa cara untuk menyalin:
sumber
Anda dapat menggunakan ES6 dengan menyebarkan Opeartor, yang lebih sederhana.
Ada batasan..hapus dokumentasi. Sebarkan sintaks @ mozilla
sumber
Contoh Cepat:
sumber
Berikut variannya:
sumber
toSource
tidak standar dan tidak akan berfungsi di Chrome misalnya.Ada yang baru diperkenalkan
Array.from
, tetapi sayangnya, pada saat penulisan ini hanya didukung pada versi Firefox terbaru (32 dan lebih tinggi). Ini dapat dengan mudah digunakan sebagai berikut:Referensi: Di Sini
Atau
Array.prototype.map
dapat digunakan dengan fungsi identitas:Referensi: Di Sini
sumber
Array.from
, yang sekarang didukung di semua browser utama kecuali Internet Explorer ( sumber ). .Array.from
akan bermutasi data, tidak menyediakan penyalinan dalam / kloning dalam.Untuk array ES6 yang berisi objek
sumber