Artinya, jika saya menggunakan waktu saat ini sebagai indeks ke dalam array:
array[Date.getTime()] = value;
akankah penerjemah memberi contoh semua elemen dari 0 hingga sekarang? Apakah browser yang berbeda melakukannya secara berbeda?
Saya ingat dulu ada bug di kernel AIX , yang akan membuat pseudo-ttys berdasarkan permintaan, tetapi jika Anda melakukannya, katakan, "echo> / dev / pty10000000000" itu akan membuat / dev / pty0, / dev / pty1, .... dan kemudian jatuh mati. Itu menyenangkan di pameran dagang, tetapi saya tidak ingin ini terjadi pada pelanggan saya.
javascript
sparse-matrix
Berry
sumber
sumber
Jawaban:
Bagaimana sebenarnya larik JavaScript diimplementasikan berbeda dari satu peramban ke peramban lainnya, tetapi umumnya kembali ke penerapan renggang - kemungkinan besar sama yang digunakan untuk akses properti objek biasa - jika menggunakan larik sebenarnya tidak efisien.
Anda harus meminta seseorang yang memiliki lebih banyak pengetahuan tentang implementasi spesifik untuk menjawab apa yang memicu pergeseran dari padat ke jarang, tetapi contoh Anda harus benar-benar aman. Jika Anda ingin mendapatkan larik padat, Anda harus memanggil konstruktor dengan argumen panjang eksplisit dan berharap Anda benar-benar mendapatkannya.
Lihat jawaban ini untuk penjelasan lebih rinci oleh olliej.
sumber
foo = new Array(10000)
. Namun, ini seharusnya pekerjaan:foo = Array.apply(null, {length: 10});
.Ya begitulah. Mereka sebenarnya adalah tabel hash secara internal, sehingga Anda tidak hanya dapat menggunakan bilangan bulat besar tetapi juga string, float, atau objek lainnya. Semua kunci diubah menjadi string melalui
toString()
sebelum ditambahkan ke hash. Anda dapat mengonfirmasi ini dengan beberapa kode tes:Menampilkan:
Perhatikan bagaimana saya menggunakan
for...in
sintaks, yang hanya memberi Anda indeks yang sebenarnya didefinisikan. Jika Anda menggunakanfor (var i = 0; i < array.length; ++i)
gaya iterasi yang lebih umum maka Anda jelas akan memiliki masalah dengan indeks array non-standar.sumber
length
properti ajaiblength
hanya tidak terlihat dalamfor..in
loop karenaDontEnum
flag memiliki set; di ES5, atribut properti dipanggilenumerable
dan dapat diatur secara eksplisit melaluiObject.defineProperty()
String
; apa pun yang Anda masukkan ke dalam subskrip mendapattoString()
-ed. Gabungkan ini dengan ketidaktepatan integer dari Angka besar dan itu berarti jika Anda mengatura[9999999999999999]=1
,a[10000000000000000]
akan menjadi 1 (dan banyak lagi perilaku yang mengejutkan). Menggunakan non-integer sebagai kunci sangat tidak bijaksana, dan objek arbitrer benar.Anda dapat menghindari masalah ini dengan menggunakan sintaks javascript yang dirancang untuk hal semacam ini. Anda dapat memperlakukannya sebagai kamus, namun sintaks "untuk ... dalam ..." akan memungkinkan Anda mengambil semuanya.
sumber
Objek JavaScript jarang, dan array hanyalah objek khusus dengan properti panjang yang dipertahankan otomatis (yang sebenarnya lebih besar dari indeks terbesar, bukan jumlah elemen yang ditentukan) dan beberapa metode tambahan. Anda aman dengan cara apa pun; menggunakan array jika Anda membutuhkan fitur tambahannya, dan sebaliknya menggunakan objek.
sumber
Jawabannya, seperti yang biasanya terjadi pada JavaScript, adalah "ini sedikit lebih aneh ...."
Penggunaan memori tidak ditentukan dan implementasi apa pun boleh dianggap bodoh. Secara teori,
const a = []; a[1000000]=0;
bisa membakar megabyte memori, seperti bisaconst a = [];
. Dalam praktiknya, bahkan Microsoft menghindari penerapan tersebut.Justin Love menunjukkan, atribut panjang adalah kumpulan indeks tertinggi . TAPI hanya diperbarui jika indeksnya adalah bilangan bulat.
Jadi, arraynya jarang. TAPI fungsi bawaan seperti reduce (), Math.max (), dan "for ... of" akan berjalan melalui seluruh rentang kemungkinan indeks integer dari 0 ke panjang, mengunjungi banyak yang mengembalikan 'tidak ditentukan'. TAPI 'untuk ... dalam' loop mungkin melakukan seperti yang Anda harapkan, hanya mengunjungi kunci yang ditentukan.
Berikut ini contoh menggunakan Node.js:
memberi:
Tapi. Ada lebih banyak kasus sudut dengan Array belum disebutkan.
sumber
Ketersebaran (atau kepadatan) dapat dikonfirmasi secara empiris untuk NodeJS dengan proses non-standar . MemoriUsage () .
Terkadang node cukup pintar untuk menjaga array tetap jarang:
Terkadang node memilih untuk membuatnya padat (perilaku ini mungkin dioptimalkan di masa mendatang):
Lalu jauhkan lagi:
Jadi mungkin menggunakan larik padat untuk merasakan bug kernel AIX asli mungkin perlu dipaksa dengan rentang yang mirip :
Karena kenapa tidak membuatnya jatuh?
sumber
Mereka bisa jadi tapi tidak selalu harus begitu, dan mereka bisa berkinerja lebih baik padahal tidak.
Berikut adalah pembahasan tentang cara menguji ketersebaran indeks dalam instance array: https://benmccormick.org/2018/06/19/code-golf-sparse-arrays/
Pemenang kode golf (karakter paling sedikit) ini adalah:
Pada dasarnya menjalankan array untuk entri yang diindeks sambil mengurangi nilai panjang dan mengembalikan
!!
boolean yang diperkeras dari hasil numerik falsy / truthy (jika akumulator diturunkan hingga nol, indeks terisi penuh dan tidak tersebar). Peringatan Charles Merriam di atas harus dipertimbangkan juga dan kode ini tidak membahasnya, tetapi berlaku untuk entri string berciri yang dapat terjadi saat menugaskan elemen denganarr[var]= (something)
var yang bukan merupakan integer.Alasan untuk peduli tentang ketersebaran indeks adalah pengaruhnya terhadap kinerja, yang dapat berbeda di antara mesin skrip, ada diskusi hebat tentang pembuatan larik / .inisialisasi di sini: Apa perbedaan antara "Array ()" dan "[]" saat mendeklarasikan JavaScript Himpunan?
Jawaban baru-baru ini untuk postingan tersebut memiliki link ke penjelasan mendalam tentang cara V8 mencoba mengoptimalkan array dengan menandai mereka untuk menghindari pengujian (ulang) untuk karakteristik seperti ketersebaran: https://v8.dev/blog/elements-kinds . Entri blog tersebut dari September '17 dan materinya dapat berubah, tetapi uraian implikasi untuk pengembangan sehari-hari berguna dan jelas.
sumber