Menu

JavaScript Dizi Metotları: map, filter, reduce ve Dostları

for döngülerinin çoğunun yerini alan dizi metotları: map, filter, reduce, find, some, every. Hangileri diziyi değiştirir, hangileri yeni dizi döndürür?

Diziler Kendi Araç Kutusuyla Gelir

JavaScript dizileri, hazır metotlarla dolu zengin bir araç kutusuna sahiptir. for döngüsüyle yazacağınız şeylerin çoğu — değerleri dönüştürmek, bazılarını seçip ayıklamak, toplamını almak — tek satırda iş gören, okunması çok daha kolay ve birbiriyle güzelce zincirlenebilen bir metoda karşılık gelir.

Başlangıç seti üç metottan oluşur: map, filter ve reduce. Bu üçünü ve birkaç yakın akrabasını öğrendiğinizde, döngülerle şişmiş kodunuz bir bakışta anlaşılır hale gelir.

index.js
Output
Click Run to see the output here.

Her metot bir callback alıyor ve bir şey döndürüyor. Hiçbiri nums dizisini değiştirmedi — bunu erkenden kafaya kazımakta fayda var.

map: Her Elemanı Dönüştürmek

map metodu, verdiğin fonksiyonu dizinin her elemanı için çalıştırır ve dönen değerleri aynı uzunlukta yeni bir diziye toplar. Yani "her girdiye bir çıktı" istediğinde map kullanımı tam sana göre.

index.js
Output
Click Run to see the output here.

Callback fonksiyonu, ihtiyacın olursa ikinci argüman olarak index'i de alır: arr.map((item, i) => ...). Kullanmayacaksan görmezden gel.

Sık yapılan bir hata: dönen diziye ihtiyacın olmadığı halde refleks olarak map kullanmak. Amacın sadece her elemanı yazdırmak ya da veritabanına eklemekse, oraya forEach veya klasik bir döngü yakışır.

filter: Koşulu Sağlayanları Süz

filter metodu, her eleman için bir predicate — yani true ya da false döndüren bir fonksiyon — çalıştırır ve truthy değer dönenleri tutar. Yeni dizi ya aynı uzunlukta olur ya da daha kısa.

index.js
Output
Click Run to see the output here.

map ve filter birbirine doğal bir şekilde zincirlenir. Zinciri soldan sağa bir pipeline gibi okuyabilirsin:

index.js
Output
Click Run to see the output here.

Önce filter, sonra map uygula — böylece map yalnızca elemeyi geçenler üzerinde çalışır.

reduce: Diziyi Tek Bir Değere İndirgemek

reduce, bu üçlünün en esnek olanı. Ona bir indirgeyici fonksiyon (accumulator, item) => newAccumulator ve bir başlangıç değeri veriyorsun. Diziyi baştan sona dolaşıyor, her elemanı o ana kadarki akümülatörle birlikte fonksiyona veriyor ve sonunda akümülatörün ulaştığı değeri döndürüyor.

index.js
Output
Click Run to see the output here.

Sonucun illa bir sayı olması gerekmiyor. Bir nesne, başka bir dizi, bir string — ne istersen onu inşa edebilirsin:

index.js
Output
Click Run to see the output here.

İlk değeri (ikinci argümanı) her zaman ver. Vermezsen reduce, dizinin ilk elemanını başlangıç akümülatörü olarak kullanır; bu da boş dizilerde patlar ve çoğu zaman zaten istediğin davranışı vermez.

reduce güçlü bir metot ama işin mantığı karışınca okunması zorlaşabilir. Reducer fonksiyonun birkaç satırı geçiyorsa, sade bir for...of döngüsü genelde çok daha anlaşılır olur.

forEach: Yan Etkiler İçin, Dönüş Değeri Yok

forEach'i, geriye dizi döndürmeyen bir map gibi düşünebilirsin. Her eleman için bir şey yapmak istediğinde işe yarar — konsola yazdırmak, API çağırmak, DOM'u güncellemek gibi. Yeni bir koleksiyona ihtiyacın yoksa tam aradığın metot bu.

index.js
Output
Click Run to see the output here.

Bilmeniz gereken iki şey var:

  • forEach geriye undefined döner. Yani sonrasına .map() zincirleyemezsiniz.
  • forEach içinden break ile erken çıkış yapamazsınız. Erken çıkmanız gerekiyorsa for...of ya da some/every kullanın.

Kendinizi arr.forEach(x => results.push(transform(x))) yazarken bulduğunuz an, aslında yapmak istediğiniz şey map'tir.

find ve findIndex: Tek bir eleman yeter

find, koşulu sağlayan ilk elemanı döner; hiçbir eleman eşleşmezse undefined gelir. findIndex ise bu elemanın indeksini (bulamazsa -1) döner.

index.js
Output
Click Run to see the output here.

find, ilk eşleşmede durur. filter(...)[0] yazmaktan kaçının — bütün diziyi tarayıp geri kalanını boşuna çöpe atar.

some ve every: Diziye Evet/Hayır Sormak

some, dizide testten geçen en az bir eleman varsa true döner. every ise yalnızca tüm elemanlar testi geçerse true döner.

index.js
Output
Click Run to see the output here.

Her ikisi de kısa devre yapar — some ilk true değerinde durur, every ise ilk false değerinde. "Herhangi biri…" / "Hepsi…" sorularını cevaplamak için tam da aradığınız araçlar bunlar.

