Map, anahtarı herhangi bir değer olabilen ve ekleme sırasını koruyan bir anahtar-değer koleksiyonudur. Set her değeri yalnızca bir kez tutan bir değer koleksiyonudur. WeakMap ve WeakSet bunların "zayıf" sürümleridir: anahtar olarak yalnızca nesne (ve kayıtsız Symbol) kabul eder, bu anahtarları çöp toplayıcıdan (garbage collector) korumaz ve içerikleri gezilemez.
Kısa cevap: anahtarlar baştan bilinen sabit alanlarsa (bir kullanıcının adı, e-postası gibi) düz nesne; anahtarlar çalışma anında ekleniyor, siliniyor, metin dışı türde oluyor ya da kullanıcıdan geliyorsa Map kullanın. Tekrarsız liste için Set, bir nesneye onun ömrüne bağlı ek veri iliştirmek için WeakMap doğru araçtır. Bu yazıda dördünü örneklerle karşılaştırıyoruz. Genel yol haritası JavaScript öğrenme rehberinde.
Map temelleri

Bir Map'e set(anahtar, değer) ile ekler, get() ile okur, has() ile varlığını sorar, delete() ile silersiniz. Eleman sayısı size özelliğindedir. set() Map'in kendisini döndürdüğü için çağrılar zincirlenebilir.
const stok = new Map();
stok.set("kalem", 120).set("defter", 40);
console.log(stok.get("kalem")); // 120
console.log(stok.has("silgi")); // false
console.log(stok.get("silgi")); // undefined
console.log(stok.size); // 2
stok.delete("defter");
console.log(stok); // Map(1) { 'kalem' => 120 }
// Ekleme sırasıyla gezilir; her adım [anahtar, değer] çiftidir
const fiyat = new Map([["elma", 40], ["muz", 65]]);
for (const [urun, tl] of fiyat) {
console.log(urun, tl);
}
// elma 40
// muz 65Map yalnızca anahtarları ya da yalnızca değerleri gezmek için keys() ve values(), çiftler için entries() metotlarını sunar. Bunlar dizi değil iterator döndürür; dizi gerekiyorsa spread ile açın. forEach() de vardır, ancak callback fonksiyonun argüman sırası (değer, anahtar) biçimindedir; ters yazmak yaygın bir hatadır.
const m2 = new Map([["x", 1], ["y", 2]]);
console.log([...m2.keys()], [...m2.values()]); // [ 'x', 'y' ] [ 1, 2 ]
m2.forEach((deger, anahtar) => console.log(anahtar, deger));
// x 1
// y 2Çıktıdaki => işareti Node.js'in Map'i yazdırma biçimidir, bir arrow function değildir. Döngüdeki [urun, tl] yazımı için destructuring yazısına bakabilirsiniz.
Map anahtarı olarak nesne ve NaN
Düz nesnede anahtarlar metne (ya da Symbol'e) çevrilir. Map ise anahtarın türünü korur: sayı, nesne, fonksiyon her şey anahtar olabilir. Anahtar karşılaştırması MDN'nin "SameValueZero" dediği kurala göre yapılır; pratikte === gibidir ama NaN kendine eşit sayılır. Nesne anahtarları referansa göre karşılaştırılır, içeriğe göre değil.
const m = new Map();
const kullanici = { id: 1 };
m.set(kullanici, "oturum-a");
m.set(1, "sayı bir");
m.set("1", "metin bir");
m.set(NaN, "sayı değil");
console.log(m.get(kullanici)); // oturum-a
console.log(m.get({ id: 1 })); // undefined (farklı nesne)
console.log(m.get(1), "/", m.get("1")); // sayı bir / metin bir
console.log(m.get(NaN)); // sayı değil
const nesne = {};
nesne[1] = "a";
nesne["1"] = "b";
console.log(nesne); // { '1': 'b' }Map mi düz nesne mi?

MDN, Map ile düz nesneyi birkaç başlıkta karşılaştırır. Özet:
| Konu | Map | Düz nesne |
|---|---|---|
| Anahtar türü | her değer (nesne, fonksiyon, sayı...) | yalnızca string ve Symbol |
| Varsayılan anahtarlar | yok, sadece eklediğiniz | prototipten gelenlerle çakışabilir |
| Kullanıcı girdisi anahtar | güvenli | prototype pollution riski (null prototip ile azaltılır) |
| Sıra | ekleme sırası | kuralları karmaşık, güvenmeyin |
| Eleman sayısı | size özelliği | Object.keys(obj).length |
| Gezinme | doğrudan for...of | Object.entries ile |
| Sık ekleme/silme | bu senaryoda daha iyi performans | bu senaryo için optimize değil |
| JSON desteği | yerleşik yok | JSON.stringify ve JSON.parse ile doğrudan |
İkisi arasında dönüşüm kolaydır: new Map(Object.entries(obj)) nesneden Map, Object.fromEntries(map) Map'ten nesne üretir (bkz. Object metotları). Map doğrudan JSON'a yazılamaz; JSON.stringify(new Map([["a", 1]])) sonucu "{}" olur. Çözüm yolları JSON.parse ve JSON.stringify yazısında.
Set: tekrarsız değerler
Set'e add() ile değer eklersiniz; aynı değer ikinci kez eklenmez. Değer kontrolü Map'teki anahtar kuralıyla aynıdır. MDN, has() metodunun ortalamada, aynı uzunluktaki bir dizide includes() çağırmaktan daha hızlı olduğunu belirtir. Dizideki tekrarları silmenin en kısa yolu da Set'tir:
const etiketler = ["js", "node", "js", "react", "node"];
const tekil = [...new Set(etiketler)];
console.log(tekil); // [ 'js', 'node', 'react' ]
const goruldu = new Set();
goruldu.add(5).add(5).add("5");
console.log(goruldu.size); // 2
console.log(goruldu.has(5)); // true
// Metindeki farklı harfler
console.log(new Set("merhaba").size); // 6Set kompozisyon metotları: union, intersection ve diğerleri
Set'e matematikteki küme işlemlerini yapan yeni metotlar eklendi. union(), intersection(), difference() ve symmetricDifference() yeni bir Set döndürür; isSubsetOf(), isSupersetOf() ve isDisjointFrom() ise true/false döndürür. Bu metotlar görece yenidir; örnekler Node.js 24 ile çalıştı, hedef ortamlarınız için MDN uyumluluk tablosuna bakın.
const frontend = new Set(["js", "css", "html"]);
const backend = new Set(["js", "sql", "linux"]);
console.log(frontend.union(backend)); // Set(5) { 'js', 'css', 'html', 'sql', 'linux' }
console.log(frontend.intersection(backend)); // Set(1) { 'js' }
console.log(frontend.difference(backend)); // Set(2) { 'css', 'html' }
console.log(frontend.symmetricDifference(backend)); // Set(4) { 'css', 'html', 'sql', 'linux' }
console.log(new Set(["js"]).isSubsetOf(frontend)); // true
console.log(frontend.isDisjointFrom(new Set(["go"]))); // trueArgümanın gerçek bir Set olması gerekmez; MDN'nin "set-like" dediği, size özelliği ile has() ve keys() metotları olan her nesne kabul edilir. Map bu koşulu sağladığı için anahtarlarıyla birlikte kullanılabilir. Diziler ise has() ve size içermediğinden doğrudan verilemez; önce new Set(dizi) ile çevirin.
WeakMap: nesneye ömrü kadar veri iliştirmek
WeakMap'in anahtarları nesne ya da kayıtsız (registered olmayan) Symbol olmalıdır. Bir nesnenin WeakMap'te anahtar olması onu çöp toplamadan korumaz; nesneye başka hiçbir yerden ulaşılamıyorsa nesne ve ona bağlı değer toplanabilir. Bu yüzden WeakMap'in size özelliği, keys() veya forEach() gibi gezinme metotları yoktur; MDN bunu, liste vermenin çöp toplamanın anlık durumuna bağımlı, öngörülemez bir sonuç üreteceğiyle açıklar. Yalnızca set, get, has ve delete vardır.
const hesapOnbellegi = new WeakMap();
function ozet(nesne) {
if (hesapOnbellegi.has(nesne)) return hesapOnbellegi.get(nesne);
const sonuc = Object.values(nesne).reduce((a, b) => a + b, 0);
hesapOnbellegi.set(nesne, sonuc);
return sonuc;
}
const sepet = { kitap: 120, kalem: 15 };
console.log(ozet(sepet)); // 135
console.log(hesapOnbellegi.has(sepet)); // true
try {
hesapOnbellegi.set("metin", 1);
} catch (e) {
console.log(e.name); // TypeError
}Bu kalıp, fonksiyona verilen nesneyle sonucunu ilişkilendirip aynı nesne tekrar geldiğinde hesaplamayı atlamak için kullanılır. MDN'nin uyarısı: anahtar nesne yaşadığı sürece sonuç da bellekte kalır. Çöp toplamanın ayrıntıları için bellek yönetimi yazısına, sınıflarda özel alan yerine WeakMap kullanımı ve # alanları için class yazısına bakabilirsiniz.
WeakSet: nesneleri işaretlemek
WeakSet de yalnızca nesne ve kayıtsız Symbol tutar, gezilemez ve size özelliği yoktur. Tipik kullanımı "bu nesneyi daha önce gördüm mü?" sorusudur; örneğin iç içe bir yapıyı gezerken döngüsel referansa takılmamak:
function derinlikSay(nesne, gorulen = new WeakSet()) {
if (typeof nesne !== "object" || nesne === null) return 0;
if (gorulen.has(nesne)) return 0; // döngü
gorulen.add(nesne);
let enDerin = 0;
for (const deger of Object.values(nesne)) {
enDerin = Math.max(enDerin, derinlikSay(deger, gorulen));
}
return enDerin + 1;
}
const a = { b: { c: {} } };
a.b.c.geri = a; // döngüsel referans
console.log(derinlikSay(a)); // 3Dört koleksiyonun özeti
| Yapı | Ne tutar | Anahtar/değer türü | Gezilebilir mi | size |
|---|---|---|---|---|
| Map | anahtar-değer | her tür | evet, ekleme sırasıyla | var |
| Set | tekil değer | her tür | evet, ekleme sırasıyla | var |
| WeakMap | anahtar-değer | anahtar: nesne veya kayıtsız Symbol | hayır | yok |
| WeakSet | tekil değer | nesne veya kayıtsız Symbol | hayır | yok |
Sık yapılan hatalar

- Nesne anahtarı içeriğe göre aramak:
m.get({ id: 1 })her zaman yeni bir nesne oluşturur ve eşleşmez. Anahtarın aynı referansını saklayın ya da metin bir kimlik (id) kullanın. - Map'e köşeli parantezle yazmak: Veri Map'e değil nesneye eklenir;
set()kullanın. - WeakMap'i listelemeye çalışmak: İçeriği gezmeniz gerekiyorsa Map kullanın.
- Set'te nesneleri tekilleştirmeyi beklemek: İçeriği aynı iki ayrı nesne, farklı referans oldukları için Set'te iki ayrı öğedir.
Sık Sorulan Sorular
Object.groupBy yerine Map.groupBy ne zaman kullanılır?
Object.groupBy() grup anahtarlarını metne çevirir. Gruplar bir nesneyle temsil ediliyorsa ve o nesneyi anahtar olarak kullanmak istiyorsanız Map.groupBy() bir Map döndürür. MDN, anahtar sabit bir değerse metin kullanıp Object.groupBy() tercih edilebileceğini belirtir.
Map'te "yoksa ekle" işlemi için kısa bir yol var mı?
Klasik yol if (!m.has(k)) m.set(k, v) biçimidir. MDN'de Map.prototype.getOrInsert() ve getOrInsertComputed() metotları da belgelenmiştir; ancak bu metotlar çok yenidir ve bu yazıyı denediğimiz Node.js 24.4 sürümünde tanımlı değildi. Kullanmadan önce MDN uyumluluk tablosuna bakın.
Set elemanlarına indeksle erişebilir miyim?
Hayır, Set'in indeksi yoktur. Sıralı erişim gerekiyorsa [...set] ile diziye çevirip dizi metotlarını kullanın.
Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.
İlgili içerikler: JavaScript öğrenme rehberi · Object metotları · Bellek yönetimi ve garbage collection · Symbol nedir · JSON.parse ve JSON.stringify