
Önceki makalede Factory Function'ların bir sorununu gördük: her nesne oluşturulduğunda metotların yeni kopyaları üretiliyor. Bu hafıza israfına yol açıyordu.
Peki metotları nasıl paylaştırabiliriz? İşte Constructor Functions ve new keyword'ü tam da bu sorunu çözmek için var. Prototype sistemini kullanarak metotları tek bir yerde tutmamızı sağlar.
new Keyword'ü Zaten Kullanıyorsunuz!
Aslında new keyword'ünü daha önce görmüştük:
// Array oluşturma (alternatif yol)
const dizi = new Array(1, 2, 3);
// Date nesnesi
const tarih = new Date();
// XMLHttpRequest
const xhr = new XMLHttpRequest();
// RegExp
const regex = new RegExp("\\d+");Tüm bu new ile başlayan ifadeler bir constructor function çağırıyor!
Constructor Function Nedir?
Constructor Function, new keyword'ü ile çağrıldığında yeni nesne oluşturan özel bir fonksiyondur.
Temel Yapı
// Constructor function - büyük harfle başlar (convention)
function Kullanici(ad, yas) {
this.ad = ad;
this.yas = yas;
}
// new ile çağırma
const kullanici1 = new Kullanici("Ahmet", 25);
const kullanici2 = new Kullanici("Ayşe", 30);
console.log(kullanici1); // Kullanici {ad: "Ahmet", yas: 25}
console.log(kullanici2); // Kullanici {ad: "Ayşe", yas: 30}Dikkat Edilecekler
- İsim büyük harfle başlar -
Kullanici,Araba,Urun(convention) - return yok -
newotomatik olarak nesneyi döndürür - this kullanılır - Oluşturulan nesneye özellik eklemek için
new Keyword Ne Yapar?
new keyword'ü 4 önemli işlem yapar:
function Araba(marka, model) {
// new çağrıldığında arka planda:
// 1. Boş bir nesne oluşturulur
// this = {}
// 2. this.__proto__ = Araba.prototype olarak ayarlanır
// 3. Fonksiyon çalışır, this'e özellikler eklenir
this.marka = marka;
this.model = model;
// 4. this otomatik olarak döndürülür
// return this
}Görsel Temsil
new Araba("Toyota", "Corolla") çağrıldığında:
┌─────────────────────────────────────────────────────┐
│ 1. Boş nesne oluştur: this = {} │
│ 2. Prototype bağla: this.__proto__ = Araba.prototype │
│ 3. Fonksiyonu çalıştır: this.marka = "Toyota" │
│ this.model = "Corolla" │
│ 4. Nesneyi döndür: return this │
└─────────────────────────────────────────────────────┘
│
▼
{ marka: "Toyota", model: "Corolla" }new Olmadan Çağırırsak?
function Kullanici(ad) {
this.ad = ad;
console.log(this);
}
// new ile - DOĞRU
const user1 = new Kullanici("Ali");
// this = yeni oluşturulan nesne
// Çıktı: Kullanici {ad: "Ali"}
// new olmadan - YANLIŞ!
const user2 = Kullanici("Veli");
// this = window (global object)
// user2 = undefined (return yok!)
// window.ad = "Veli" oldu! 😱Önemli: Constructor function'ları her zaman new ile çağırın!
Prototype'a Metot Ekleme
İşte constructor function'ların asıl gücü! Metotları prototype'a ekleyerek tüm nesneler arasında paylaştırabilirsiniz:
// Constructor function
function Hesap(sahibi, bakiye) {
this.sahibi = sahibi;
this.bakiye = bakiye;
}
// Metotları prototype'a ekle
Hesap.prototype.paraYatir = function(miktar) {
this.bakiye += miktar;
console.log(`${miktar} TL yatırıldı. Bakiye: ${this.bakiye} TL`);
};
Hesap.prototype.paraCek = function(miktar) {
if (miktar > this.bakiye) {
console.log("Yetersiz bakiye!");
return;
}
this.bakiye -= miktar;
console.log(`${miktar} TL çekildi. Bakiye: ${this.bakiye} TL`);
};
Hesap.prototype.bilgiGoster = function() {
console.log(`${this.sahibi} - ${this.bakiye} TL`);
};Kullanım
const hesap1 = new Hesap("Mehmet", 1000);
const hesap2 = new Hesap("Zeynep", 5000);
hesap1.paraYatir(500); // 500 TL yatırıldı. Bakiye: 1500 TL
hesap2.paraCek(1000); // 1000 TL çekildi. Bakiye: 4000 TL
hesap1.bilgiGoster(); // Mehmet - 1500 TL
hesap2.bilgiGoster(); // Zeynep - 4000 TLFactory vs Constructor: Hafıza Karşılaştırması
// Metotların aynı olup olmadığını kontrol edelim
// FACTORY FUNCTION
function fabrikaKullanici(ad) {
return {
ad,
selamla() { console.log(`Merhaba, ${this.ad}`); }
};
}
const fUser1 = fabrikaKullanici("Ali");
const fUser2 = fabrikaKullanici("Veli");
console.log(fUser1.selamla === fUser2.selamla); // false ❌
// Her nesnenin AYRI metot kopyası var!
// CONSTRUCTOR FUNCTION
function ConstKullanici(ad) {
this.ad = ad;
}
ConstKullanici.prototype.selamla = function() {
console.log(`Merhaba, ${this.ad}`);
};
const cUser1 = new ConstKullanici("Ali");
const cUser2 = new ConstKullanici("Veli");
console.log(cUser1.selamla === cUser2.selamla); // true ✅
// İkisi de AYNI metodu paylaşıyor!Görsel Karşılaştırma
FACTORY FUNCTION:
┌──────────┐ ┌──────────┐
│ fUser1 │ │ fUser2 │
│ ad:"Ali" │ │ ad:"Veli"│
│ selamla()│ │ selamla()│ ← Her birinin AYRI kopyası
└──────────┘ └──────────┘
CONSTRUCTOR FUNCTION:
┌──────────┐ ┌──────────┐
│ cUser1 │ │ cUser2 │
│ ad:"Ali" │ │ ad:"Veli"│
│__proto__─┼──┼─__proto__│
└──────────┘ └──────────┘
│ │
└─────┬──────┘
▼
┌─────────────────┐
│ Prototype │
│ selamla() │ ← TEK kopya, paylaşılıyor
└─────────────────┘Pratik Örnek: Oyuncu Sistemi
// Constructor function
function Oyuncu(isim, seviye) {
this.isim = isim;
this.seviye = seviye || 1;
this.deneyim = 0;
this.can = 100;
}
// Prototype metotları
Oyuncu.prototype.deneyimKazan = function(miktar) {
this.deneyim += miktar;
console.log(`${this.isim} ${miktar} XP kazandı!`);
// Seviye atlama kontrolü
if (this.deneyim >= this.seviye * 100) {
this.seviyeAtla();
}
};
Oyuncu.prototype.seviyeAtla = function() {
this.seviye++;
this.deneyim = 0;
this.can = 100; // Can yenilenir
console.log(`🎉 ${this.isim} seviye atladı! Yeni seviye: ${this.seviye}`);
};
Oyuncu.prototype.hasarAl = function(miktar) {
this.can -= miktar;
console.log(`${this.isim} ${miktar} hasar aldı. Can: ${this.can}`);
if (this.can <= 0) {
console.log(`💀 ${this.isim} öldü!`);
}
};
Oyuncu.prototype.durum = function() {
console.log(`
══════════════════════
İsim: ${this.isim}
Seviye: ${this.seviye}
XP: ${this.deneyim}/${this.seviye * 100}
Can: ${this.can}/100
══════════════════════
`);
};Kullanım
const oyuncu1 = new Oyuncu("DragonSlayer", 1);
const oyuncu2 = new Oyuncu("ShadowNinja", 3);
oyuncu1.deneyimKazan(50); // DragonSlayer 50 XP kazandı!
oyuncu1.deneyimKazan(60); // DragonSlayer 60 XP kazandı!
// 🎉 DragonSlayer seviye atladı! Yeni seviye: 2
oyuncu1.hasarAl(30); // DragonSlayer 30 hasar aldı. Can: 70
oyuncu1.durum();
// Metotların paylaşıldığını doğrula
console.log(oyuncu1.durum === oyuncu2.durum); // truePratik Örnek: Ürün Kataloğu
function Urun(ad, fiyat, kategori) {
this.ad = ad;
this.fiyat = fiyat;
this.kategori = kategori;
this.stok = 0;
this.indirimOrani = 0;
}
Urun.prototype.stokEkle = function(adet) {
this.stok += adet;
return this; // Zincirleme için
};
Urun.prototype.stokCikar = function(adet) {
if (adet > this.stok) {
console.log(`Yetersiz stok! Mevcut: ${this.stok}`);
return this;
}
this.stok -= adet;
return this;
};
Urun.prototype.indirimYap = function(yuzde) {
this.indirimOrani = yuzde;
return this;
};
Urun.prototype.guncelFiyat = function() {
const indirim = this.fiyat * (this.indirimOrani / 100);
return this.fiyat - indirim;
};
Urun.prototype.ozet = function() {
const fiyatStr = this.indirimOrani > 0
? `${this.fiyat} TL → ${this.guncelFiyat()} TL (%${this.indirimOrani} indirim)`
: `${this.fiyat} TL`;
console.log(`[${this.kategori}] ${this.ad} - ${fiyatStr} (Stok: ${this.stok})`);
};Kullanım
const laptop = new Urun("MacBook Pro", 75000, "Elektronik");
const telefon = new Urun("iPhone 15", 55000, "Elektronik");
// Zincirleme kullanım
laptop.stokEkle(10).indirimYap(15);
telefon.stokEkle(25);
laptop.ozet();
// [Elektronik] MacBook Pro - 75000 TL → 63750 TL (%15 indirim) (Stok: 10)
telefon.ozet();
// [Elektronik] iPhone 15 - 55000 TL (Stok: 25)Arrow Function Kullanmayın!
Constructor prototype'larında arrow function kullanmayın. Arrow function'lar this'i farklı işler:
function Kisi(ad) {
this.ad = ad;
}
// ❌ YANLIŞ - Arrow function
Kisi.prototype.selamlaYanlis = () => {
console.log(`Merhaba, ${this.ad}`); // this = window!
};
// ✅ DOĞRU - Normal function
Kisi.prototype.selamlaDogru = function() {
console.log(`Merhaba, ${this.ad}`); // this = nesne
};
const kisi = new Kisi("Ali");
kisi.selamlaYanlis(); // Merhaba, undefined
kisi.selamlaDogru(); // Merhaba, Aliinstanceof Operatörü
Bir nesnenin hangi constructor'dan oluşturulduğunu kontrol edebilirsiniz:
function Araba(marka) {
this.marka = marka;
}
function Bisiklet(marka) {
this.marka = marka;
}
const toyota = new Araba("Toyota");
const bianchi = new Bisiklet("Bianchi");
console.log(toyota instanceof Araba); // true
console.log(toyota instanceof Bisiklet); // false
console.log(bianchi instanceof Bisiklet); // true
// Tüm nesneler Object'ten türer
console.log(toyota instanceof Object); // trueConstructor Function'ın Dezavantajları
1. Dağınık Sözdizimi
// Constructor ayrı
function Hayvan(isim) {
this.isim = isim;
}
// Metotlar ayrı ayrı
Hayvan.prototype.konus = function() { ... };
Hayvan.prototype.yuru = function() { ... };
Hayvan.prototype.ye = function() { ... };
// Kod dağınık ve takibi zor2. new Unutma Riski
const kedi = Hayvan("Tekir"); // new unutuldu!
// kedi = undefined
// window.isim = "Tekir" 😱3. Okunabilirlik
// Birçok prototype tanımı ardarda...
Urun.prototype.metot1 = function() { ... };
Urun.prototype.metot2 = function() { ... };
Urun.prototype.metot3 = function() { ... };
// Hangi metot nereye ait? Karışık!Özet
// Constructor Function şablonu
function NesneAdi(param1, param2) {
this.ozellik1 = param1;
this.ozellik2 = param2;
}
// Metotları prototype'a ekle
NesneAdi.prototype.metot1 = function() {
// this.ozellik1 kullan
};
NesneAdi.prototype.metot2 = function() {
// this.ozellik2 kullan
};
// Kullanım - new ile!
const nesne = new NesneAdi(deger1, deger2);| Özellik | Factory Function | Constructor Function |
|---|---|---|
| Çağırma | fonksiyon() | new Fonksiyon() |
| Metot paylaşımı | ❌ Her nesne kendi kopyasını taşır | ✅ Prototype'ta paylaşılır |
| Hafıza | Daha fazla kullanır | Daha verimli |
| instanceof | ❌ Çalışmaz | ✅ Çalışır |
| Syntax | Basit | Dağınık |
Sırada Ne Var?
Constructor function'lar çalışıyor ama syntax'ı dağınık: constructor ayrı, prototype metotları ayrı...
ES6 ile gelen class syntax'ı tüm bunları tek bir yapı altında toplar. Aynı işi yapar ama çok daha temiz ve okunabilir kod yazmanızı sağlar.
Bir sonraki makalede JavaScript Classes konusunu öğreneceğiz - modern ve önerilen yöntem!


