Symbol, her çağrıda benzersiz bir değer üreten ilkel (primitive) bir tiptir. Symbol("id") === Symbol("id") her zaman false döner. Symbol'ler genellikle başka kodun eklediği anahtarlarla çakışmayacak, for...in, Object.keys ve JSON.stringify tarafından görülmeyen özellik anahtarları oluşturmak için kullanılır. Ayrıca Symbol.iterator ve Symbol.toPrimitive gibi "well-known" symbol'ler, dilin yerleşik davranışlarını kendi nesnelerinize uyarlamanızı sağlar.
Bu yazıda symbol oluşturmayı, symbol anahtarlı özelliklerin nerede göründüğünü ve nerede gizlendiğini, Symbol.for ile global kayıt defterini ve en çok kullanılan well-known symbol'leri çalışan örneklerle görüyorsunuz. Diğer ilkel tiplerle karşılaştırma için veri tipleri yazısına bakabilirsiniz.
Symbol oluşturmak
Symbol() fonksiyonu isteğe bağlı bir açıklama metni alır. Bu açıklama yalnızca hata ayıklama içindir; symbol'e açıklama üzerinden ulaşamazsınız. description özelliği açıklamayı, toString() ise Symbol(...) biçimindeki metni verir. new Symbol() yazmak hata verir.
const a = Symbol("kimlik");
const b = Symbol("kimlik");
console.log(a === b); // false
console.log(typeof a); // symbol
console.log(a.toString(), a.description); // Symbol(kimlik) kimlik
console.log(Symbol().description); // undefined
new Symbol();
// TypeError: Symbol is not a constructor
a + "";
// TypeError: Cannot convert a Symbol value to a string
console.log(String(a)); // Symbol(kimlik)Symbol'ler metne kendiliğinden çevrilmez. Bu, bir symbol'ü yanlışlıkla metin anahtarına dönüştürmenizi engeller. Açıkça metin istiyorsanız String(sym) ya da sym.description kullanın.
Tip dönüşüm kuralları
Symbol, dönüşüm konusunda diğer ilkel tiplerden daha katıdır. MDN'nin listelediği kurallar Node.js 24 ile şöyle görünür:
const sym = Symbol("x");
+sym;
// TypeError: Cannot convert a Symbol value to a number
`${sym}`;
// TypeError: Cannot convert a Symbol value to a string
new String(sym);
// TypeError: Cannot convert a Symbol value to a string
console.log(Object(sym) == sym); // true
console.log(String(sym)); // Symbol(x)Kısacası sayıya çevirme her zaman hata verir; metne çevirme yalnızca String() fonksiyonu ile açıkça yapılabilir. Şablon metin içinde symbol kullanacaksanız description özelliğini yazın. Tip dönüşümünün genel mantığı tip dönüşümü yazısında anlatılıyor.
Symbol anahtarlı özellikler

