JavaScript, web geliştirme dünyasının vazgeçilmez bir parçası haline geldi. Son on yılda frontend teknolojilerindeki gelişmelerle birlikte, neredeyse her web projesi az ya da çok JavaScript kodu içeriyor. Ancak bu yaygın kullanım, beraberinde bazı tipik hataları da getiriyor. 15 yılı aşkın web geliştirme deneyimim boyunca, hem kendi projelerimde hem de danışmanlık verdiğim şirketlerde aynı JavaScript hatalarının tekrar tekrar yapıldığını gözlemledim.
Bu hatalar bazen küçük can sıkıcı sorunlara neden olurken, bazen de büyük performans sorunları veya güvenlik açıkları yaratabiliyorlar. İyi haber şu ki, bu hataların çoğu, temel prensipleri anladığımızda kolayca çözülebiliyor. Bu yazıda, özellikle kurumsal web siteleri ve e-ticaret platformları geliştiren ekiplerin sıklıkla karşılaştığı JavaScript hatalarını ve bunların pratik çözümlerini ele alacağız.
Değişken Tanımlama ve Kapsam (Scope) Sorunları
JavaScript’te en sık karşılaşılan hatalardan biri, değişken tanımlama ve kapsam ile ilgili yanlış anlayışlardan kaynaklanır. Özellikle var, let ve const arasındaki farkları anlamadığımızda, kodumuzda beklenmeyen davranışlar ortaya çıkabilir.
Yıllarca geliştirici ekipleriyle çalışırken gördüğüm en yaygın hata, var anahtar kelimesinin JavaScript’teki hoisting (yukarı çekme) özelliği nedeniyle oluşan karışıklıklardır. Bir değişkeni var ile tanımladığımızda, bu tanımlama işlevi bloğunun en üstüne taşınır, ancak değeri taşınmaz.
Yaygın Hata: Yanlış Değişken Tanımlama
Aşağıdaki örneğe bakalım:
function orderProcessor() {
console.log(productName); // undefined, hata vermez
if (true) {
var productName = "Akıllı Telefon";
}
console.log(productName); // "Akıllı Telefon"
}
Bu kod ilk bakışta mantıksız görünebilir. İlk console.log çağrısında productName değişkeni henüz tanımlanmamış olmasına rağmen hata vermez, sadece “undefined” döndürür. Bunun nedeni, var ile tanımlanan değişkenlerin hoisting özelliğidir.
Çözüm: let ve const Kullanımı
Modern JavaScript’te (ES6 ve sonrası) bu sorunu çözmek için let ve const anahtar kelimeleri sunuldu. Bu değişkenler blok kapsamlıdır ve hoisted edilmezler:
function orderProcessor() {
// console.log(productName); // Hata verir: ReferenceError
if (true) {
let productName = "Akıllı Telefon";
console.log(productName); // "Akıllı Telefon"
}
// console.log(productName); // Hata verir: ReferenceError
}
Kurumsal projelerde değişken tanımlama için şu basit kuralı öneriyorum:
- const: Değeri değişmeyecek değişkenler için (varsayılan seçiminiz olmalı)
- let: Değeri değişecek değişkenler için
- var: Mümkün olduğunca kaçının (eski kodlarda uyumluluk için gerekmedikçe)
Asenkron İşlemlerde Karşılaşılan Zorluklar
JavaScript’in en güçlü yönlerinden biri asenkron programlama yapabilme kabiliyetidir, ancak bu aynı zamanda en çok hata yapılan alanlardan biridir. Özellikle API çağrıları, kullanıcı etkileşimleri ve zamanlayıcılar gibi asenkron işlemlerde sorunlar ortaya çıkıyor.
Yaygın Hata: Callback Hell
E-ticaret sitelerinde sıklıkla gördüğüm bir hata, iç içe geçmiş callback fonksiyonları (callback hell olarak da bilinir) kullanmaktır:
fetchUserData(userId, function(userData) {
getCartItems(userData.cartId, function(cartItems) {
calculateDiscount(cartItems, function(discount) {
applyPromoCode(discount, promoCode, function(finalPrice) {
displayCheckout(finalPrice, function() {
// Ve böylece devam eder...
});
});
});
});
});
Bu yaklaşım, kodu okunması, bakımı ve hata ayıklaması zor hale getirir. Ayrıca hata yönetimi de oldukça karmaşıklaşır.
Çözüm: Promise ve async/await Kullanımı
Modern JavaScript’te Promise’ler ve async/await sözdizimi, bu sorunu çok daha zarif bir şekilde çözmeye olanak tanır:
async function processCheckout(userId, promoCode) {
try {
const userData = await fetchUserData(userId);
const cartItems = await getCartItems(userData.cartId);
const discount = await calculateDiscount(cartItems);
const finalPrice = await applyPromoCode(discount, promoCode);
await displayCheckout(finalPrice);
return finalPrice;
} catch (error) {
console.error("Ödeme işlemi sırasında hata:", error);
notifyUser("Ödeme işlemi sırasında bir sorun oluştu.");
}
}
Bu yaklaşım, kodun daha doğrusal ve okunabilir olmasını sağlar, ayrıca hata yönetimi de try/catch blokları ile daha kolay hale gelir. Kurumsal projelerde, özellikle e-ticaret sistemlerinde, bu tarz asenkron işlem zincirlerini async/await ile yazmak, kodun bakımını ve ölçeklenebilirliğini önemli ölçüde artırır.
DOM Manipülasyonu ve Performans Sorunları
Web sitelerinde JavaScript’in en yaygın kullanım alanlarından biri DOM manipülasyonudur. Ancak bu, performans sorunlarına neden olabilecek bir alandır. Özellikle WordPress tabanlı kurumsal sitelerde veya e-ticaret platformlarında, yanlış DOM manipülasyonu teknikleri ciddi yavaşlamalara yol açabilir.
Yaygın Hata: Sık DOM Güncellemeleri
Aşağıdaki kod, bir ürün listesine 100 yeni ürün eklemek istediğimizde yaygın olarak yapılan bir hatayı gösterir:
function addProducts(products) {
const productList = document.getElementById('product-list');
products.forEach(product => {
// Her seferinde DOM'u güncelliyor - performans sorunu
productList.innerHTML += `
<div class="product">
<h4>${product.name}</h4>
<p>${product.price} TL</p>
</div>
`;
});
}
Bu yaklaşımda, her ürün eklendiğinde DOM yeniden işlenir (reflow ve repaint olayları tetiklenir), bu da özellikle büyük listelerde performans sorunlarına neden olur.
Çözüm: Fragment Kullanımı ve Toplu Güncellemeler
Daha verimli bir yaklaşım, DOM’a yapılacak değişiklikleri bir fragment içinde toplamak ve sonra tek seferde uygulamaktır:
function addProducts(products) {
const productList = document.getElementById('product-list');
const fragment = document.createDocumentFragment();
products.forEach(product => {
const productDiv = document.createElement('div');
productDiv.className = 'product';
productDiv.innerHTML = `
<h4>${product.name}</h4>
<p>${product.price} TL</p>
`;
fragment.appendChild(productDiv);
});
// Tüm değişiklikleri tek seferde DOM'a uygula
productList.appendChild(fragment);
}
Bu teknik, büyük e-ticaret sitelerinde ürün listelerini render ederken önemli performans iyileştirmeleri sağlar. Gerçek bir müşteri projemizde, bu optimizasyon sayesinde ürün listeleme sayfasının yüklenme süresini %40 oranında azalttık.
Bellek Sızıntıları ve Kaynak Yönetimi
JavaScript’in otomatik çöp toplama (garbage collection) mekanizması olmasına rağmen, bellek sızıntıları hala yaygın bir sorundur. Özellikle uzun süre açık kalan ve dinamik içerikle sürekli güncellenen kurumsal web uygulamalarında, bellek sızıntıları kullanıcı deneyimini olumsuz etkileyebilir.
Yaygın Hata: Kapatılmayan Event Listener’lar
Single Page Application’larda (SPA) en sık gördüğüm bellek sızıntısı kaynağı, bileşenler kaldırıldığında event listener’ların temizlenmemesidir:
function initProductPage() {
const addToCartButton = document.getElementById('add-to-cart');
addToCartButton.addEventListener('click', function() {
addItemToCart(productId);
});
// Sayfa değiştiğinde olay dinleyicisi kaldırılmıyor
}
Kullanıcı sayfalar arasında gezindikçe, eski olay dinleyicileri bellekte kalır ve kaynakları tüketmeye devam eder.
Çözüm: Temizleme Fonksiyonları Kullanmak
Modern JavaScript framework’leri (React, Vue, Angular) bu sorunu genellikle otomatik olarak çözer, ancak vanilla JavaScript kullanıyorsanız, temizleme fonksiyonları eklemeniz gerekir:
function initProductPage() {
const addToCartButton = document.getElementById('add-to-cart');
function handleAddToCart() {
addItemToCart(productId);
}
addToCartButton.addEventListener('click', handleAddToCart);
// Temizleme fonksiyonu döndür
return function cleanUp() {
addToCartButton.removeEventListener('click', handleAddToCart);
};
}
const cleanUpFunction = initProductPage();
// Sayfa değiştiğinde:
cleanUpFunction();
Bu yaklaşım, özellikle AJAX ile içerik yüklenen WordPress tabanlı kurumsal sitelerde bellek kullanımını optimize etmenin etkili bir yoludur. Bir finans sektörü müşterimizin dashboard uygulamasında bu tekniği uyguladığımızda, uzun süreli kullanımda tarayıcının bellek tüketimini %30’a kadar azaltabildik.
Sonuç ve En İyi Pratikler
JavaScript hataları, web projelerinizin performansını, güvenilirliğini ve bakım kolaylığını önemli ölçüde etkileyebilir. Bu yazıda ele aldığımız en yaygın hataların farkında olmak ve bunlardan kaçınmak için bazı temel ilkeleri uygulamak, kodunuzun kalitesini artıracaktır.
Kurumsal projeleriniz için JavaScript geliştirmede önerdiğim en iyi pratikler şunlardır:
- var yerine let ve const kullanın, mümkün olduğunca değişmez (immutable) veri yapıları tercih edin
- Callback yapıları yerine Promise ve async/await tercih edin
- DOM manipülasyonlarını toplu halde yapın ve gereksiz render işlemlerinden kaçının
- Olay dinleyicileri ve diğer kaynakları kullanımdan sonra temizleyin
- Kod kalitesini artırmak için ESLint gibi statik kod analiz araçları kullanın
- Düzenli kod incelemeleri (code review) yapın ve ekip içinde bilgi paylaşımını teşvik edin
Bu pratikleri web projelerinize dahil etmek, sadece hataları azaltmakla kalmaz, aynı zamanda sitenizin performansını iyileştirir ve SEO çalışmalarınıza da olumlu katkı sağlar. Çünkü unutmayın, hızlı ve hatasız çalışan bir web sitesi, hem kullanıcı deneyimini iyileştirir hem de arama motorları tarafından daha üst sıralarda gösterilme şansını artırır.
Sizin de JavaScript ile ilgili karşılaştığınız zorluklar veya çözümleriniz varsa, yorum bölümünde paylaşabilirsiniz. Web geliştirme ve WordPress konularında daha fazla ipucu ve rehber için blog yazılarımı takip etmeyi unutmayın!