Object polos menampung data berupa pasangan kunci dan nilai, tetapi object bukan alat yang tepat untuk semua koleksi. Topik ini memperkenalkan Map yang menerima kunci bertipe apa pun, Set yang menyimpan nilai unik, dan symbol sebagai tipe kunci yang selalu unik. Ketiganya menggantikan trik yang sebelumnya dipakai untuk mengakali keterbatasan object, seperti mengubah object menjadi string agar bisa dijadikan kunci.
Map ketika kunci bukan hanya string#
Map menyimpan pasangan kunci dan nilai dengan kunci yang boleh bertipe apa pun, sedangkan object selalu mengubah kuncinya menjadi string atau symbol. Isi Map diatur lewat metode, yaitu set untuk menambahkan, get untuk membaca, has untuk menguji keberadaan, dan delete untuk menghapus, sementara jumlah pasangannya terbaca langsung dari properti size.
const stok = new Map();
stok.set("pensil", 40);
stok.set("buku", 25);
stok.set("pensil", 38); // kunci sama, nilainya diganti
console.log(stok.size);
console.log(stok.get("pensil"));
const rakA = { kode: "A" };
const rakB = { kode: "B" };
stok.set(rakA, 12);
stok.set(rakB, 7);
console.log(stok.get(rakA));
console.log(stok.size);
const objekBiasa = {};
objekBiasa[rakA] = 12;
objekBiasa[rakB] = 7;
console.log(Object.keys(objekBiasa).length);
console.log(Object.keys(objekBiasa)[0]);2
38
12
4
1
[object Object]Setengah pertama keluaran menunjukkan perilaku yang wajar. Kunci pensil yang ditambahkan dua kali lewat set tidak menduplikasi pasangan, melainkan mengganti nilainya, dan size ikut bertambah setelah dua object rak menjadi kunci. Setengah kedua memperlihatkan perbedaannya dengan object. Dua object berbeda yang dipakai sebagai kunci object biasa menyatu menjadi satu karena keduanya diubah menjadi string "[object Object]", sedangkan Map menyimpannya sebagai dua kunci terpisah berdasarkan identitas referensinya. Perulangan for...of atas Map menghasilkan pasangan kunci dan nilai dalam urutan penambahannya, dan urutan ini dijamin oleh spesifikasi, bukan sekadar kebetulan implementasi.
Kapan Map lebih tepat daripada object#
Pilihan antara Map dan object mengikuti bentuk datanya, bukan selera. Perbandingan berikut merangkum aspek yang membedakan keduanya.
| Aspek | Map | Object |
|---|---|---|
| Tipe kunci | apa pun, termasuk object | string dan symbol |
| Jumlah pasangan | properti size | hitung Object.keys manual |
| Urutan | urutan penambahan | umumnya urutan penambahan, dengan pengecualian kunci yang menyerupai indeks |
| Konversi JSON | bukan data JSON, stringify menghasilkan {} | asli sebagai data JSON |
| Cocok untuk | koleksi yang sering bertambah dan berkurang | data terstruktur yang bentuknya tetap |
Dua kriteria praktis paling sering menentukan pilihan. Pertama, kunci yang lahir saat program berjalan, misalnya object pembeli sebagai kunci keranjangnya atau hitungan frekuensi per kata, cocok untuk Map karena kuncinya dinamis. Kedua, data yang dikirim dan diterima sebagai JSON tetap memakai object, karena Map tidak punya bentuk JSON dan harus dikonversi dulu menjadi array atau object sebelum dikirim. Pemisahan ini juga menjelaskan mengapa keduanya tetap dipakai berdampingan pada program yang sama, yaitu object untuk menyusun data dan Map untuk mengindeksnya saat berjalan.
Set untuk keanggotaan dan dedup#
Set menyimpan nilai-nilai yang unik, dan penambahan nilai yang sama untuk kedua kalinya diabaikan. Sifat ini menjadikan Set alat yang ringkas untuk dua pekerjaan, yaitu menguji keanggotaan lewat has dan menghilangkan duplikat array lewat konversi ke Set lalu spread kembali.
const angka = [7, 7, 12, 7, 12, 30];
const unik = new Set(angka);
console.log(unik);
console.log([...unik]);
console.log(unik.has(12));
unik.add(30);
console.log(unik.size);Set(3) { 7, 12, 30 }
[ 7, 12, 30 ]
true
3Baris pertama memperlihatkan enam angka yang hanya menyisakan tiga anggota, dan baris kedua mengembalikannya menjadi array tanpa duplikat lewat spread. Pada baris keempat, add(30) tidak mengubah apa pun karena 30 sudah menjadi anggota, sehingga size tetap 3. Pengujian has bekerja cepat untuk koleksi besar karena Set mengindeks anggotanya, berbeda dari includes pada array yang memeriksa satu per satu dari awal.
symbol sebagai kunci yang unik#
symbol adalah tipe primitif yang nilainya selalu unik, sehingga dua symbol dengan deskripsi yang sama tetap berbeda. Deskripsi pada Symbol("id") hanya penanda untuk manusia yang membaca kode, sedangkan identitasnya ditetapkan saat pembuatan dan tidak bisa ditiru oleh symbol lain. Untuk kebutuhan berbagi, Symbol.for("nama") mencari symbol pada registry global dan membuatnya bila belum ada. Dua berkas yang memanggil Symbol.for dengan nama yang sama menerima symbol yang sama, dan Symbol.keyFor membaca nama itu kembali.
const id = Symbol("id");
const idLain = Symbol("id");
console.log(id === idLain);
console.log(typeof id);
const pencatat = Symbol.for("pencatat");
const pencatatJuga = Symbol.for("pencatat");
console.log(pencatat === pencatatJuga);
console.log(Symbol.keyFor(pencatat));
const data = { nama: "Citra", [id]: 42 };
console.log(JSON.stringify(data));
console.log(Object.keys(data));
console.log(data[id]);false
symbol
true
pencatat
{"nama":"Citra"}
[ 'nama' ]
42Tiga baris terakhir adalah inti pemakaiannya. Symbol id yang menjadi kunci object tidak terlihat oleh JSON.stringify maupun Object.keys, sehingga data yang dikirim keluar tidak membawanya. Kode di dalam berkas yang sama tetap bisa membacanya lewat akses kurung siku. Kunci seperti ini cocok untuk properti internal yang tidak boleh bentrok dengan properti dari sumber luar, misalnya metadata yang ditempelkan pada data milik pustaka lain. Sifatnya perlu diingat, yakni symbol bukan penyimpanan privat sejati karena Object.getOwnPropertySymbols tetap mendaftar kunci-kunci tersebut bagi siapa pun yang mencarinya.
Ringkasan#
Mapmenerima kunci bertipe apa pun, menghitung isinya lewatsize, dan menjaga urutan penambahan, sedangkan object memaksakan kunci string dan symbol.Mapuntuk kunci dinamis dan koleksi yang sering berubah, object untuk data terstruktur yang dikirim sebagai JSON.Setmenyimpan anggota unik, menguji keanggotaan lewathas, dan menghilangkan duplikat array lewatnew Set(array)lalu spread kembali.symbolselalu unik,Symbol.forberbagi lewat registri global, dan kunci symbol tersembunyi dariObject.keysmaupunJSON.stringifytanpa menjadi penyimpanan privat sejati.
Referensi#
- Map — MDN Web Docs — Metode Map, properti size, dan perbandingannya dengan object.
- Set — MDN Web Docs — Keanggotaan nilai unik beserta metode add, has, dan delete.
- Symbol — MDN Web Docs — Tipe symbol, Symbol.for, dan sifat kuncinya pada object.
- ECMA-262, 7.3 SameValueZero — TC39 — Aturan kesamaan nilai yang dipakai Map dan Set, termasuk kasus NaN.