JavaScript dizi metotları, bir dizi üzerinde döngü yazmadan dönüştürme, süzme, arama ve özetleme yapmanızı sağlar. map() her öğeyi dönüştürüp aynı uzunlukta yeni bir dizi verir, filter() koşulu sağlayan öğeleri yeni bir diziye toplar, reduce() bütün diziyi tek bir değere indirger. find() ilk eşleşen öğeyi, some() ve every() ise birer true/false sonucu döndürür.

Bu yazıda en sık kullanılan dizi metotlarını çalışan örneklerle anlatıyor, hangi metodun asıl diziyi değiştirdiğini (mutating) hangisinin kopya döndürdüğünü bir tabloyla karşılaştırıyoruz. Yeni eklenen toSorted(), toReversed(), toSpliced() ve with() metotlarını da göreceksiniz. Konuya yeni başlıyorsanız önce JavaScript öğrenme rehberine göz atabilirsiniz.

Ortak imza: callbackFn ve thisArg

Ortak imza: callbackFn ve thisArg

MDN bu metotların çoğunu "iterative method" (yinelemeli metot) olarak gruplar. Hepsi aynı kalıbı izler: ilk argüman her öğe için çağrılan bir fonksiyondur (callbackFn), isteğe bağlı ikinci argüman ise bu fonksiyonun içindeki this değeridir (thisArg). Fonksiyon sırasıyla üç değer alır: o anki öğe (element), sırası (index) ve metodun çağrıldığı dizinin kendisi (array).

Arrow function kullanıyorsanız thisArg işe yaramaz, çünkü arrow function kendi this bağlamını oluşturmaz. Bu konunun ayrıntısı this anahtar kelimesi ve arrow function yazılarında. Callback kavramının kendisini merak ediyorsanız callback fonksiyon rehberine bakın.

map, filter ve reduce: üç temel dönüşüm

Aşağıdaki örnekte küçük bir ürün listesi üzerinde üç metodu sırayla kullanıyoruz:

javascript
const urunler = [
  { ad: "Klavye", fiyat: 750, stok: 12 },
  { ad: "Fare", fiyat: 300, stok: 0 },
  { ad: "Monitör", fiyat: 5200, stok: 4 },
];

// map: her öğeden yeni bir değer üret
const adlar = urunler.map((u) => u.ad);
console.log(adlar); // [ 'Klavye', 'Fare', 'Monitör' ]

// filter: koşulu sağlayanları tut
const stokta = urunler.filter((u) => u.stok > 0);
console.log(stokta.map((u) => u.ad)); // [ 'Klavye', 'Monitör' ]

// reduce: tek bir değere indir (başlangıç değeri 0)
const depoDegeri = urunler.reduce((toplam, u) => toplam + u.fiyat * u.stok, 0);
console.log(depoDegeri); // 29800

map() her zaman kaynak diziyle aynı uzunlukta bir dizi döndürür. filter() ise callback fonksiyonun truthy (doğru kabul edilen) değer döndürdüğü öğeleri toplar; hiçbir öğe geçmezse boş dizi döner. Truthy ve falsy kavramları için tip dönüşümü yazısına bakabilirsiniz.

reduce() biraz farklı çalışır: callback fonksiyon ilk parametre olarak bir "biriktirici" (accumulator) alır ve her adımda döndürdüğünüz değer bir sonraki adımın biriktiricisi olur. İkinci argüman olan başlangıç değerini (initialValue) verirseniz döngü ilk öğeden başlar. Vermezseniz dizinin ilk öğesi biriktirici olur ve döngü ikinci öğeden başlar. Ayrıca reduce(), diğer yinelemeli metotların aksine thisArg almaz.

javascript
try {
  [].reduce((a, b) => a + b);
} catch (e) {
  console.log(e.name + ": " + e.message);
}
// TypeError: Reduce of empty array with no initial value

console.log([].reduce((a, b) => a + b, 0)); // 0

find, findIndex, findLast: tek öğe aramak

find, findIndex, findLast: tek öğe aramak

find() koşulu sağlayan ilk öğeyi döndürür, hiçbiri sağlamazsa undefined verir. Öğenin kendisi yerine sırasını istiyorsanız findIndex() kullanın; bulamazsa -1 döner. findLast() ve findLastIndex() aynı işi dizinin sonundan başa doğru yapar. Bu metotlar sonucu bulduğu anda durur, dizinin geri kalanını gezmez.

javascript
const siparisler = [
  { no: 101, durum: "kargoda" },
  { no: 102, durum: "teslim" },
  { no: 103, durum: "kargoda" },
];

