Jika saya membuat objek seperti ini:
var obj = {};
obj.prop1 = "Foo";
obj.prop2 = "Bar";
Apakah objek yang dihasilkan akan selalu terlihat seperti ini?
{ prop1 : "Foo", prop2 : "Bar" }
Yaitu, akankah properti berada dalam urutan yang sama dengan yang saya tambahkan?
javascript
object
mellowsoon
sumber
sumber
for-in
,Object.keys
) tidak perlu mendukungnya (resmi), tapi ada yang pesan sekarang. (Secara tidak resmi: Firefox, Chrome, dan Edge semua mengikuti urutan yang ditentukan bahkan untuk masuk dan Object.keys, di mana mereka tidak secara resmi diharuskan untuk: jsfiddle.net/arhbn3k2/1 )Jawaban:
Urutan iterasi untuk objek mengikuti serangkaian aturan tertentu sejak ES2015, tetapi tidak (selalu) mengikuti urutan penyisipan . Sederhananya, urutan iterasi adalah kombinasi dari urutan penyisipan untuk kunci string, dan urutan naik untuk kunci seperti angka:
Menggunakan array atau
Map
objek bisa menjadi cara yang lebih baik untuk mencapai ini.Map
berbagi beberapa kesamaan denganObject
dan menjamin kunci untuk diulang sesuai urutan pemasangan , tanpa kecuali:Sebagai catatan, urutan properti pada objek tidak dijamin sama sekali sebelum ES2015. Definisi Objek dari ECMAScript Edisi Ketiga (pdf) :
sumber
YA (untuk kunci non-integer).
Sebagian besar Peramban mengulangi properti objek sebagai:
Beberapa browser lama menggabungkan kategori # 1 dan # 2, iterasi semua kunci dalam urutan penyisipan. Jika kunci Anda mungkin diuraikan sebagai bilangan bulat, yang terbaik adalah tidak bergantung pada urutan iterasi tertentu.
Urutan penyisipan Spec Bahasa Saat Ini (sejak ES2015) dipertahankan, kecuali dalam kasus kunci yang diuraikan sebagai bilangan bulat (misalnya "7" atau "99"), di mana perilaku bervariasi di antara browser. Sebagai contoh, Chrome / V8 tidak menghormati urutan penyisipan ketika kunci diuraikan sebagai angka.
Spesifikasi Bahasa Lama (sebelum ES2015) : Urutan Iterasi secara teknis tidak terdefinisi, tetapi semua browser utama mematuhi perilaku ES2015.
Perhatikan bahwa perilaku ES2015 adalah contoh yang baik dari spesifikasi bahasa yang didorong oleh perilaku yang ada, dan bukan sebaliknya. Untuk memahami lebih mendalam tentang pola pikir kompatibilitas-belakang itu, lihat http://code.google.com/p/v8/issues/detail?id=164 , bug Chrome yang mencakup secara detail keputusan desain di balik perilaku urutan iterasi Chrome. . Per salah satu (agak berpendapat) komentar pada laporan bug itu:
sumber
createFragment
API sudah bergantung pada ini ... 🤔Urutan properti di Objek normal adalah subjek kompleks dalam Javascript.
Sementara di ES5 secara eksplisit tidak ada pesanan yang ditentukan, ES2015 memiliki pesanan dalam kasus tertentu. Diberikan adalah objek berikut:
Ini menghasilkan urutan berikut (dalam kasus tertentu):
Jadi, ada tiga segmen, yang dapat mengubah urutan penyisipan (seperti yang terjadi dalam contoh). Dan kunci integer seperti tidak menempel pada urutan penyisipan sama sekali.
Pertanyaannya adalah, untuk metode apa pesanan ini dijamin dalam spesifikasi ES2015?
Metode berikut menjamin urutan yang ditunjukkan:
Metode / loop berikut tidak menjamin pesanan sama sekali:
Kesimpulan: Bahkan dalam ES2015 Anda tidak harus bergantung pada urutan properti objek normal di Javascript. Itu rentan terhadap kesalahan. Gunakan
Map
sebagai gantinya.sumber
Pada saat penulisan, sebagian besar browser memang mengembalikan properti dalam urutan yang sama seperti yang dimasukkan, tetapi itu secara eksplisit tidak menjamin perilaku sehingga tidak seharusnya diandalkan.
The ECMAScript spesifikasi yang digunakan untuk mengatakan:
Namun dalam ES2015 dan kemudian kunci non-integer akan dikembalikan dalam urutan penyisipan.
sumber
Seluruh jawaban ini adalah dalam konteks kepatuhan spesifikasi, bukan apa yang dilakukan mesin pada saat tertentu atau secara historis.
Secara umum, tidak
Pertanyaan yang sebenarnya sangat kabur.
Dalam konteks apa?
Jawabannya adalah: itu tergantung pada sejumlah faktor. Secara umum, tidak .
Terkadang ya
Di sinilah Anda dapat mengandalkan pesanan kunci properti untuk polos
Objects
:Object.getOwnPropertyNames()
,Reflect.ownKeys()
,Object.getOwnPropertySymbols(O)
Dalam semua kasus, metode ini mencakup kunci properti yang tidak dapat dihitung dan kunci pesanan seperti yang ditentukan oleh
[[OwnPropertyKeys]]
(lihat di bawah). Mereka berbeda dalam jenis nilai kunci yang mereka sertakan (String
dan / atauSymbol
). Dalam konteks iniString
termasuk nilai integer.Object.getOwnPropertyNames(O)
Mengembalikan properti yang dikunci
O
sendiriString
( nama properti ).Reflect.ownKeys(O)
Mengembalikan properti
O
milik sendiriString
dan yangSymbol
dikunci.Object.getOwnPropertySymbols(O)
Mengembalikan properti milik
O
sendiri yangSymbol
dikunci.[[OwnPropertyKeys]]
Urutannya pada dasarnya: seperti integer
Strings
dalam urutan menaik, tidak seperti integerStrings
dalam urutan pembuatan, Simbol dalam urutan penciptaan. Bergantung pada fungsi mana yang memanggil ini, beberapa tipe ini mungkin tidak termasuk.Bahasa spesifiknya adalah bahwa kunci dikembalikan dalam urutan berikut:
Map
Jika Anda tertarik pada peta yang dipesan, Anda harus mempertimbangkan untuk menggunakan
Map
jenis yang diperkenalkan di ES2015 alih-alih polosObjects
.sumber
Di browser modern, Anda dapat menggunakan
Map
struktur data alih-alih objek.Pengembang mozilla> Peta
sumber
Dalam ES2015, itu terjadi, tetapi tidak untuk apa yang mungkin Anda pikirkan
Urutan kunci dalam suatu objek tidak dijamin hingga ES2015. Itu didefinisikan implementasi.
Namun, dalam ES2015 di telah ditentukan. Seperti banyak hal dalam JavaScript, ini dilakukan untuk tujuan kompatibilitas dan umumnya mencerminkan standar tidak resmi yang ada di antara sebagian besar mesin JS (dengan Anda-tahu-siapa yang menjadi pengecualian).
Urutan didefinisikan dalam spesifikasi, di bawah operasi abstrak OrdinaryOwnPropertyKeys , yang menopang semua metode pengulangan pada kunci objek sendiri. Diparafrasekan, urutannya adalah sebagai berikut:
Semua indeks integer kunci (hal-hal seperti
"1123"
,"55"
, dll) di urutan menaik numerik.Semua kunci string yang bukan indeks bilangan bulat, sesuai urutan pembuatan (terlama-pertama).
Semua kunci simbol, sesuai urutan pembuatan (terlama-pertama).
Adalah konyol untuk mengatakan bahwa pesanan itu tidak dapat diandalkan - itu dapat diandalkan, itu hanya mungkin bukan yang Anda inginkan, dan browser modern menerapkan pesanan ini dengan benar.
Beberapa pengecualian termasuk metode penghitungan kunci yang diwarisi, seperti
for .. in
loop. Thefor .. in
Loop tidak menjamin agar sesuai dengan spesifikasi.sumber
Pada ES2015, pesanan properti dijamin untuk metode tertentu yang beralih ke properti. tapi tidak yang lain . Sayangnya, metode yang tidak dijamin memiliki pesanan umumnya yang paling sering digunakan:
Object.keys
,Object.values
,Object.entries
for..in
loopJSON.stringify
Tetapi, pada ES2020, pesanan properti untuk metode - metode yang sebelumnya tidak dapat dipercaya ini akan dijamin oleh spesifikasi untuk diulangi dengan cara deterministik yang sama seperti yang lain, karena proposal yang sudah selesai : for-in mechanical .
Sama seperti dengan metode yang memiliki urutan iterasi dijamin (seperti
Reflect.ownKeys
danObject.getOwnPropertyNames
), metode yang sebelumnya tidak ditentukan juga akan beralih dalam urutan berikut:Inilah yang hampir setiap implementasi sudah (dan telah dilakukan selama bertahun-tahun), tetapi proposal baru telah membuatnya resmi.
Meskipun spesifikasi saat ini menyisakan ... dalam urutan iterasi " hampir sama sekali tidak ditentukan , mesin nyata cenderung lebih konsisten:"
Karena setiap implementasi sudah berulang properti lebih dapat diprediksi, dapat dimasukkan ke dalam spesifikasi tanpa melanggar kompatibilitas ke belakang.
Ada beberapa kasus aneh yang implementasi saat ini tidak setuju, dan dalam kasus seperti itu, pesanan yang dihasilkan akan terus tidak ditentukan. Untuk pemesanan properti dijamin :
sumber
Seperti yang telah dinyatakan orang lain, Anda tidak memiliki jaminan tentang urutan ketika Anda beralih ke properti suatu objek. Jika Anda memerlukan daftar beberapa bidang yang dipesan, saya sarankan untuk membuat array objek.
Dengan cara ini Anda dapat menggunakan loop reguler untuk dan memiliki urutan insert. Anda kemudian dapat menggunakan metode semacam Array untuk mengurutkan ini ke dalam array baru jika diperlukan.
sumber
Hanya menemukan ini dengan cara yang sulit.
Menggunakan Bereaksi dengan Redux, wadah negara kunci mana yang ingin saya lintasi untuk menghasilkan anak-anak disegarkan setiap kali toko diubah (sesuai konsep kekekalan Redux).
Jadi, untuk mengambil
Object.keys(valueFromStore)
saya menggunakanObject.keys(valueFromStore).sort()
, sehingga saya setidaknya sekarang memiliki urutan abjad untuk kunci.sumber
Dari standar JSON :
(penekanan milikku).
Jadi, tidak, Anda tidak dapat menjamin pesanan.
sumber