Tanım olarak objeler, karakter dizisi veya sembol tipinde olmalıdır. Sayı veya boolean olamaz.
Şimdiye kadar sadece karakter dizisi işlendi. Bundan sonra semboller nasıl kullanılır ve ne gibi artısı var bunların üzerinden geçilecektir.
“Symbol” değeri eşsizdir.
Symbol() yazılara yeni bir değer yaratılabilir.
// id yeni bir semboldür let id = Symbol();
Ayrıca sembollere tanım açıklama ( sembol ismi ) verilebilir. Bu genelde hata ayıklarken kullanılır:
// id açıklaması "id" olan bir semboldür. let id = Symbol("id");
Sembollerin eşsiz oldukları garantidir. Eğer aynı açıklamaya ( sembol ismi ) ait iki sembol olsa bile değerleri farklıdır. Bu açıklama sadece etikettir. Hiç birşeyi etkilemez.
Örneğin aşağıdaki iki sembol aynı açıklamalara aittir – eşit değillerdir:
Eğer Ruby veya diğer diller ile çalışıyorsanız “symbols” farklı özelliklere sahip olabilir. JavaScript sembolleri tamamen farklıdır.
Çoğu değer karakter dizisine çevrilmeyi destekler. Örneğin,
alert neredeyse tüm değerler için çalışır. Symbol ise farklıdır. Doğrudan karakter disizine çevrilemez.
Örneğin,
Aşağıdaki
alert hata verecektir.
Eğer sembol’ün değerini göstermek istiyorsanız bu durumda
.toString() metodunu çağırmanız gerekir:
Sembol ve karakter dizisi birbirinden mantıken farklı olduklarından dolayı bu şekilde birbirlerine çevrilirken sorun olmasın diye kontrollü bir şekilde çevrilmesi istenmektedir.
Semboller objelere “gizli” özellikler eklenmesinin yolunu açar, bunlar vasıtasıyla kodun başka bir bölgesindeki değişiklik var olan objenin üzerine yazamaz.
Örneğin,
kullanici objesi için “id” özelliği şu şekilde tanımlanabilir:
Peki
Symbol("id")'nin karakter dizisi
"id"'ye olan üstünlüğü nedir?
Bunu anlamak için örneği biraz daha genişletmek gerekirse;
Başka bir kodun
kullanici içerisinde
id özelliği eklemek istediğini farzedin. Bu belki başka bir JavaScript kütüphanesi olabilir. Doğal olarak sizin yaptığınız değişiklikten hiç haberi yoktur.
O kod parçası kendi
id'sini
Symbol("id") şeklinde yaratabilir:
// ... let id = Symbol("id"); kullanici[id] = "Id değeri";
Artık birbiri ile hiç bir ayrılık olmayacaktır, hatta aynı isme sahip olsalar bile.
Şimdi bu
"id"'nin karakter dizisi olduğunu varsayın, eğer başkası aynı isim ile
id objeye veri eklemeye çalışırsa bu durumda ayrılık olacaktır.
Eğer obje tanımlanırken sembol doğrudan yazılmak istenirse, köşeli parantez gerekmektedir.
Aşağıdaki Gibi:
let id = Symbol("id"); let kullanici = { isim: "Mahsun", [id]: 123 // dikkat ederseniz id:123 değil };
Böyle yazılmasının nedeni,
id değişkeninin ismi değil değerinin istenmesidir, bu değer karakter dizisi değildir.
Obje içindeki semboller obje döngüsü içinde pas geçilir.
Örneğin:
Bu da “gizleme” konseptine dahildir. Diğer bir kütüphane veya kod parçası yanlışlıkla bizim gizlediğimiz bir özelliğin üzerine yazmasın diye.
Buna karşın Object.assign hem karakter değerlerini hem de sembolleri kopyalar:
Burada problem yoktur. Dizaynında. Amaç yeni bir obje yaratıp istenilen objenin tüm alanlarının bu yeni objeye kopyalanmasından ibarettir. Buna elbette
id alanı da dahildir.
Obje içinde anahtarlar sadece karakter dizisi veya sembol olabilirler. Diğer tipler doğrudan karakter dizisine çevrililer.
Örneğin
0 değeri obje içerisinde anahtar olarak
"0" karakter olan sıfıra dönüşmektedir.
Görüldüğü üzere semboller her zaman, isimleri aynı olsa bile, birbirinden farklıdır. Bazen durumlarda aynı isimdeki sembolün aynı anlama gelmesi istenebilir.
Örneğin, uygulamnın bir yerinde
"id" isminde bir sembol oluşturdunuz, başka bir yerinde ise aynı bu objeye erişmek istiyorsunuz.
Bunu yapabilmek için global sembol kaydı kullanılabilir. Sembolleri bunun içinde yaratılabilir ve sonra kullanılabilir. Bu aynı isme sahip sembollerin aynı değeri döndereceğini garantiler.
Bu kayıt bölümünden sembolleri okumak için
Symbol.for(anahtar) kullanılır.
Bu global kayıt bölümünü kontrol eder. Eğer bir sembol
anahtarolarak tanımalnmışsa bunu döndürür. Eğer böyle bir anahtar yok ise
Symbol(anahtar) metodu çalışır ve bu yeni anahtar global sembol kaydı bölümüne kaydedilir.
Örneğin:
Kayıt bölümündeki Sembollere global semboller denir. Eğer uygulamanın tamamında sembol kullanmak isterseniz bu bölüme kayıt edilmelidir.
Bazı programlama dillerinde , Ruby gibi, her bir isim için bir sembol bulunmaktadır. JavaScript’te ise gördüğünüz gibi bu global semboller için geçerlidir.
Global semboller için
Symbol.for(anahtar) sembolü ismiyle çağırır, bunun tam tersi de mümkündür:
Symbol.keyFor(sym), global sembol ile sembolün ismini dönderir.
Örneğin:
Symbol.keyFor sembol kayıt bölümünde bulunan sembolleri aramak için kullanılır. Bu da global olmayanlarda arama yapılamaz demektir. Eğer sembol global olarak tanımlanamaz ise
undefined döndürür.
Örneğin:
JavaScript içinde tanımlı bir çok “sistem” sembolü bulunmaktadır. Bunları farklı yönlerden objeler içinde kullanmak mümkündür.
Bu semboller Bilinen semboller tablosundan kontrol edilebilir:
Symbol.hasInstance
Symbol.isConcatSpreadable
Symbol.iterator
Symbol.toPrimitive
- …vs.
Örneğin
Symbol.toPrimitive ilkel tiplere çevirirken objelerin nasıl davranması gerektiğini tanımlar. Bunlara yakında değinilecektir.
Diğer sembollere de kullanıldığı yerlerde değinildiğinde siz de kullanımına alışacaksınız.
Symbol benzersiz tanımlayıcıdır.
Symbol() çağırılarak yaratılır. Bunun yanında isteğe bağlı olarak tanım argümanı kullanılabilir.
Semboller her zaman farklı değerler alır. Aynı ismi kullansanız bile farklı değerler alır. Eğer aynı değerlerin alınması isteniyorsa,
Symbol.for(key)'e kayıt edilmelidir. Eğer daha önce yaratılmamış ise burada tanım argümanı ile kaydedilir. Global kayıt için
Symbol.for her zaman aynı değeri dönderir.
Sembollerin iki kullanım yeri vardır:
-
“Gizli” obje özellikleri
Eğer objeye yeni bir özellik eklenmek istenirse ve bu özellik başka kütüphaneler veya kodlar tarafından daha önce tanımlanmış ise, yeni bir sembol oluşturup bunu anahtar olarak kullanabilirsiniz. Sembol özelliği
for..iniçerisinde görünmez. Doğrudan da erişilemez, çünkü başka bir kod sizin yazdığınız sembole ulaşamaz. Bundan dolayı sizin istediğiniz aksiyonu değiştiremez
Öyleyse obje içine “gizlice” özellik eklenebilir ve başkasının da bu özelliği görmesi engellenmiş olur. Sembol özellikler ile bu amaca erişilebilir.
-
JavaScript birçok sistem sembolüne sahiptir. Bunlara
Symbol.*altından erişilebilir. Varolan davranışlar üzerinde değişiklik yapmak için kullanılır. Örneğin iterables içinde
Symbol.iteratorkullanılmıştır, veya objeden ilkel tiplere çevrilirken
Symbol.toPrimitivekullanılabilir. object-to-primitive conversion
Teknik olarak semboller %100 gizli değillerdir. Object.getOwnPropertySymbols(obj) ile tüm semboller alınabilir. Ayrıca tüm sembolik anahtarları çevirmek için Reflect.ownKeys(obj) fonksiyonu kullanılabilir. Gördüğünüz gibi aslında tam da gizli sayılmaz. Fakat yine de çoğu kütüphane bunları ortak bir anlaşma varmışçasına kullanmaktadır.