console.log(siparisler.find((s) => s.durum === "kargoda")); // { no: 101, durum: 'kargoda' }
console.log(siparisler.findLast((s) => s.durum === "kargoda").no); // 103
console.log(siparisler.findIndex((s) => s.no === 999)); // -1
console.log(siparisler.find((s) => s.no === 999)); // undefined

Yalnızca bir değerin dizide olup olmadığını soruyorsanız callback gerektirmeyen includes() daha sade bir seçimdir: [1, 2, 3].includes(2) doğrudan true döndürür.

some ve every: evet/hayır soruları

some() en az bir öğe koşulu sağlıyorsa true, every() bütün öğeler sağlıyorsa true döndürür. İkisi de sonucu kesinleştiği anda durur: some() ilk truthy sonuçta, every() ilk falsy sonuçta. Boş dizide davranışları matematikteki "en az biri vardır" ve "hepsi için" niceleyicileriyle aynıdır:

javascript
const puanlar = [72, 85, 90];
console.log(puanlar.some((x) => x < 50)); // false
console.log(puanlar.every((x) => x >= 70)); // true

// Boş dizide
console.log([].some((x) => x > 0)); // false
console.log([].every((x) => x > 0)); // true

flatMap: dönüştür ve bir seviye düzleştir

flatMap(), map() ardından derinliği 1 olan flat() çağırmakla aynı sonucu verir. MDN bunun iki ayrı çağrıdan biraz daha verimli olduğunu belirtir. Callback fonksiyon bir dizi döndürürse o dizinin öğeleri sonuca açılır; boş dizi döndürmek o öğeyi tamamen atlamak demektir. Bu sayede filtreleme ile dönüştürmeyi tek geçişte yapabilirsiniz:

javascript
const cumleler = ["merhaba dünya", "javascript dizi metotları"];
console.log(cumleler.flatMap((c) => c.split(" ")));
// [ 'merhaba', 'dünya', 'javascript', 'dizi', 'metotları' ]

const sayilar = [5, -3, 8, -1];
// Negatifleri at, pozitiflerin iki katını al
console.log(sayilar.flatMap((n) => (n < 0 ? [] : [n * 2]))); // [ 10, 16 ]

Diziyi değiştiren ve değiştirmeyen metotlar

Diziyi değiştiren ve değiştirmeyen metotlar: sort(), reverse(), splice(), push(v1, v2)

Yukarıdaki metotların hiçbiri asıl diziyi değiştirmez; MDN bunları "copying" (kopyalayan) metotlar olarak sınıflar. Buna karşılık push(), pop(), sort(), reverse(), splice() gibi metotlar diziyi yerinde (in place) değiştirir. Bir dizi birden çok yerde paylaşılıyorsa (örneğin bir React state değeri ya da fonksiyona gelen bir parametre) yerinde değişiklik beklenmedik hatalara yol açabilir. MDN, değiştiren her metot için değiştirmeyen bir karşılık listeler:

Diziyi değiştirenDeğiştirmeyen karşılıkNot
sort()toSorted()yeni dizi döner
reverse()toReversed()yeni dizi döner
splice()toSpliced()silinenleri değil yeni diziyi döner
push(v1, v2)concat([v1, v2])push yeni uzunluğu döner
pop()slice(0, -1)pop çıkan öğeyi döner
shift()slice(1)shift çıkan öğeyi döner
unshift(v1, v2)toSpliced(0, 0, v1, v2)unshift yeni uzunluğu döner
arr[i] = vwith(i, v)with yeni dizi döner
fill(), copyWithin()tek metotlu karşılık yokönce [...arr] ile kopyalayın

with() satırı MDN tablosunda yer almaz, ancak aynı "copying" ailesindendir ve tek bir indeksi değiştirilmiş yeni bir dizi döndürür. Aşağıdaki örnek farkı gösteriyor:

javascript
const notlar = [40, 100, 1, 5];

const sirali = notlar.toSorted((a, b) => a - b);
console.log(sirali); // [ 1, 5, 40, 100 ]
console.log(notlar); // [ 40, 100, 1, 5 ]  (asıl dizi aynı)

console.log(notlar.with(0, 99)); // [ 99, 100, 1, 5 ]
console.log(notlar.toReversed()); // [ 5, 1, 100, 40 ]

notlar.sort((a, b) => a - b); // yerinde sıralar
console.log(notlar); // [ 1, 5, 40, 100 ]

Kopyalar sığdır (shallow copy)

Kopyalayan metotlar yalnızca dizinin kendisini yeniden oluşturur. Dizi nesneler içeriyorsa yeni dizi aynı nesnelere işaret eder; bir nesnenin alanını değiştirdiğinizde değişiklik iki dizide de görünür. Sayı, metin gibi primitive değerler ise değer olarak kopyalanır.

