instanceof operatörü bir objenin belirli bir sınıfa ait olup olmadığını kontrol eder. Kalıtımı da hesaba kadar.
Böyle bir kontrole birçok durumda ihtiyacımız olabilir. Aşağıda polymorphic fonksiyon inşa etmek için, argümanların tipine göre farklı davranış sergileyen bir yapı yer almaktadır.
instanceof operatorü
Yazımı şu şekildedir:
obj instanceof Class
Eğer obj’e Class’a aitse true döner. ( Veya Class’tan türüyorsa)
Örneğin:
Bu yapıcı fonksiyonlar için de çalışır:
…Array gibi gömülü sınıflar için de
Dikkat edin arr ayrıca Object sınıfına da aittir. Çünkü Array prototipi Object’ten kalıtım alır.
instanceof operatörü prototip zincirini kontrol eder. Symbol.hasInstance statik metodu ile daha performanslı yapılabilir.
obj instanceof Class algoritması kabaca aşağıdaki gibi çalışır:
-
Eğer
Symbol.hasInstancestatik metodu var ise onu kullan. Şu şekilde: -
Çoğu sınıf
Symbol.hasInstance’a sahip değildir. Bu durumda eğerClass.prototypeobj’nin bir prototipine zincirde olup olmadığını kontrol eder.Diğer bir deyişle:
obj.__proto__ == Class.prototype obj.__proto__.__proto__ == Class.prototype obj.__proto__.__proto__.__proto__ == Class.prototype ...Yukarıdaki örnekte
Rabbit.prototype == rabbit.__proto__, cevabı doğrudan verir.Kalıtım yönünden ise
rabbitüst sınıfın da instanceof’u dur.
Aşağıda rabbit instanceof Animal’ın Animal.prototypea karşılaştırılması gösterilmiştir.
Ayrıca objA.isPrototypeOf(objB) metodu ile eğer objA objB’nin prototip zincirinin herhangi bir yerindeyse true döner. obj instanceof Class şu şekilde de yazılabilir Class.prototype.isPrototypeOf(obj)
Class yapıcısının kendisi bu kontrolde yer almaz, garip değil mi? Sadece Class.prototype ve prototiplerin zinciri önemlidir.
Bu prototip değiştiğinde farklı sonuçlara yol açabilir.
Aşağıdaki gibi:
Prototip’i değiştirmemeniz ve daha güvenli tutmanız için bir diğer neden daha olmuş oldu.
Bonus: Tip için Object toString
Bildiğiniz gibi basit objeler karakter dizisine [object Object] şeklinde çevrilir.
Bu toString’i bu şekilde tanımlamalarından dolayıdır. Fakat görünenden daha güçlü bir toString yazmak için gizli özellikler bulunmaktadır. Bunu typeof’un daha genişi ve instanceof’un alternatifi olarak görmek mümkün.
Garip geliyor değilmi. Bakalım neymiş
Şartname, incelendiğinde gömülü gelen toString metodunun objeden çıkarılabileceği ve başka bir değerin kaynağında çalıştırabileceği görülmektedir. Sonucu da bu değere göre gelir.
- Sayı için
[object Number] - Boolean değerler için
[object Boolean] nulliçin:[object Null]undefinediçin:[object Undefined]- Diziler için:
[object Array] - …vs (düzenlenebilir).
Bir örnekle gösterelim:
Burada call’i kullandık ve Dekoratörler ve iletilme, call/apply bölümünde objectToString fonksiyonunun nasıl this=arr kaynağında kullanılacağı gösterilmişti.
Dahili olarak toString algoritması this’i kontrol eder ve buna denk gelen sonucu döner. Örneğin:
Symbol.toStringTag
Objenin toString metodu özel bir özellikle Symbol.toStringTag düzenlenebilir.
Örneğin:
Çoğu çevre-özel objelerde böyle özellikler bulunur. Aşağıda tarayıcı tabanlılar yer almaktadır:
Gördüğünüz gibi, sonuç kesinlikle Symbol.toStringTag’dır ve varsa [object ...] içerisinde saklanır.
Sonunda daha güçlü bir typeof’a sahip olduk. Artık sadece ilkel datalar için değil, gömülü gelen objeler için bile çalışabilir durumdadır.
Gömülü gelen objeler için tipi karakter dizi olarak almak istediğimizde instanceof yerine bunu kullanabiliriz. Instanceof sadece kontrol işlemi yapmaktaydı.
Özet
Bildiğimiz tip kontrol metodlarının üzerinden geçecek olursak:
| çalışır | döner | |
|---|---|---|
typeof |
ilkellerde | string |
{}.toString |
ilkellerde, gömülü ve Symbol.toStringTag’li objelerde |
string |
instanceof |
objelerde | true/false |
Gördüğünüz gibi {}.toString teknik olarak “en gelişmiş” typeof’tur denebilir.
instanceof operatörü sınıf hiyerarşilerileri ve bu hiyerarşiyi göz önüne alacak sınıf için bulunmaz bir kaynaktır.