
JavaScript Classes
Giriş
Önceki makalede constructor function'ları gördük. Çalışıyorlar ama syntax'ları dağınık: constructor bir yerde, prototype metotları başka yerde...
ES6 (2015) ile JavaScript'e class syntax'ı geldi. Aynı işi yapıyor ama çok daha temiz, organize ve okunabilir kod yazmanızı sağlıyor. Modern JavaScript'te nesne şablonları oluşturmanın önerilen yöntemi budur.
Class Nedir?
Class, nesne oluşturmak için kullanılan bir şablondur. Aslında constructor function'ların üzerine giydirilmiş "syntactic sugar" (sözdizimsel şeker) - yani aynı işi yapan daha güzel bir yazım şekli.
En Basit Class
class Kullanici {
constructor(ad, yas) {
this.ad = ad;
this.yas = yas;
}
}
const kullanici1 = new Kullanici("Ahmet", 25);
console.log(kullanici1); // Kullanici {ad: "Ahmet", yas: 25}Class Yapısı
class SinifAdi {
// Constructor: Nesne oluşturulurken çalışır
constructor(param1, param2) {
this.ozellik1 = param1;
this.ozellik2 = param2;
}
// Metotlar: Otomatik olarak prototype'a eklenir
metot1() {
// ...
}
metot2() {
// ...
}
}Temel Kurallar
- class keyword'ü ile başlar
- İsim büyük harfle başlar (convention):
Kullanici,Araba,Urun - constructor metodu zorunludur (nesne oluşturulurken çalışır)
- Metotlar arasında virgül yok
- new keyword'ü ile çağrılır
Constructor Metodu
constructor, class'tan yeni bir nesne oluşturulduğunda otomatik olarak çalışan özel metottur.
class Ogrenci {
constructor(ad, numara) {
console.log("Constructor çalıştı!");
// this = yeni oluşturulan nesne
this.ad = ad;
this.numara = numara;
this.notlar = [];
}
}
const ogrenci1 = new Ogrenci("Ali", 1234);
// Konsol: "Constructor çalıştı!"
// ogrenci1 = {ad: "Ali", numara: 1234, notlar: []}Constructor'da Yapılanlar
class Urun {
constructor(ad, fiyat) {
// 1. Özellikleri ayarla
this.ad = ad;
this.fiyat = fiyat;
// 2. Varsayılan değerler ata
this.stok = 0;
this.aktif = true;
// 3. Hesaplamalar yap
this.kdvliFiyat = fiyat * 1.20;
// 4. Doğrulama yap
if (fiyat < 0) {
throw new Error("Fiyat negatif olamaz!");
}
}
}Metot Tanımlama
Class içinde tanımlanan metotlar otomatik olarak prototype'a eklenir. Bu sayede tüm nesneler aynı metotları paylaşır.
class Hesap {
constructor(sahibi, bakiye) {
this.sahibi = sahibi;
this.bakiye = bakiye;
}
// Metotlar - prototype'a eklenir
paraYatir(miktar) {
this.bakiye += miktar;
console.log(`${miktar} TL yatırıldı.`);
}
paraCek(miktar) {
if (miktar > this.bakiye) {
console.log("Yetersiz bakiye!");
return false;
}
this.bakiye -= miktar;
console.log(`${miktar} TL çekildi.`);
return true;
}
bakiyeGoster() {
console.log(`${this.sahibi}: ${this.bakiye} TL`);
}
}Kullanım
const hesap1 = new Hesap("Mehmet", 1000);
const hesap2 = new Hesap("Ayşe", 5000);
hesap1.paraYatir(500); // 500 TL yatırıldı.
hesap1.bakiyeGoster(); // Mehmet: 1500 TL
hesap2.paraCek(2000); // 2000 TL çekildi.
hesap2.bakiyeGoster(); // Ayşe: 3000 TL
// Metotlar paylaşılıyor mu?
console.log(hesap1.paraYatir === hesap2.paraYatir); // true ✅Constructor Function vs Class Karşılaştırması
Eski Yöntem: Constructor Function
// Constructor
function Araba(marka, model) {
this.marka = marka;
this.model = model;
}
// Metotlar ayrı ayrı tanımlanır
Araba.prototype.bilgiVer = function() {
return `${this.marka} ${this.model}`;
};
Araba.prototype.calistir = function() {
console.log("Motor çalıştı!");
};
Araba.prototype.durdur = function() {
console.log("Motor durdu!");
};Yeni Yöntem: Class
class Araba {
constructor(marka, model) {
this.marka = marka;
this.model = model;
}
// Tüm metotlar bir arada!
bilgiVer() {
return `${this.marka} ${this.model}`;
}
calistir() {
console.log("Motor çalıştı!");
}
durdur() {
console.log("Motor durdu!");
}
}Fark: Class ile her şey tek bir blok içinde, organize ve okunabilir!
Pratik Örnek: Todo Uygulaması
class TodoListesi {
constructor(baslik) {
this.baslik = baslik;
this.gorevler = [];
}
gorevEkle(metin) {
const gorev = {
id: Date.now(),
metin: metin,
tamamlandi: false,
tarih: new Date().toLocaleDateString("tr-TR")
};
this.gorevler.push(gorev);
console.log(`✅ Görev eklendi: "${metin}"`);
return gorev;
}
gorevTamamla(id) {
const gorev = this.gorevler.find(g => g.id === id);
if (gorev) {
gorev.tamamlandi = true;
console.log(`✓ Tamamlandı: "${gorev.metin}"`);
}
}
gorevSil(id) {
const index = this.gorevler.findIndex(g => g.id === id);
if (index > -1) {
const silinen = this.gorevler.splice(index, 1)[0];
console.log(`🗑️ Silindi: "${silinen.metin}"`);
}
}
bekleyenler() {
return this.gorevler.filter(g => !g.tamamlandi);
}
tamamlananlar() {
return this.gorevler.filter(g => g.tamamlandi);
}
ozet() {
const bekleyen = this.bekleyenler().length;
const tamamlanan = this.tamamlananlar().length;
console.log(`
📋 ${this.baslik}
────────────────────
Toplam: ${this.gorevler.length} görev
Bekleyen: ${bekleyen}
Tamamlanan: ${tamamlanan}
────────────────────`);
}
listele() {
console.log(`\n📋 ${this.baslik}\n`);
this.gorevler.forEach(g => {
const durum = g.tamamlandi ? "✓" : "○";
console.log(`${durum} ${g.metin} (${g.tarih})`);
});
}
}Kullanım
const isListesi = new TodoListesi("Haftalık İşler");
const gorev1 = isListesi.gorevEkle("Alışveriş yap");
const gorev2 = isListesi.gorevEkle("Fatura öde");
const gorev3 = isListesi.gorevEkle("Spor yap");
isListesi.gorevTamamla(gorev1.id);
isListesi.listele();
/*
📋 Haftalık İşler
✓ Alışveriş yap (27.01.2024)
○ Fatura öde (27.01.2024)
○ Spor yap (27.01.2024)
*/
isListesi.ozet();
/*
📋 Haftalık İşler
────────────────────
Toplam: 3 görev
Bekleyen: 2
Tamamlanan: 1
────────────────────
*/Pratik Örnek: Oyuncu Karakteri
class Karakter {
constructor(isim, sinif) {
this.isim = isim;
this.sinif = sinif;
this.seviye = 1;
this.deneyim = 0;
this.maxCan = 100;
this.can = 100;
this.guc = 10;
this.envanter = [];
}
// Savaş metotları
saldir(hedef) {
const hasar = Math.floor(Math.random() * this.guc) + 5;
console.log(`⚔️ ${this.isim}, ${hedef.isim}'e ${hasar} hasar verdi!`);
hedef.hasarAl(hasar);
return hasar;
}
hasarAl(miktar) {
this.can -= miktar;
if (this.can <= 0) {
this.can = 0;
console.log(`💀 ${this.isim} yenildi!`);
} else {
console.log(`💔 ${this.isim}'in canı: ${this.can}/${this.maxCan}`);
}
}
iyiles(miktar) {
this.can = Math.min(this.can + miktar, this.maxCan);
console.log(`💚 ${this.isim} ${miktar} can yeniledi. Can: ${this.can}/${this.maxCan}`);
}
// Gelişim metotları
deneyimKazan(miktar) {
this.deneyim += miktar;
console.log(`✨ ${this.isim} ${miktar} XP kazandı!`);
// Seviye atlama kontrolü
const gerekliXP = this.seviye * 100;
if (this.deneyim >= gerekliXP) {
this.seviyeAtla();
}
}
seviyeAtla() {
this.seviye++;
this.deneyim = 0;
this.maxCan += 20;
this.can = this.maxCan;
this.guc += 5;
console.log(`🎉 ${this.isim} seviye atladı! Seviye: ${this.seviye}`);
}
// Envanter metotları
esyaEkle(esya) {
this.envanter.push(esya);
console.log(`🎒 ${esya} envantere eklendi.`);
}
esyaKullan(esyaAdi) {
const index = this.envanter.indexOf(esyaAdi);
if (index > -1) {
this.envanter.splice(index, 1);
console.log(`🧪 ${esyaAdi} kullanıldı.`);
return true;
}
console.log(`❌ ${esyaAdi} envanterde yok!`);
return false;
}
// Durum metodu
durum() {
console.log(`
╔══════════════════════════╗
║ ${this.isim.padEnd(22)} ║
╠══════════════════════════╣
║ Sınıf: ${this.sinif.padEnd(17)}║
║ Seviye: ${String(this.seviye).padEnd(16)}║
║ XP: ${this.deneyim}/${this.seviye * 100}${" ".repeat(14 - String(this.deneyim).length - String(this.seviye * 100).length)}║
║ Can: ${this.can}/${this.maxCan}${" ".repeat(15 - String(this.can).length - String(this.maxCan).length)}║
║ Güç: ${String(this.guc).padEnd(18)}║
║ Envanter: ${this.envanter.length} eşya${" ".repeat(9)}║
╚══════════════════════════╝
`);
}
}Kullanım
const savaşçı = new Karakter("Thorin", "Savaşçı");
const büyücü = new Karakter("Gandalf", "Büyücü");
savaşçı.esyaEkle("Kılıç");
savaşçı.esyaEkle("Kalkan");
savaşçı.esyaEkle("İksir");
savaşçı.saldir(büyücü); // Thorin, Gandalf'a X hasar verdi!
büyücü.saldir(savaşçı); // Gandalf, Thorin'e X hasar verdi!
savaşçı.deneyimKazan(50);
savaşçı.deneyimKazan(60); // Seviye atlama!
savaşçı.durum();Getter ve Setter
Class içinde özel erişim metotları tanımlayabilirsiniz:
class Dikdortgen {
constructor(en, boy) {
this.en = en;
this.boy = boy;
}
// Getter - özellik gibi erişilir, parantez yok
get alan() {
return this.en * this.boy;
}
get cevre() {
return 2 * (this.en + this.boy);
}
// Setter - değer atanırken çalışır
set alan(yeniAlan) {
// Alanı koruyarak eni ayarla (boy sabit)
this.en = yeniAlan / this.boy;
}
}
const dikdortgen = new Dikdortgen(5, 10);
// Getter kullanımı - parantez YOK
console.log(dikdortgen.alan); // 50
console.log(dikdortgen.cevre); // 30
// Setter kullanımı
dikdortgen.alan = 100; // en otomatik 10 olur
console.log(dikdortgen.en); // 10
console.log(dikdortgen.alan); // 100Static Metotlar
Static metotlar nesne oluşturmadan, doğrudan class üzerinden çağrılır:
class Matematik {
static topla(a, b) {
return a + b;
}
static cikar(a, b) {
return a - b;
}
static rastgele(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
static PI = 3.14159;
}
// Static metotlar - class üzerinden çağrılır
console.log(Matematik.topla(5, 3)); // 8
console.log(Matematik.rastgele(1, 100)); // Rastgele sayı
console.log(Matematik.PI); // 3.14159
// ❌ Nesne üzerinden çağrılamaz!
const m = new Matematik();
m.topla(5, 3); // Error!Static Ne Zaman Kullanılır?
- Yardımcı fonksiyonlar (helper/utility)
- Fabrika metotları
- Sabit değerler
class Kullanici {
constructor(ad, email) {
this.ad = ad;
this.email = email;
}
// Static fabrika metodu
static misafirOlustur() {
return new Kullanici("Misafir", "misafir@site.com");
}
// Static yardımcı metot
static emailGecerliMi(email) {
return email.includes("@");
}
}
// Fabrika metodu kullanımı
const misafir = Kullanici.misafirOlustur();
// Yardımcı metot kullanımı
console.log(Kullanici.emailGecerliMi("test@mail.com")); // trueClass Özellikleri (Class Fields)
Modern JavaScript'te özellikleri constructor dışında da tanımlayabilirsiniz:
class Sayac {
// Class field - constructor dışında
deger = 0;
adim = 1;
constructor(baslangic = 0) {
this.deger = baslangic;
}
artir() {
this.deger += this.adim;
}
azalt() {
this.deger -= this.adim;
}
}
const sayac = new Sayac(10);
sayac.artir();
console.log(sayac.deger); // 11Private Alanlar (#)
# ile başlayan özellikler class dışından erişilemez:
class BankaHesabi {
#bakiye = 0; // Private!
#pin;
constructor(sahibi, pin) {
this.sahibi = sahibi;
this.#pin = pin;
}
#pinDogrula(girilenPin) { // Private metot!
return this.#pin === girilenPin;
}
paraYatir(miktar) {
this.#bakiye += miktar;
console.log(`Yatırıldı: ${miktar} TL`);
}
paraCek(miktar, pin) {
if (!this.#pinDogrula(pin)) {
console.log("❌ Hatalı PIN!");
return false;
}
if (miktar > this.#bakiye) {
console.log("❌ Yetersiz bakiye!");
return false;
}
this.#bakiye -= miktar;
console.log(`Çekildi: ${miktar} TL`);
return true;
}
bakiyeSorgula(pin) {
if (!this.#pinDogrula(pin)) {
console.log("❌ Hatalı PIN!");
return null;
}
return this.#bakiye;
}
}
const hesap = new BankaHesabi("Ali", 1234);
hesap.paraYatir(1000);
hesap.paraCek(500, 1234); // Çekildi: 500 TL
hesap.paraCek(500, 0000); // ❌ Hatalı PIN!
// ❌ Dışarıdan erişilemez!
console.log(hesap.#bakiye); // SyntaxError!
console.log(hesap.#pin); // SyntaxError!Özet
class SinifAdi {
// Class fields (opsiyonel)
ozellik = "deger";
#privateOzellik = "gizli";
// Constructor (zorunlu)
constructor(param) {
this.param = param;
}
// Instance metotları (prototype'a eklenir)
normalMetot() {
return this.param;
}
// Getter
get hesaplananDeger() {
return this.param * 2;
}
// Setter
set hesaplananDeger(yeniDeger) {
this.param = yeniDeger / 2;
}
// Private metot
#gizliMetot() {
// ...
}
// Static metot
static yardimciMetot() {
// ...
}
}| Özellik | Açıklama |
|---|---|
| class | Nesne şablonu tanımlar |
| constructor | Nesne oluşturulurken çalışır |
| this | Oluşturulan nesneyi ifade eder |
| Metotlar | Otomatik prototype'a eklenir |
| static | Class üzerinden çağrılan metotlar |
| get/set | Özel erişim metotları |
| # | Private (gizli) alanlar |
Sırada Ne Var?
Class syntax'ını öğrendik. Artık temiz, organize kod yazabiliyoruz.
Bir sonraki makalede class'larla daha fazla pratik yapacağız ve gerçek dünya örnekleri üzerinde çalışacağız.


