Modern JavaScript’te protitip’i __proto__
kullanarak ( bir önceki bölümde anlatıldığı gibi ) ayarlayabiliriz. Fakat bu daha öncesinde böyle değildi.
JavaScript başlangıcından beri kalıtıma sahipti. Bu dilin çekirdek özelliklerinden biriydi.
Fakat bunu ayarlamak için sadece bir yol vardı ve bu yol yapıcıda(constructor)'da "prototype"
kullanmaktı. Hala birçok kodda bu şekilde kullanılmaktadır.
“Prototip” özelliği
Bildiğiniz gibi, new F()
yeni bir obje oluşturur.
new F()
ile yeni bir obje yaratıldığında, obje’nin [[Prototype]]
'ı F.prototype
a ayarlanır.
Diğer bir deyişle, eğer F
prototype
özelliğine sahip ve bu da obje tipine ayarlanmışsa, new
operatörü bunu [[Prototype]]
ayarlamak için kullanır.
Aklınızda bulunsun F.prototype
burada F
’in sahip olduğu sıradan bir "prototype"
objesidir. “prototype” terimine çok benzese de aslında burada gerçekten kullanılan sıradan bir objedir.
Örneğin:
let animal = {
eats: true
};
function Rabbit(name) {
this.name = name;
}
Rabbit.prototype = animal;
let rabbit = new Rabbit("White Rabbit"); // rabbit.__proto__ == animal
alert( rabbit.eats ); // true
Rabbit.prototype = animal
sözcük anlamıyla: “Eğer yeni bir Rabbit yaratılırsa new Rabbit
, bunun [[Prototype]]
ını animal
’a ata”
Sonuç şu şekildedir:
Görselde "prototip"
yataydaki oktur, sıranda bir özelliktir. [[Prototype]]
ise dikeydir ve rabbit
’in animal
’dan miras aldığını ifade eder.
Sıradan F.prototype, yapıcı (contructor) özelliği
Her fonksiyonun "prototype"
özelliği bulunmaktadır. Siz belirtmeseniz bile bu geçerlidir.
Varsayılan "prototype" sadece
contructor` özelliği olan olan ve bu da fonksiyonun kendisini gösteren bir objedir.
Şu şekilde:
function Rabbit() {}
/* varsayılan prototip
Rabbit.prototype = { constructor: Rabbit };
*/
Şu şekilde kontrol edebiliriz:
function Rabbit() {}
// varsayılan:
// Rabbit.prototype = { constructor: Rabbit }
alert( Rabbit.prototype.constructor == Rabbit ); // true
Eğer hiçbir şey yapmazsak doğal olarak contructor
özelliği tüm rabbit objelerine [[Prototype]]
vasıtasıyla iletilir.
function Rabbit() {}
// varsayılan:
// Rabbit.prototype = { constructor: Rabbit }
let rabbit = new Rabbit(); // {constructor: Rabbit}'dan miras alır.
alert(rabbit.constructor == Rabbit); // true (prototype'tan gelir)
Eğer constructor
özelliğini kullarak varolan yapıcı ile aynı şekilde bir obje yapabiliriz.
Şu şekilde:
function Rabbit(name) {
this.name = name;
alert(name);
}
let rabbit = new Rabbit("White Rabbit");
let rabbit2 = new rabbit.constructor("Black Rabbit");
Bir obje var fakat bu objenin ( 3. parti kütüphanelerden gelebilir) hangi yapıcısının kullanıldığını bilmiyorsak ve aynısını yaratmak istiyorsak oldukça kullanışlıdır.
Muhtemelen "contructor"
hakkındaki en önemli şey…
… JavaScript "contructor"
değerinin doğru olduğuna garanti vermez.
Evet, varsayılan "prototype"
da bulunur fakat hepsi budur, sonrasındaki her şey bize aittir.
Daha özelde, eğer prototip’i tamamen değiştirirsek, bu durumda içinde "contructor"
olmayacaktır.
Örneğin:
function Rabbit() {}
Rabbit.prototype = {
jumps: true
};
let rabbit = new Rabbit();
alert(rabbit.constructor === Rabbit); // false
Öyleyse doğru "contructor"
'ı tutmak için varsayılan prototip’e özellik ekleme/çıkarma yoluna gidebiliriz. Tamamen üzerine yazarsak varsayılan obje kaybolur.
function Rabbit() {}
// Rabbit.prototype üzerine doğrudan yazma!
// sadece ekle
Rabbit.prototype.jumps = true
// varsayılan Rabbit.prototype.contructor bu şekilde korunacaktır.
Veya alternatif olarak, constructor
özelliği tekrar yaratılabilir:
Rabbit.prototype = {
jumps: true,
constructor: Rabbit
};
// bu şekilde constructor doğru olur, çünkü bunu el ile belirtmekteyiz.
Özet
Bu bölümde kısaca yapıcı fonksiyonlar ile oluşturulan objelerin [[Prototip]]
'lerinin nasıl ayarlanabileceğinden bahsettik. İlerde bunların daha gelişmişini programlama kalıpları üzerinde öğreneceksiniz.
Her şey aslında çok basit, birkaç cümle ile daha net anlatmak gerekirse:
F.prototype
özelliği[[Prototype]]
ile aynı değildir.F.prototype
aslındanew F()
çağırıldığında[[Prototype]]
'ı ayarlar.F.prototype
değeri ya obje ya da null olmalıdır: diğer değerler çalışmaz."prototype"
özelliği sadece bir yapıcı fonksiyona ayarlandığı venew
ile çağırıldığında özel etkisi olur.
Normal objeler prototype
’ın ayrı bir önemi yoktur:
let user = {
name: "John",
prototype: "Bla-bla" // hiçbir büyüsü yok
};
Varsayılan durumda tüm fonksiyonlar F.prototype = { constructor: F}
şeklinde tanımlıdır, bundan dolayı, bir objenin yapıcısına "constructor"
özelliği ile erişilebilir.