JavaScript'te class aslında bir prototip-tabanlı sistemin üzerine
yazılmış kibar bir sözdizimidir. Class'ı gerçekten anlamak için altındaki
prototip mekaniğini anlaman lazım.
Her objenin bir [[Prototype]]'i var
Her obje, başka bir objeyi referans gösterir. Bir property okuyamadığında bu referansa bakar. Buna prototip zinciri denir.
const a = { x: 1 };
const b = Object.create(a);
b.y = 2;
console.log(b.x); // 1 — kendi yok, a'ya baktı
console.log(b.y); // 2
Object.getPrototypeOf(b) === a; // trueFunction.prototype
Eski yol (sınıf yokken):
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function () {
return `${this.name} ses çıkardı`;
};
const a = new Animal("Karabaş");
a.speak();Burada olan: new Animal(...) çağrısı bir obje yaratır, onun prototip'ini
Animal.prototype yapar. a.speak() çağrısında JavaScript önce a üzerinde
arar, yok, Animal.prototype'a bakar, bulur, çağırır.
Class altında olan budur
class Animal {
constructor(name) { this.name = name; }
speak() { return `${this.name} ses çıkardı`; }
}Tam olarak yukarıdaki function-tabanlı koda eşittir. class, sadece
sözdizimsel şeker.
Object.prototype — zincirin sonu
const arr = [1, 2, 3];
arr -> Array.prototype -> Object.prototype -> nullarr.toString() çağrısı:
arrüzerinde arar — yokArray.prototype— toString var, oradan kullanır- (Olmasaydı
Object.prototype'a bakacaktı)
Bu yüzden [].hasOwnProperty() çalışır — Object.prototype.hasOwnProperty'den
miras gelir.
Inheritance prototipte
class Dog extends Animal {
bark() { return "Hav"; }
}
const d = new Dog("Karabaş");
d.bark(); // 1. Dog.prototype'ta bulundu
d.speak(); // 1. Dog.prototype — yok
// 2. Animal.prototype — bulunduZincir: d -> Dog.prototype -> Animal.prototype -> Object.prototype -> null
Pratik metotlar
const obj = {};
obj.hasOwnProperty("x"); // sadece kendi mi?
"x" in obj; // zincir dahil her yerde mi?
Object.keys(obj); // sadece kendi enumerable
Object.getOwnPropertyNames(obj); // kendi tüm property
Object.getPrototypeOf(obj);
Object.setPrototypeOf(obj, başkaObje); // performans için kaçınObject.create
Belirli bir prototiple obje üretmek için:
const proto = {
greet() { return `Merhaba, ${this.name}`; }
};
const u = Object.create(proto);
u.name = "Furkan";
u.greet(); // "Merhaba, Furkan"Class'ın aşağı seviyedeki halidir.
Prototype pollution — güvenlik
// ❌ tehlikeli
const merge = (a, b) => Object.assign(a, b);
merge({}, JSON.parse('{ "__proto__": { "isAdmin": true } }'));
// Şimdi her objenin .isAdmin'i true!Kullanıcıdan gelen JSON'u doğrudan obje merge etme. Object.create(null)
ile prototip'siz objeler üret veya Map kullan.
Performans notu
- Property erişimi prototip zincirinden yapılır → derin zincir = yavaş
- Aynı obje şekli (shape) tutmak motorun optimize etmesine yardım eder
Object.setPrototypeOfruntime'da çağrılınca optimize edilen kodu geçersiz kılar → en başta belirle
JavaScript'te class yok — prototip zinciri var. Class sadece bunun
güzel sözdizimi. Class kullansan bile altta prototip vardır; bu yüzden
instanceof, Object.getPrototypeOf ve "this" davranışı tutarlıdır.