Giriş
Bu rehber, JavaScript başlangıç kodları bağlamında diziler ve objeler üzerinde sık kullanılan fonksiyonel yaklaşımları — map, filter, reduce — ile obje manipülasyonunda kullanılan spread operatörü ve Object.assign kullanımını örneklerle anlatır. Amaç, hem kavramsal anlayış sağlamak hem de gerçek dünya görevleri için pratik kod şablonları sunmaktır.
Tanımlar ve örnekler için başvurduğum rehberler arasında Emre Demir'in yazısı ve Web Tasarım ve Kodlama’nın ilgili sayfası vardır; detaylı açıklamalar için bkz. Emre Demir ve Web Tasarım ve Kodlama. Diğer faydalı kaynaklar: Medium ve Ichi Pro rehberleri.
Temel kavramlar: map, filter, reduce
map — dizi elemanlarını dönüştürme
map, dizinin her elemanı için bir dönüşüm uygular ve aynı uzunlukta, yeni bir dizi döndürür. Orijinal dizi değişmez; dönüşüm fonksiyonu her eleman için çağrılır (eleman, indeks, orijinal dizi argümanlarıyla).
Örnek:
const numbers = [1, 2, 3, 4];
const doubled = numbers.map(n => n * 2); // [2, 4, 6, 8]
map hakkında daha ayrıntılı tanım ve örnekler için Emre Demir kaynağına bakabilirsiniz.
filter — koşula göre seçim
filter, dizinin her elemanını verilen koşula göre test eder ve koşulu sağlayan elemanlardan yeni bir dizi döndürür. Yine orijinal dizi değişmez.
Örnek:
const evens = numbers.filter(n => n % 2 === 0); // [2, 4]
reduce — birleştirme ve indirgeme
reduce, dizinin elemanlarını tek bir değere indirgemek için kullanılır: toplam, çarpım, nesne map'i oluşturma, gruplayıcılar vb. Bir accumulator (kümülatör) taşınır ve her adımda güncellenir. Genellikle ikinci argüman olarak başlangıç değeri (initial value) verilir.
Örnek (toplam):
const sum = numbers.reduce((acc, n) => acc + n, 0); // 10
Reduce ve başlangıç değeriyle ilgili uyarılar ve örnekler için şu kaynakları inceleyebilirsiniz: Medium, Ichi Pro.
Pratik örnekler: adım adım
Örnek 1 — Sadece e-posta adreslerini almak (map)
Senaryo: Kullanıcı objelerinden yalnızca e-posta adreslerini bir diziye almak istiyoruz.
const users = [{ name: 'Ali', email: 'ali@example.com' },{ name: 'Ayşe', email: 'ayse@example.com' }];
const emails = users.map(u => u.email); // ['ali@example.com', 'ayse@example.com']
Örnek 2 — Aktif kullanıcıların isimleri (filter + map zinciri)
Senaryo: Sadece active olan kullanıcıların isimlerini bir dizide toplamak.
const activeNames = users.filter(u => u.active).map(u => u.name);
Zincirleme kullanım, okunabilirliği artırır; ancak performans açısından ara diziler oluşturur (aşağıda bununla ilgili notlar var).
Örnek 3 — Yaş toplamı ve gruplayıcı (reduce)
Toplam yaş:
const totalAge = users.reduce((acc, u) => acc + (u.age || 0), 0);
Kullanıcıları role göre gruplamak:
const grouped = users.reduce((acc, user) => {
const key = user.role || 'unknown';
if (!acc[key]) acc[key] = [];
acc[key].push(user);
return acc;
}, {});
Örnek 4 — Frekans sayacı (reduce ile)
Bir dizi içindeki etiketlerin kaç kez geçtiğini saymak:
const tags = ['js','css','js','html'];
const freq = tags.reduce((acc, t) => { acc[t] = (acc[t] || 0) + 1; return acc; }, {}); // { js: 2, css: 1, html: 1 }
Objelerle çalışmak: spread ve Object.assign
Objeleri kopyalamak veya birleştirmek için iki sık kullanılan yöntem vardır: spread operatörü ({ ...obj }) ve Object.assign(). Her ikisi de yüzeysel (shallow) kopya oluşturur; iç içe (nested) objeler referans olarak taşınır.
Örnek kopyalama ve birleştirme:
const original = { a: 1, nested: { b: 2 } };
const copy = { ...original }; // shallow copy
const merged = Object.assign({}, original, { c: 3 });
Önemli not: Eğer nested bir obje içeriğini değiştirdiğinizde, hem orijinal hem de kopya etkilenir çünkü iç obje referans olarak paylaşılır. Derin kopya (deep clone) ihtiyaçlarında basit yöntem olarak JSON.parse(JSON.stringify(obj)) kullanılabilir, ancak bu yöntem Date, RegExp, fonksiyon gibi özel türleri korumaz. Modern ortamlarda ayrıca derin kopya için farklı yaklaşımlar bulunmaktadır; kullanım senaryonuza göre en uygun yöntemi seçin.
Performans ve en iyi uygulamalar
- map, filter ve reduce fonksiyonları her biri dizi üzerinde tam bir geçiş (iteration) yapar. Zincirleme map().filter().map() kullanımı okunabilirliği artırır ama ara diziler yaratır; çok büyük dizilerde bellek ve hız maliyeti olabilir.
- Eğer aynı anda filtreleme ve toplama yapmak istiyorsanız, reduce ile tek geçişte hem süzme hem toplama yapabilirsiniz (örnek: aktif kullanıcıların yaş toplamı). Bu, bazı durumlarda daha hızlıdır ve ara dizileri ortadan kaldırır.
- Callback fonksiyonları içinde orijinal diziyi değiştirmekten kaçının. Fonksiyonel yöntemlerin avantajı tarafsız (pure) dönüşümlere izin vermesidir; bu, hataları azaltır ve test yazmayı kolaylaştırır.
- Gerçek performans ihtiyaçlarında ölçüm (profiling) yapın; mikro optimizasyonlar yerine okunabilirliği ve bakım kolaylığını önceliklendirin.
Sık yapılan hatalar ve çözümleri
- arrow-return hatası: Küçük kenar: arr.map(x => { x * 2 }) ifadesi undefined döndürür; doğru kullanım arr.map(x => x * 2) veya arr.map(x => { return x * 2; }) şeklindedir.
- reduce başlangıç değeri eksikliği: Boş dizilerde reduce çağrıldığında başlangıç değeri verilmezse hata alınır; genelde ikinci argüman olarak başlangıç değeri verin.
- yan etki için map kullanmak: Eğer amaç sadece döngüsel yan etki yapmaksa forEach tercih edilir; map yeni bir dizi oluşturur.
- Object.assign ve spread'ın yüzeysel kopya olduğunu unutmamak: Nested objeler için derin kopya stratejisi uygulayın.
Hızlı kontrol listesi (checklist)
- Transformasyon için map, seçim için filter, birleştirme/hesaplama için reduce kullanın.
- Map kullanıyorsanız dönüş değeri döndürdüğünüzden emin olun.
- Reduce için daima başlangıç değeri verin; özellikle boş diziler için.
- Objeyi kopyalarken spread/Object.assign ile sadece yüzeysel kopya alındığını unutmayın.
- Zincirleme işlemlerin okunabilirlik vs. performans dengesini değerlendirin.
- Kodunuzu küçük örneklerle test ederek beklenen çıktıyı doğrulayın.
Özet
map, filter ve reduce, JavaScript'te diziler üzerinde sık başvurulan, okunabilir ve fonksiyonel yaklaşımlar sunan metodlardır. Obje manipülasyonunda spread ve Object.assign hızlı ve okunabilir çözümler sağlar; ancak shallow copy davranışı ve reduce başlangıç değeri gibi ayrıntılar göz önünde bulundurulmalıdır. Daha fazla teknik detay ve örnekler için Emre Demir ve Web Tasarım ve Kodlama kaynaklarına bakabilirsiniz.
Bu rehberdeki kod örnekleri öğretim amaçlıdır; üretim ortamında kullanmadan önce kendi testlerinizi yapmanızı öneririm.
Kaynaklar:
https://www.emredemir.tech/blog/map-reduce-filter
https://www.webtasarimivekodlama.com/javascript-dizi-eleman-ekleme-ve-silme
https://medium.com/@BerkayKulak/javascript-map-filter-reduce-fonksiyonlar%C4%B1-a6dec63934f2
https://ichi.pro/tr/javascript-te-map-filter-ve-reduce-54854408496733