Bu bölümde prototipler ile çalışmak için ek metodlardan bahsedeceğiz
Bizim bildiğimizin haricinde prototipi ayarlamak ve almak için başka yöntemler de bulunmaktadır:
- Object.create(proto[, descriptors]) – verilen
proto’yu[[Prototype]]şeklinde alarak ve opsiyonel tanımlayıcı özelliği kullanarak boş bir obje oluşturur. - Object.getPrototypeOf(obj) –
obj’nin[[Prototype]]'ını döndürür. - Object.setPrototypeOf(obj, proto) –
obj’nin[[Prototype]]'ınıproto’ya ayarlar.
Örneğin:
let animal = {
eats: true
};
// animal prototipi ile yeni bir rabbit objesi yaratma.
let rabbit = Object.create(animal);
alert(rabbit.eats); // true
alert(Object.getPrototypeOf(rabbit) === animal); // rabbit'in prototipini alma
Object.setPrototypeOf(rabbit, {}); // rabbit'in prototipini {}'e çevirme.
Object.create opsiyonel olarak ikinci bir argümana sahiptir: özellik tanımlayıcı. Aşağıdaki gibi yeni objeye özellikler ekleyebiliriz:
let animal = {
eats: true
};
let rabbit = Object.create(animal, {
jumps: {
value: true
}
});
alert(rabbit.jumps); // true
Tanımlayıcıların Özellik bayrakları ve tanımlayıcılar bölümünde üstünden geçilmiştir. Formatları aynıdır.
Object.create kullanarak obje klonlama işlemini yapabiliriz. Bu objenin özelliklerini for..in ile dolanmaktan daha etkin bir yöntemdir.
// Objenin yüzeysel klonu
let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
Bu tam olarak obj’nin aynısını verir. Tüm özellikler: dönülebilir veya dönülemez, veri özellikleri, alıcı ve ayarlayıcılar – her şey, ayrıca doğru [[Prototype]] ile
Tarihçe
[[Prototype]]'ı ayarlayabileceğimiz yöntemleri saymaya kalsak baya zorluk yaşarız. Çok fazla yöntem bulunmaktadır.
Neden?
Birçok nedeni bulunmaktadır.
- Yapıcının
"prototype"özelliği ilk javascript ortaya çıktığından beri bulunmaktadır. - 2012’de:
Object.createbir standart olarak oturdu. Bu verilen prototip ile objeleri yaratmaya izin verdi. Fakat bunları almaya veya ayarlamaya değil. Bundan dolayı tarayıcılar bir standart olmayan__proto__erişimcilerini uygulayarak alıcı ve ayarlayıcılara ( get/set)'e izin verdi. - 2015’te:
Object.setPrototypeOfveObject.getPrototypeOfbir standart olarak eklendi.__proto__defakto şeklinde aslında her yerde kullanılmıştı, Bundan dolayı çokta kulllanılan özellikler olmadı, sadece tarayıcı harici çevrelerde kullanılır oldu.
Artık bunların hepsi bizim kullanımımızdadır.
Teknik olarak [[Prototype]]'ı istediğimiz an alma/ayarlama işi yapabiliriz. Fakat genelde bunu sadece obje yaratırken kullanır ve daha sonra düzenleme yapmayız: rabbit, animaldan kalıtım alır fakat onu değiştirmez. JavaScript motorları da bunu yüksek derecede optimize edebilir. Prototipi Object.setPrototypeOf veya obj.__proto__ ile sonradan değiştirmek oldukça yavaş bir operasyondur. Ama mümkündür.
“En basit” Objeler
Bildiğiniz gibi objeler anahtar/değer ikilisini tutan ilişkisel dizi şeklinde kullanılabilir.
…Eğer içerisinde kullanıcı-kaynaklı anahtarlar ( örneğin kullanıcının girdiği sözlük tipi veriler) var ise, ilginç bir aksaklık meydana gelir: "__proto_" haricinde tüm anahtarlar doğru çalışır.
Örneğin:
let obj = {};
let key = prompt("What's the key?", "__proto__");
obj[key] = "some value";
alert(obj[key]); // [object Object] olarak döner , "some value" değil!
Eğer kullanıcı tipleri __proto__ içerisinde ise atama görmezden gelinir!
Bu aslında çok da sürpriz olmasa gerek. __proto__ farklı bir özelliktir: Ya obje olur veya null, mesela bir karakter dizisi prototip olamaz.
Fakat buradaki amacımız böyle bir davranışı uygulamak değildi, değil mi? Biz key/value ikililerini kaydetmekti. "__proto__"