Perbedaan utama adalah bahwa Objek hanya mendukung kunci string dan Simbol sedangkan Peta mendukung kurang lebih jenis kunci apa pun
Jika saya melakukan obj[123] = true dan kemudian Object.keys(obj) maka saya akan mendapatkan Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 0 daripada Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 1. Peta akan mempertahankan jenis kunci dan mengembalikan Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 1 yang bagus. Peta juga memungkinkan Anda menggunakan Objek sebagai kunci. Secara tradisional untuk melakukan ini, Anda harus memberikan objek semacam pengidentifikasi unik untuk mencirikannya (saya rasa saya belum pernah melihat yang seperti Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 3 dalam JavaScript sebagai bagian dari standar). Peta juga menjamin pelestarian ketertiban sehingga semuanya lebih baik untuk pelestarian dan terkadang dapat menyelamatkan Anda karena perlu melakukan beberapa hal
Antara peta dan objek dalam praktiknya ada beberapa pro dan kontra. Objek mendapatkan keuntungan dan kerugian yang terintegrasi dengan sangat erat ke dalam inti JavaScript yang membedakannya dari secara signifikan Memetakan melampaui perbedaan dalam dukungan utama
Keuntungan langsungnya adalah Anda memiliki dukungan sintaksis untuk Objek sehingga mudah untuk mengakses elemen. Anda juga memiliki dukungan langsung untuk itu dengan JSON. Saat digunakan sebagai hash, sangat menjengkelkan untuk mendapatkan objek tanpa properti sama sekali. Secara default jika Anda ingin menggunakan Objek sebagai tabel hash mereka akan tercemar dan Anda akan sering harus memanggil Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 4 pada mereka saat mengakses properti. Anda dapat melihat di sini bagaimana secara default Objek tercemar dan cara membuat objek yang mudah-mudahan tidak tercemar untuk digunakan sebagai hash
({}).toString toString() { [native code] } JSON.parse('{}').toString toString() { [native code] } (Object.create(null)).toString undefined JSON.parse('{}', (k,v) => (typeof v === 'object' && Object.setPrototypeOf(v, null) ,v)).toString undefinedPolusi pada objek bukan hanya sesuatu yang membuat kode lebih mengganggu, lebih lambat, dll. , tetapi juga dapat memiliki konsekuensi potensial untuk keamanan
Objek bukanlah tabel hash murni, tetapi mereka berusaha melakukan lebih banyak. Anda mengalami sakit kepala seperti Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 4, tidak bisa mendapatkan panjang dengan mudah (Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size(); 6) dan seterusnya. Objek tidak dimaksudkan untuk murni digunakan sebagai peta hash, tetapi juga sebagai Objek dinamis yang dapat diperluas dan ketika Anda menggunakannya sebagai tabel hash murni, masalah muncul
Perbandingan/Daftar berbagai operasi umum
Object: var o = {}; var o = Object.create(null); o.key = 1; o.key += 10; for(let k in o) o[k]++; var sum = 0; for(let v of Object.values(m)) sum += v; if('key' in o); if(o.hasOwnProperty('key')); delete(o.key); Object.keys(o).length Map: var m = new Map(); m.set('key', 1); m.set('key', m.get('key') + 10); m.foreach((k, v) => m.set(k, m.get(k) + 1)); for(let k of m.keys()) m.set(k, m.get(k) + 1); var sum = 0; for(let v of m.values()) sum += v; if(m.has('key')); m.delete('key'); m.size();Ada beberapa opsi, pendekatan, metodologi, dll. dengan berbagai pasang surut (kinerja, singkat, portabel, dapat diperpanjang, dll. ). Objek agak aneh menjadi inti bahasa sehingga Anda memiliki banyak metode statis untuk bekerja dengannya
Selain keuntungan dari Peta mempertahankan jenis kunci serta mampu mendukung hal-hal seperti objek sebagai kunci, mereka diisolasi dari efek samping yang dimiliki banyak objek. Peta adalah hash murni, tidak ada kebingungan untuk mencoba menjadi objek pada saat yang bersamaan. Peta juga dapat dengan mudah diperluas dengan fungsi proxy. Objek saat ini memiliki kelas Proxy namun kinerja dan penggunaan memori suram, sebenarnya membuat proxy Anda sendiri yang terlihat seperti Map for Objects saat ini berkinerja lebih baik daripada Proxy
Kerugian substansial untuk Maps adalah bahwa mereka tidak didukung dengan JSON secara langsung. Parsing dimungkinkan, tetapi memiliki beberapa hangup
JSON.parse(str, (k,v) => { if(typeof v !== 'object') return v; let m = new Map(); for(k in v) m.set(k, v[k]); return m; }); _Di atas akan memperkenalkan hit kinerja yang serius dan juga tidak akan mendukung kunci string apa pun. Pengkodean JSON bahkan lebih sulit dan bermasalah (ini adalah salah satu dari banyak pendekatan)
// An alternative to this it to use a replacer in JSON.stringify. Map.prototype.toJSON = function() { return JSON.stringify({ keys: Array.from(this.keys()), values: Array.from(this.values()) }); };Ini tidak terlalu buruk jika Anda murni menggunakan Maps, tetapi akan bermasalah saat Anda mencampur jenis atau menggunakan nilai non-skalar sebagai kunci (bukan berarti JSON sempurna dengan masalah seperti itu, IE referensi objek melingkar . Saya belum mengujinya, tetapi kemungkinan besar itu akan sangat merusak kinerja dibandingkan dengan merangkai
Bahasa skrip lain seringkali tidak memiliki masalah seperti itu karena mereka memiliki tipe non-skalar yang eksplisit untuk Map, Object, dan Array. Pengembangan web seringkali menyusahkan dengan tipe non-skalar di mana Anda harus berurusan dengan hal-hal seperti PHP menggabungkan Array/Peta dengan Objek menggunakan A/M untuk properti dan JavaScript menggabungkan Peta/Objek dengan Array memperluas M/O. Menggabungkan tipe kompleks adalah kutukan setan dari bahasa scripting tingkat tinggi
Sejauh ini sebagian besar masalah seputar implementasi, tetapi kinerja untuk operasi dasar juga penting. Performanya juga kompleks karena tergantung mesin dan pemakaian. Ikuti tes saya dengan sebutir garam karena saya tidak dapat mengesampingkan kesalahan apa pun (saya harus terburu-buru). Anda juga harus menjalankan tes Anda sendiri untuk mengonfirmasi karena saya hanya memeriksa skenario sederhana yang sangat spesifik untuk memberikan indikasi kasar saja. Menurut pengujian di Chrome untuk objek/peta yang sangat besar, kinerja objek lebih buruk karena penghapusan yang tampaknya sebanding dengan jumlah kunci daripada O(1)
Object Set Took: 146 Object Update Took: 7 Object Get Took: 4 Object Delete Took: 8239 Map Set Took: 80 Map Update Took: 51 Map Get Took: 40 Map Delete Took: 2Chrome jelas memiliki keunggulan yang kuat dalam mendapatkan dan memperbarui, tetapi kinerja penghapusannya sangat buruk. Peta menggunakan sedikit lebih banyak memori dalam kasus ini (overhead), tetapi dengan hanya satu Objek/Peta yang diuji dengan jutaan kunci, dampak overhead untuk peta tidak diekspresikan dengan baik. Dengan manajemen memori, objek juga tampaknya bebas lebih awal jika saya membaca profil dengan benar yang mungkin merupakan salah satu keuntungan dari objek
Di Firefox untuk tolok ukur khusus ini, ini adalah cerita yang berbeda
Object Set Took: 435 Object Update Took: 126 Object Get Took: 50 Object Delete Took: 2 Map Set Took: 63 Map Update Took: 59 Map Get Took: 33 Map Delete Took: 1Saya harus segera menunjukkan bahwa di tolok ukur khusus ini menghapus dari objek di Firefox tidak menyebabkan masalah, namun di tolok ukur lain hal itu menyebabkan masalah terutama ketika ada banyak kunci seperti di Chrome. Peta jelas lebih unggul di Firefox untuk koleksi besar
Namun ini bukanlah akhir dari cerita, bagaimana dengan banyak benda kecil atau peta? . Tes ini lebih lanjut tentang memori dan inisialisasi
Sekali lagi angka-angka ini bervariasi, tetapi pada dasarnya Object memimpin dengan baik. Dalam beberapa kasus keunggulan Objek di atas peta sangat ekstrem (~10 kali lebih baik), tetapi rata-rata sekitar 2-3 kali lebih baik. Tampaknya lonjakan kinerja yang ekstrem dapat bekerja dua arah. Saya hanya menguji ini di Chrome dan pembuatan profil penggunaan memori dan overhead. Saya cukup terkejut melihat bahwa di Chrome tampaknya Peta dengan satu kunci menggunakan memori sekitar 30 kali lebih banyak daripada Objek dengan satu kunci
Untuk menguji banyak objek kecil dengan semua operasi di atas (4 tombol)
Chrome Object Took: 61 Chrome Map Took: 67 Firefox Object Took: 54 Firefox Map Took: 139Dalam hal alokasi memori, ini berlaku sama dalam hal pembebasan/GC, tetapi Map menggunakan memori lima kali lebih banyak. Tes ini menggunakan empat kunci dimana pada tes terakhir saya hanya menetapkan satu kunci jadi ini akan menjelaskan pengurangan overhead memori. Saya menjalankan pengujian ini beberapa kali dan Map/Object kurang lebih sama secara keseluruhan untuk Chrome dalam hal kecepatan keseluruhan. Di Firefox untuk Objek kecil ada keunggulan kinerja yang pasti dibandingkan peta secara keseluruhan
Ini tentu saja tidak termasuk opsi individual yang bisa sangat bervariasi. Saya tidak akan menyarankan pengoptimalan mikro dengan angka-angka ini. Apa yang bisa Anda dapatkan dari ini adalah sebagai aturan umum, pertimbangkan Maps lebih kuat untuk penyimpanan nilai kunci yang sangat besar dan objek untuk penyimpanan nilai kunci kecil
Di luar itu, strategi terbaik dengan keduanya adalah mengimplementasikannya dan membuatnya berfungsi terlebih dahulu. Saat membuat profil, penting untuk diingat bahwa terkadang hal-hal yang menurut Anda tidak akan lambat saat melihatnya bisa menjadi sangat lambat karena keanehan mesin seperti yang terlihat pada kasus penghapusan kunci objek