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

Performans ve Best Practices

Hızlı, hafıza dostu ve sürdürülebilir JavaScript yazma rehberi.

Önce ölç, sonra optimize et

Tahmin yerine performance API kullan:

performance.mark("start");
isYap();
performance.mark("end");
performance.measure("isYap", "start", "end");
 
console.log(performance.getEntriesByName("isYap"));

Tarayıcı DevTools → Performance sekmesi de güçlü bir araçtır.

Algoritma > mikro-optimizasyon

// O(n²) — büyüyünce can sıkar
for (const item of list) {
  if (otherList.includes(item)) { ... }
}
 
// O(n) — çok daha hızlı
const set = new Set(otherList);
for (const item of list) {
  if (set.has(item)) { ... }
}

map vs for micro-bench'iyle uğraşmadan önce algoritmayı düzelt.

Memoization

Aynı argümanlarla çağrılan saf fonksiyonun sonucunu cache'le:

function memoize(fn) {
  const cache = new Map();
  return (...args) => {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = fn(...args);
    cache.set(key, result);
    return result;
  };
}
 
const fibCache = memoize(function fib(n) {
  return n <= 1 ? n : fib(n - 1) + fib(n - 2);
});

Lazy yükleme

Modülleri ihtiyaç olunca yükle:

button.onclick = async () => {
  const { showModal } = await import("./heavyModal.js");
  showModal();
};

Bundle boyutunu küçük tutar.

DOM erişimini topla

DOM okuma/yazma layout reflow tetikler. Birden fazla işlem varsa toplu yap:

// ❌ kötü: her satırda reflow
items.forEach((item) => {
  const div = document.createElement("div");
  div.textContent = item;
  list.appendChild(div);
});
 
// ✅ iyi: fragment ile tek seferde
const frag = document.createDocumentFragment();
items.forEach((item) => {
  const div = document.createElement("div");
  div.textContent = item;
  frag.appendChild(div);
});
list.appendChild(frag);

Memory leak'ten kaçın

Yaygın leak kaynakları:

  1. Tutulan event listener'lar — component kaldırıldı ama listener document'ta kaldı
  2. Closure'da büyük data — arrow function dış scope'tan büyük objeyi referans tutuyor
  3. setInterval / setTimeout unutulduğunda
  4. Global cache'lerWeakMap kullan, sonsuz büyümesin
// Cleanup şart
const ctrl = new AbortController();
window.addEventListener("scroll", h, { signal: ctrl.signal });
// component unmount → ctrl.abort()

Saf fonksiyonlar

  • Test edilmesi kolay
  • Cache'lenebilir
  • Paralel çalıştırılabilir
  • Hata ayıklamak kolay
// ❌ saf değil
let total = 0;
function add(n) { total += n; }
 
// ✅ saf
function add(state, n) { return state + n; }

Erken return (early exit)

// ❌ iç içe
function calc(user) {
  if (user) {
    if (user.active) {
      // ...iş
    }
  }
}
 
// ✅ guard clause
function calc(user) {
  if (!user) return;
  if (!user.active) return;
  // ...iş
}

Type-safety: TypeScript düşün

JavaScript'in dinamik yapısı küçük projede süpriz, büyük projede ızdırap. 3+ kişiyle çalıştığın bir kod tabanın varsa TypeScript'e geç. Aynı dili yazmaya devam edersin, ekstra olarak runtime hatalarının çoğunu compile time'da yakalarsın.

Eslint + Prettier

  • ESLint — bug'a açık pattern'leri yakalar
  • Prettier — formatlama tartışmasını bitirir

Yeni projeye otomatik kur:

npm i -D eslint prettier

Erken optimizasyona düşme

Knuth'un sözü: "Erken optimizasyon tüm kötülüklerin anasıdır."

Önce çalışan, okunabilir kod yaz. Sonra ölç. Sonra darboğazı düzelt. İçinden geçen veri yolu zaten 10ms'den hızlıysa, micro-optimization uğraşmaya değmez.

📋Özet
  1. Algoritmayı düzelt
  2. Lazy yükle
  3. DOM erişimini topla
  4. Memory leak'i kapat
  5. Saf fonksiyon yaz
  6. Ölçmeden optimize etme

Bu sıra önemli.

Bu bölümü bitirdin mi?

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

Paylaş