javascript
const kullanicilar = [{ ad: "Ayşe", yas: 31 }, { ad: "Can", yas: 24 }];
const yasaGore = kullanicilar.toSorted((a, b) => a.yas - b.yas);

yasaGore[0].ad = "Can Y.";
console.log(kullanicilar[1].ad); // Can Y.
console.log(yasaGore[0] === kullanicilar[1]); // true

Nesneleri de bağımsız kopyalamak istiyorsanız spread sözdizimi ile her öğeyi ayrı kopyalayabilir (arr.map((o) => ({ ...o }))) ya da derin kopya için structuredClone() kullanabilirsiniz.

Metot özet tablosu

MetotDöndürdüğüErken durur muDiziyi değiştirir mi
mapaynı uzunlukta yeni dizihayırhayır
filterkoşulu sağlayanlardan yeni dizihayırhayır
reducetek bir değerhayırhayır
find / findLastöğe ya da undefinedevethayır
findIndexindeks ya da -1evethayır
sometrue / falseevet (ilk truthy)hayır
everytrue / falseevet (ilk falsy)hayır
flatMapbir seviye düzleşmiş yeni dizihayırhayır
forEachundefinedhayırhayır
sortaynı dizi (sıralanmış)yinelemeli değilevet

Sık yapılan hatalar

Süslü parantezli arrow function içinde return unutmak

Arrow function gövdesini süslü paranteze alırsanız değer döndürmek için return yazmanız gerekir. Yazmazsanız map() her öğe için undefined üretir:

javascript
console.log([1, 2, 3].map((x) => { x * 2; })); // [ undefined, undefined, undefined ]
console.log([1, 2, 3].map((x) => x * 2)); // [ 2, 4, 6 ]

map sonucunu kullanmamak

map() yeni bir dizi oluşturur. Dönen diziyi hiçbir yerde kullanmıyorsanız MDN bunu bir anti-pattern sayar; yan etki için forEach() ya da for...of döngüsü daha doğru bir tercihtir.

map içine doğrudan parseInt vermek

map() callback fonksiyona üç argüman geçirir. parseInt ise ikinci argümanı sayı tabanı (radix) olarak yorumlar. Sonuç şaşırtıcıdır:

javascript
console.log(["1", "2", "3"].map(parseInt)); // [ 1, NaN, NaN ]
console.log(["1", "2", "3"].map((s) => parseInt(s, 10))); // [ 1, 2, 3 ]
console.log(["1", "2", "3"].map(Number)); // [ 1, 2, 3 ]

Gezinirken diziyi değiştirmek

Yinelemeli metotlar dizinin uzunluğunu döngü başlamadan önce kaydeder. Callback içinde diziye öğe eklerseniz yeni öğeler ziyaret edilmez, henüz gezilmemiş bir öğeyi silerseniz o öğe atlanır. MDN bu tür eşzamanlı değişikliklerin anlaşılması zor kod ürettiğini vurgular; callback içinde kaynak diziye dokunmayın.

Sık Sorulan Sorular

map ile forEach arasındaki fark nedir?

map() callback sonuçlarından yeni bir dizi oluşturup döndürür. forEach() ise her öğe için fonksiyonu çalıştırır ve undefined döndürür. Yeni bir diziye ihtiyacınız varsa map(), yalnızca yan etki (loglama, dışarıya yazma) istiyorsanız forEach() kullanın.

Bu metotlar async fonksiyonları bekler mi?

Hayır. map() bir async callback ile çağrılırsa sonuç Promise dizisi olur; bunları beklemek için Promise.all() kullanılır. Ayrıntı için async/await yazısına bakın.

toSorted() her ortamda var mı?

toSorted(), toReversed(), toSpliced() ve with() görece yeni metotlardır. Bu yazıdaki örnekler Node.js 24 üzerinde çalıştı. Eski tarayıcıları hedefliyorsanız MDN uyumluluk tablosuna bakın ya da [...arr].sort() gibi bir kopya üzerinden çalışın.

Dizi yerine nesne ya da Map üzerinde aynı işlemleri yapabilir miyim?

Düz nesnelerde bu metotlar yoktur; önce Object.entries() ile diziye çevirip sonra Object.fromEntries() ile geri dönüştürebilirsiniz. Bu kalıp Object metotları yazısında anlatılıyor. Anahtar-değer koleksiyonları için Map ve Set yazısına da bakabilirsiniz.

Marka adları sahiplerine aittir. Bu yazı bağımsız bir teknik rehberdir; adı geçen kuruluşlarla bayilik veya ortaklık ilişkisi bulunduğu anlamına gelmez.

İlgili içerikler: JavaScript öğrenme rehberi · Object metotları · Destructuring ve spread · Callback fonksiyonlar · Map, Set ve WeakMap