JavaScript: Başlangıçtan İleri Seviyeye
Bölüm 23 / 313 dk okuma

Prototip Zinciri

JavaScript'in kalıtım modelinin temeli. class'ın altında ne olduğu.

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;  // true

Function.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 -> null

arr.toString() çağrısı:

  1. arr üzerinde arar — yok
  2. Array.prototype — toString var, oradan kullanır
  3. (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 — bulundu

Zincir: 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çın

Object.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.setPrototypeOf runtime'da çağrılınca optimize edilen kodu geçersiz kılar → en başta belirle
📋Özet

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.

Bu bölümü bitirdin mi?

İlerlemen tarayıcıda saklanır, eğitim listesinde görünür.

Paylaş