Bir symbol'ü hesaplanmış özellik adı olarak ([ID]) kullanabilirsiniz. Bu özellik metin anahtarlarını listeleyen mekanizmalarda görünmez; yine de gerçek anlamda gizli değildir, Object.getOwnPropertySymbols veya Reflect.ownKeys ile bulunabilir. MDN bunu zayıf bir kapsülleme olarak tanımlar. Gerçek gizlilik için sınıfların #özel alanlarını kullanın.
const ID = Symbol("id");
const urun = { ad: "Klavye", fiyat: 750, [ID]: 9001 };
console.log(urun[ID]); // 9001
console.log(Object.keys(urun)); // [ 'ad', 'fiyat' ]
for (const k in urun) console.log(k); // ad, fiyat
console.log(JSON.stringify(urun)); // {"ad":"Klavye","fiyat":750}
console.log(Object.getOwnPropertySymbols(urun)); // [ Symbol(id) ]
console.log(Reflect.ownKeys(urun)); // [ 'ad', 'fiyat', Symbol(id) ]
console.log({ ...urun }[ID]); // 9001Bu davranışın pratik bir kullanımı, başkasının oluşturduğu nesneye çakışma riski olmadan işaret koymaktır. Aşağıdaki fonksiyon bir kaydın işlenip işlenmediğini symbol ile işaretler; işaret JSON çıktısına sızmaz ve nesnede aynı adlı bir metin alanı olsa bile onunla karışmaz:
const ISLENDI = Symbol("islendi");
function isle(kayit) {
if (kayit[ISLENDI]) return "zaten işlendi";
kayit[ISLENDI] = true;
return "işlendi";
}
const k = { id: 7 };
console.log(isle(k)); // işlendi
console.log(isle(k)); // zaten işlendi
console.log(JSON.stringify(k)); // {"id":7}| Mekanizma | Symbol anahtarı görünür mü? |
|---|---|
| for...in | Hayır |
| Object.keys / Object.entries | Hayır |
| JSON.stringify | Hayır, tamamen atlanır |
| Object.getOwnPropertySymbols | Evet |
| Reflect.ownKeys | Evet |
| Spread ve Object.assign | Evet, kopyalanır |
Global kayıt defteri: Symbol.for ve Symbol.keyFor
Symbol() her seferinde yeni bir değer üretir. Farklı dosyalar, hatta farklı realm'ler (örneğin iframe) arasında aynı symbol'ü paylaşmak istiyorsanız Symbol.for(anahtar) kullanın: anahtar kayıtlıysa mevcut symbol'ü, değilse yeni oluşturup kaydettiği symbol'ü döndürür. Symbol.keyFor tersini yapar ve kayıtlı olmayan symbol'ler için undefined döner.
const s1 = Symbol.for("uygulama.oturum");
const s2 = Symbol.for("uygulama.oturum");
console.log(s1 === s2); // true
console.log(Symbol.keyFor(s1)); // uygulama.oturum
console.log(Symbol.keyFor(Symbol("yerel"))); // undefined
console.log(Symbol.keyFor(Symbol.iterator)); // undefined
Symbol.keyFor("metin");
// TypeError: metin is not a symbolKayıt defteri adları global olduğu için başka kütüphanelerle çakışmamak adına "uygulama.oturum" gibi ön ekli, açıklayıcı anahtarlar seçmek iyi bir alışkanlıktır. Kayıt defterinin içeriğini listelemenin bir yolu yoktur; ona yalnızca for() ve keyFor() üzerinden erişilir.
Well-known symbol'ler

