Mehmet

WFN Üye
Konular
1,851
Mesajlar
1,852
Çözüm
0
Ticaret Puanı
0
Üyelik
1 Ay 6 Gün
Konum
YurtDışı
Web Sitesi
Var
Alanı
Google Adsense
1/1
Konu sahibi
JavaScript’te prototype, bir nesnenin özellik ve metotları başka nesnelerden miras almasını sağlayan nesnedir. Bir nesnede aranan özellik doğrudan bulunamazsa JavaScript, nesnenin prototype zincirinde yukarı doğru arama yapar. Böylece aynı metodu her nesneye ayrı ayrı kopyalamak yerine ortak prototype üzerinde tanımlayabilirsiniz.

Prototype nasıl çalışır?​


JavaScript nesnelerinin dahili prototype bağlantısı başka bir nesneye veya zincirin sonunu belirten null değerine işaret eder. Bu bağlantı standart gösterimde [[Prototype]] olarak ifade edilir. Arama sırası şöyledir:
  1. Özellik önce nesnenin kendi üzerinde aranır.
  2. Bulunamazsa nesnenin [[Prototype]] nesnesine bakılır.
  3. Orada da bulunamazsa zincirdeki bir sonraki prototype kontrol edilir.
  4. Zincir null değerine ulaştığında arama sona erer.
Örneğin dizi nesnelerinde kullandığınız map(), filter() ve push() metotları genellikle her diziye ayrı ayrı yazılmaz. Bu davranışlar Array.prototype üzerinden miras alınır.

Önemli ayrım: prototype çoğunlukla constructor fonksiyonlarının sahip olduğu normal bir özelliktir. [[Prototype]] ise bir nesnenin miras aldığı nesneye yapılan dahili bağlantıdır. new kullanıldığında bu iki kavram ilişkilendirilir.

Somut örnek: Ortak metot tanımlama​


Aşağıdaki örnekte User constructor fonksiyonuyla oluşturulan nesneler, greet() metodunu User.prototype üzerinden paylaşır:

Kod:
function User(name) {
  this.name = name;
}

User.prototype.greet = function () {
  return `Merhaba, ben ${this.name}`;
};

const user1 = new User("Ayşe");
const user2 = new User("Mehmet");

console.log(user1.greet());
console.log(user2.greet());
console.log(user1.greet === user2.greet);
console.log(Object.getPrototypeOf(user1) === User.prototype);

Beklenen çıktı şöyledir:

Kod:
Merhaba, ben Ayşe
Merhaba, ben Mehmet
true
true

İlk iki satır metodun this değerinin çağrıyı yapan nesne olduğunu gösterir. Üçüncü satır, iki nesnenin aynı fonksiyon referansını prototype üzerinden kullandığını doğrular. Dördüncü satır ise new User() ile oluşan nesnenin prototype bağlantısının User.prototype olduğunu gösterir.

Metodu doğrudan constructor içinde tanımlarsanız her örnek için yeni bir fonksiyon oluşturulur:

Kod:
function User(name) {
  this.name = name;
  this.greet = function () {
    return `Merhaba, ben ${this.name}`;
  };
}

Bu yaklaşım küçük örneklerde çalışır; ancak çok sayıda nesne oluşturulacaksa ortak metotları prototype üzerinde tutmak genellikle daha uygun bir tasarımdır.

Sık kullanılan kavramların farkı​


Kavramları karıştırmamak için aşağıdaki ayrımı kullanabilirsiniz.
KavramAnlamıPratik kullanım
User.prototypeConstructor fonksiyonunun ortak özellik alanıÖrneklerin paylaşacağı metotları tanımlamak
Object.getPrototypeOf(user)Belirli nesnenin prototype bağlantısını okumakMiras zincirini incelemek
classPrototype tabanlı yapıyı daha okunabilir sözdizimiyle kullanmakYeni kodda sınıf benzeri yapı kurmak
__proto__Eski ve önerilmeyen erişim yoluYeni kodda kullanmamak

class ile prototype ilişkisi​


class sözdizimi prototype mekanizmasını ortadan kaldırmaz; onu daha okunabilir biçimde kullanır:

Kod:
class User {
  constructor(name) {
    this.name = name;
  }

  greet() {
    return `Merhaba, ben ${this.name}`;
  }
}

Bu örnekte greet() metodu örneklerin kendi içine kopyalanmak yerine sınıfın prototype yapısıyla ilişkilendirilir. Bu nedenle class kullanırken de prototype zincirini anlamak; miras alma, metot ezme ve hata ayıklama sırasında faydalıdır.

Sık yapılan hatalar​


Prototype ile nesnenin kendi özelliğini karıştırmak: user.name doğrudan nesne üzerinde bulunabilirken user.greet prototype zincirinden gelebilir.

Paylaşılan veriyi prototype üzerine koymak: Dizi veya değişebilir nesne gibi ortak bir değeri prototype üzerinde tutmak, tüm örneklerin aynı veriyi paylaşmasına yol açabilir. Örnek verileri constructor içinde, ortak metotları prototype üzerinde tutmak daha güvenlidir.

__proto__ kullanmak: Object.getPrototypeOf() bağlantıyı yalnız okur; Object.create() yeni nesneyi seçilen prototype ile kurar; Object.setPrototypeOf() mevcut bağlantıyı değiştirir. Bu işlemler aynı amaçla kullanılmaz. Prototype bağlantısını çalışma sırasında sık sık değiştirmekten de kaçının.

Sonraki adım: Kendi nesnelerinizde hangi özelliklerin örneğe özel, hangi metotların ortak olması gerektiğini ayırın. Ardından Object.getPrototypeOf() ile zinciri inceleyerek beklenmeyen miras davranışlarını doğrulayın.

Sık sorulan sorular​


Prototype zincirinde aynı isimli özellik varsa hangisi kullanılır?​


Nesnenin kendi özelliği, prototype üzerindeki aynı isimli özelliği gölgeler. Kendi özellik silinirse arama yeniden prototype zincirine ilerler.

Her JavaScript nesnesinin prototype’ı var mıdır?​


Çoğu nesnenin vardır; ancak zincirin sonundaki Object.prototype nesnesinin prototype’ı null değeridir. Object.create(null) ile doğrudan prototype’sız bir nesne de oluşturulabilir.

Özelliğin nesnenin kendisine mi ait olduğunu nasıl anlarım?​


Object.hasOwn(user1, "name") örnekte true, Object.hasOwn(user1, "greet") false döner. Buna karşılık "greet" in user1 miras alınan özelliği de gördüğü için true döner. Bu ayrım, nesnenin yalnız kendi alanlarını işlerken yararlıdır.
 
Son düzenleme:

Sende şimdi bize katılmak ister misin?

Kayıt ol

Bize katılım kolay ve ücretsizdir!

Konuyu görüntüleyenler

Bu konuyu şu anda görüntüleyen üye bulunmuyor.