Untuk menduplikasi array dalam JavaScript: manakah dari yang berikut ini yang lebih cepat digunakan?
Metode irisan
var dup_array = original_array.slice();
For
lingkaran
for(var i = 0, len = original_array.length; i < len; ++i)
dup_array[i] = original_array[i];
Saya tahu kedua cara hanya melakukan salinan dangkal : jika original_array berisi referensi ke objek, objek tidak akan dikloning, tetapi hanya referensi yang akan disalin, dan oleh karena itu kedua array akan memiliki referensi ke objek yang sama. Tapi ini bukan inti dari pertanyaan ini.
Saya hanya bertanya tentang kecepatan.
javascript
arrays
duplicates
copy
slice
Marco Demaio
sumber
sumber
Jawaban:
Setidaknya ada 5 (!) Cara untuk mengkloning array:
Telah ada utas BENCHMARKS , menyediakan informasi berikut:
untuk blink browser
slice()
adalah metode tercepat,concat()
sedikit lebih lambat, danwhile loop
2.4x lebih lambat.untuk browser lain
while loop
adalah metode tercepat, karena browser tersebut tidak memiliki optimasi internal untukslice
danconcat
.Ini tetap berlaku di Jul 2016.
Di bawah ini adalah skrip sederhana yang dapat Anda salin-tempel ke konsol browser Anda dan jalankan beberapa kali untuk melihat gambar. Mereka menghasilkan milidetik, lebih rendah lebih baik.
sementara lingkaran
mengiris
Harap dicatat bahwa metode ini akan mengkloning objek Array itu sendiri, namun isi array disalin dengan referensi dan tidak dikloning dalam.
sumber
splice
dan Anda akan terkejut (sementara ...)A.map(function(e){return e;});
Secara teknis
slice
adalah cara tercepat. Namun , bahkan lebih cepat jika Anda menambahkan0
indeks mulai.lebih cepat dari
http://jsperf.com/cloning-arrays/3
sumber
myArray.slice(0,myArray.length-1);
lebih cepat dari itumyArray.slice(0);
?bagaimana dengan es6 way?
sumber
[].concat(_slice.call(arguments))
arguments
datangnya ... Saya pikir output babel Anda menggabungkan beberapa fitur yang berbeda. Itu lebih mungkin terjadiarr2 = [].concat(arr1)
.arr2 = [].conact(arr1)
berbeda dariarr2 = [...arr1]
.[...arr1]
sintaks akan mengonversi lubang menjadiundefined
. Sebagai contoharr1 = Array(1); arr2 = [...arr1]; arr3 = [].concat(arr1); 0 in arr2 !== 0 in arr3
,.n = 1000*1000; start = + new Date(); a = Array(n); b = [...a]; console.log(new Date() - start); // 168
[{a: 'a', b: {c: 'c'}}]
. Jikac
nilai diubah dalam array "duplikat", itu akan berubah dalam array asli, karena itu hanya salinan referensial, bukan klon.Cara termudah untuk mengkloning dalam Array atau Objek:
sumber
undefined
atau apa punfunction
. Keduanya akan dikonversinull
untuk Anda selamaJSON.stringify
proses berlangsung. Strategi lain, seperti(['cool','array']).slice()
tidak akan mengubahnya tetapi juga tidak menduplikasi objek dalam array. Jadi ada tradeoff.n = 1000*1000; start = + new Date(); a = Array(n); var b = JSON.parse(JSON.stringify(a)) console.log(new Date() - start); // 221
sumber
Saya mengumpulkan demo cepat: http://jsbin.com/agugo3/edit
Hasil saya di Internet Explorer 8 adalah 156, 782, dan 750, yang akan menunjukkan
slice
jauh lebih cepat dalam hal ini.sumber
a.map(e => e)
adalah alternatif lain untuk pekerjaan ini. Sampai hari.map()
ini sangat cepat (hampir secepat.slice(0)
) di Firefox, tetapi tidak di Chrome.Di sisi lain, jika array multi-dimensi, karena array adalah objek dan objek referensi jenis, tidak ada potongan atau concat metode akan menyembuhkan ... Jadi salah satu cara yang tepat kloning array adalah penemuan
Array.prototype.clone()
sebagai mengikuti.sumber
🏁 Cara Tercepat untuk Mengkloning Array
Saya membuat fungsi utilitas yang sangat sederhana ini untuk menguji waktu yang diperlukan untuk mengkloning array. Ini tidak 100% dapat diandalkan namun dapat memberi Anda ide massal tentang berapa lama yang dibutuhkan untuk mengkloning array yang ada:
Dan menguji pendekatan yang berbeda:
UPDATE :
Catatan: dari semuanya, satu-satunya cara untuk mengkloning array adalah dengan menggunakan
JSON.parse(JSON.stringify(arr))
.Yang mengatakan, jangan gunakan di atas jika array Anda mungkin menyertakan fungsi karena akan kembali
null
.Terima kasih @GilEpshtain untuk pembaruan ini .
sumber
arr => arr.slice()
tercepat.JSON.parse(JSON.stringify([function(){}]))
akan menampilkan[null]
[...arr]
dengan4.653076171875ms
di Chrome dan8.565ms
di Safari. Cepat kedua di Chrome adalah fungsi irisanarr.slice()
dengan6.162109375ms
dan di Safari kedua adalah[].concat(arr)
dengan13.018ms
.Lihatlah: Link . Ini bukan tentang kecepatan, tetapi kenyamanan. Selain seperti yang Anda lihat, Anda hanya dapat menggunakan slice (0) pada tipe primitif .
Untuk membuat salinan array yang independen daripada salinan referensi ke dalamnya, Anda bisa menggunakan metode slice array.
Contoh:
Sumber: tautan
sumber
for
lingkaran dalam pertanyaan juga.Seperti @Dan berkata "Jawaban ini menjadi usang dengan cepat. Gunakan tolok ukur untuk memeriksa situasi aktual", ada satu jawaban spesifik dari jsperf yang belum memiliki jawaban untuk dirinya sendiri: sementara :
memiliki 960.589 ops / detik dengan runnerup
a.concat()
di 578.129 ops / detik, yaitu 60%.Ini adalah Firefox terbaru (40) 64 bit.
@aleclarson membuat patokan baru yang lebih andal.
sumber
Cara ECMAScript 2015 dengan
Spread
operator:Contoh dasar:
Coba di konsol browser:
Referensi
sumber
Itu tergantung pada browser. Jika Anda melihat di posting blog Array.prototype.slice vs pembuatan array manual , ada panduan kasar untuk kinerja masing-masing:
Hasil:
sumber
arguments
bukan array yang tepat dan dia gunakancall
untuk memaksaslice
berjalan di koleksi. hasilnya mungkin menyesatkan.Ada solusi yang jauh lebih bersih:
Diperlukan pemeriksaan panjang, karena
Array
konstruktor berperilaku berbeda ketika dipanggil dengan tepat satu argumen.sumber
splice()
, mungkin. Tapi sungguh, terapkan dan ini semua kecuali intuitif.Array.of
dan mengabaikan panjangnya:Array.of.apply(Array, array)
Ingat .slice () tidak akan berfungsi untuk array dua dimensi. Anda akan membutuhkan fungsi seperti ini:
sumber
Itu tergantung pada panjang array. Jika panjang array <= 1.000.000, metode
slice
danconcat
mengambil sekitar waktu yang sama. Tetapi ketika Anda memberikan rentang yang lebih luas,concat
metode ini menang.Misalnya, coba kode ini:
Jika Anda menetapkan panjang original_array ke 1.000.000,
slice
metode danconcat
metode mengambil sekitar waktu yang sama (3-4 ms, tergantung pada angka acak).Jika Anda menetapkan panjang original_array ke 10.000.000, maka
slice
metode ini membutuhkan lebih dari 60 ms danconcat
metode ini membutuhkan lebih dari 20 ms.sumber
dup.push
salaha5
, alihdup[i] =
- alih harus digunakanSolusi sederhana:
sumber
Jadi, untuk menghindari skenario ini terjadi, gunakan
sumber
cloneNums[0][0]
dalam contoh Anda menyebarkan perubahan kenums[0][0]
- tetapi itu karenanums[0][0]
secara efektif objek yang referensi disalin kecloneNums
oleh operator spread. Singkatnya, perilaku ini tidak akan memengaruhi kode tempat kami menyalin menurut nilai (int, string, dll. Literal).Waktu benchmark!
Hasil saya:
Chrome (mesin V8):
Firefox (Mesin SpiderMonkey):
sumber
Cara cepat untuk menduplikasi array dalam JavaScript dalam Urutan:
#1: array1copy = [...array1];
#2: array1copy = array1.slice(0);
#3: array1copy = array1.slice();
Jika objek array Anda mengandung beberapa konten JSON-non-serializable (fungsi, Number.POSITIVE_INFINITY, dll.) Lebih baik untuk digunakan
array1copy = JSON.parse(JSON.stringify(array1))
sumber
Anda dapat mengikuti kode ini. Klon array cara yang tidak berubah. Ini adalah cara sempurna untuk mengatur kloning
sumber
Di ES6, Anda cukup menggunakan sintaks Penyebaran .
Contoh:
Harap perhatikan bahwa operator spread menghasilkan array yang sama sekali baru, jadi memodifikasi yang satu tidak akan memengaruhi yang lain.
Contoh:
sumber