slice ve splice farkı: Kopyalamak mı, Kesmek mi?

İsimleri benzese de yaptıkları iş tamamen farklı.

slice(start, end) dizinin bir bölümünün yüzeysel (shallow) kopyasını döndürür. Orijinal diziye dokunmaz. end parametresi dahil değildir; yazmazsanız dizinin sonuna kadar gider.

index.js
Output
Click Run to see the output here.

splice(start, deleteCount, ...items) diziyi yerinde değiştirir. start indeksinden itibaren deleteCount kadar elemanı siler, istersen yerine yeni elemanlar ekler ve silinen elemanları geriye döndürür.

index.js
Output
Click Run to see the output here.

Hatırlatma: slice güvenlidir (kopya alır), splice ise diziyi yerinde ameliyat eder.

Diziyi Değiştiren ve Değiştirmeyen Metotlar

Bu ayrım gerçekten önemli. Paylaşılan bir diziyi farkında olmadan değiştiren kod, izini sürmesi en can sıkıcı hatalardan biri olabiliyor.

Diziyi değiştirenler (orijinali değiştirir, genelde başka bir şey döndürürler):

  • push, pop, shift, unshift
  • splice, sort, reverse
  • fill, copyWithin

Diziyi değiştirmeyenler (yeni bir dizi veya değer döner, orijinale dokunmaz):

  • map, filter, slice, concat
  • flat, flatMap
  • find, findIndex, some, every, includes, indexOf
  • reduce, reduceRight

Dikkat edilmesi gereken iki tane var: sort ve reverse. Masum görünürler ama sessiz sedasız diziyi değiştirirler. Sıralanmış bir kopyaya ihtiyacın varsa önce slice ile kopyala:

index.js
Output
Click Run to see the output here.

Modern JS'in bu metotların mutasyona yol açmayan ikizleri de var: toSorted, toReversed, toSpliced ve with. Bunlar yeni bir dizi döndürür, orijinaline dokunmaz. Güncel tüm runtime'larda destekleniyor — elinizin altındaysa tercih edin.

index.js
Output
Click Run to see the output here.

flat ve flatMap

flat metodu, iç içe geçmiş dizileri tek seviye düzleştirir (derinlik parametresi verirseniz daha fazlasını da yapabilir). flatMap ise aslında map işleminin ardından tek seviyelik bir flat uygulanmış hâlidir — her elemanın sıfır veya daha fazla çıktıya dönüşebildiği durumlarda oldukça kullanışlıdır.

index.js
Output
Click Run to see the output here.

flatMap, bir girdiden birden fazla çıktı üretirken araya flat() sokmadan işi tertemiz halleden metottur — yani öğeleri "genişletmenin" en şık yolu.

Hepsini Bir Araya Getirelim

Gerçek hayattan küçük bir örnek: Elimizde bir sipariş listesi var ve tamamlanmış, 50 doların üzerindeki siparişlerin toplam cirosunu hesaplamak istiyoruz:

index.js
Output
Click Run to see the output here.

Üç metot, tek bir işlem zinciri, hiçbir döngü takibi yok. Her adım ne yaptığını kendisi anlatıyor. İki filter çağrısını tek bir ifadede birleştirebilirsin elbette, ama ayrı bırakmak da gayet okunaklı — hatta hata ayıklarken bazen daha da rahat oluyor.

Sırada: Map ve Set

Diziler, sıralı veri dizilerini yönetmekte iyidir; ama anahtara göre hızlı erişim ya da benzersiz değerlerden oluşan bir koleksiyon gerektiğinde hantal kalırlar. JavaScript tam da bu iki iş için yerleşik iki veri yapısı sunuyor: Map ve Set. Sonraki sayfanın konusu işte bunlar.

Sıkça Sorulan Sorular

JavaScript'te map, filter ve reduce arasındaki fark nedir?

map her elemanı dönüştürür ve aynı uzunlukta yeni bir dizi döndürür. filter testten geçen elemanları tutar, genelde daha kısa yeni bir dizi döndürür. reduce ise dizinin üzerinden geçer ve onu tek bir değere indirger — bir toplam, bir nesne, başka bir dizi, ne kurarsan.

forEach ile map arasındaki fark ne?

forEach her eleman için fonksiyonu çalıştırır ve undefined döndürür — yani yan etkiler için kullanılır. map ise her eleman için fonksiyonu çalıştırır ve sonuçlardan oluşan yeni bir dizi döndürür. Dönüştürülmüş bir diziye ihtiyacın varsa map kullan. Sadece her elemanla bir iş yapacaksan ve sonuç umurunda değilse forEach (ya da for...of) yeterli.

Hangi dizi metotları orijinal diziyi değiştirir?

Diziyi değiştiren metotlar şunlar: push, pop, shift, unshift, splice, sort, reverse, fill ve copyWithin. Geri kalan herkes — map, filter, slice, concat, flat, flatMap, find, some, every, reduce — orijinal diziye dokunmaz, yeni bir değer döndürür.

slice mı splice mı kullanmalıyım?

slice(start, end) dizinin bir bölümünün yüzeysel bir kopyasını döndürür, orijinale dokunmaz. splice(start, deleteCount, ...items) ise diziyi yerinde değiştirir — eleman silip ekler ve silinenleri geri döndürür. Aklında kalsın: slice güvenlidir, splice ameliyat yapar.

Coddy ile kodlamayı öğren

BAŞLA