Symbol kurucusunun statik özellikleri, dilin yerleşik işlemlerinin baktığı "protokol" anahtarlarıdır. Bir nesneye bu anahtarlarla metot eklediğinizde ilgili dil özelliği sizin metodunuzu kullanır. Bunlar global kayıt defterinde değildir, bu yüzden Symbol.keyFor(Symbol.iterator) undefined döner.
| Symbol | Kullanan dil özelliği |
|---|---|
| Symbol.iterator | for...of, spread, dizi destructuring |
| Symbol.asyncIterator | for await...of |
| Symbol.toPrimitive | Nesneyi ilkel değere çevirme (+obj, şablon metin, ==) |
| Symbol.toStringTag | Object.prototype.toString çıktısı |
| Symbol.hasInstance | instanceof |
| Symbol.dispose / Symbol.asyncDispose | using / await using bildirimleri |
| Symbol.isConcatSpreadable | Array.prototype.concat |
Symbol.iterator: nesneyi döngüye uygun hale getirmek
for...of bir nesneyi dolaşmadan önce onun [Symbol.iterator]() metodunu çağırır. Düz nesnelerde bu metot olmadığı için döngü hata verir. Generator metodu ile bu protokolü birkaç satırda uygulayabilirsiniz; ayrıntı generator ve iterator yazısında.
class Aralik {
constructor(bas, son, adim = 1) {
this.bas = bas;
this.son = son;
this.adim = adim;
}
*[Symbol.iterator]() {
for (let i = this.bas; i <= this.son; i += this.adim) yield i;
}
}
console.log([...new Aralik(1, 10, 3)]); // [ 1, 4, 7, 10 ]
const [ilk, ikinci] = new Aralik(5, 9);
console.log(ilk, ikinci); // 5 6
for (const x of { a: 1 }) {}
// TypeError: {(intermediate value)} is not iterableSymbol.toPrimitive: dönüşümü kontrol etmek
Bir nesne sayıya, metne ya da ilkel değere çevrilirken motor önce [Symbol.toPrimitive](hint) metodunu arar. hint değeri "number", "string" ya da "default" olur. Metot ilkel bir değer döndürmek zorundadır; nesne döndürürse TypeError fırlatılır. Bu metot yoksa valueOf() ve toString() kullanılır.
class Para {
constructor(kurus) { this.kurus = kurus; }
[Symbol.toPrimitive](ipucu) {
if (ipucu === "string") return `${(this.kurus / 100).toFixed(2)} TL`;
return this.kurus / 100; // "number" ve "default"
}
}
const p = new Para(1250);
console.log(+p); // 12.5
console.log(`${p}`); // 12.50 TL
console.log(p + 1); // 13.5
console.log(p > 10); // trueSymbol.toStringTag ve Symbol.hasInstance
class Dogrulayici {
get [Symbol.toStringTag]() { return "Dogrulayici"; }
}
console.log(Object.prototype.toString.call(new Dogrulayici())); // [object Dogrulayici]
console.log(Object.prototype.toString.call(new Map())); // [object Map]
class Cift {
static [Symbol.hasInstance](n) { return Number.isInteger(n) && n % 2 === 0; }
}
console.log(4 instanceof Cift, 3 instanceof Cift); // true falseSymbol.hasInstance ile instanceof davranışını değiştirmek mümkündür, ama okuyan kişiyi şaşırtabilir; gerçek kodda bir doğrulama fonksiyonu genellikle daha anlaşılırdır.
Sık yapılan hatalar
- Symbol anahtarlı veriyi
JSON.stringifyile kaydetmeye çalışmak: bu özellikler sessizce atlanır. - Symbol'ü gizlilik mekanizması sanmak:
Reflect.ownKeysile görülebilir; gerçek gizlilik için#alanları kullanın. - Modüller arasında paylaşılması gereken bir anahtar için
Symbol()kullanmak: her modül farklı bir değer üretir; ortak anahtar gerekiyorsa symbol'ü dışa aktarın ya daSymbol.forkullanın. - Symbol'ü
+ile metne eklemek:TypeErrorverir;descriptionkullanın.
Sık Sorulan Sorular
Symbol ne zaman kullanılmalı?
Başkasının nesnesine çakışma riski olmadan meta veri eklemek, kütüphaneler arasında ortak bir protokol tanımlamak ve for...of gibi dil özelliklerini kendi nesnelerinize uyarlamak için uygundur. Günlük veri modelleri için metin anahtarlar yeterlidir.
Symbol.for ile Symbol() arasındaki fark nedir?
Symbol() her çağrıda yeni ve benzersiz bir değer üretir. Symbol.for("x") aynı anahtar için her yerde aynı değeri döndürür, ama bu yüzden toplanamaz ve zayıf koleksiyonlarda kullanılamaz.
Symbol bir WeakMap anahtarı olabilir mi?
Symbol("x") ile oluşturulan kayıtsız symbol'ler toplanabildiği için olabilir. Symbol.for ile oluşturulan kayıtlı symbol'ler ise reddedilir; Node.js 24 bu durumda TypeError: Invalid value used as weak map key verir.
Symbol anahtarlı özellikler kopyalanır mı?
Evet. Spread sözdizimi ve Object.assign kendi, numaralandırılabilir symbol özelliklerini de kopyalar. Yalnızca JSON.stringify, for...in ve Object.keys bunları atlar.
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 · Generator ve iterator · Veri tipleri · Tip dönüşümü · Proxy ve Reflect