Destructuring, bir dizinin öğelerini ya da bir nesnenin özelliklerini tek satırda ayrı değişkenlere açmanızı sağlayan JavaScript sözdizimidir: const [a, b] = dizi veya const { ad, yas } = kisi. Spread sözdizimi (...) ise tersini yapar; bir diziyi, metni ya da nesneyi yeni bir dizi, nesne veya fonksiyon argüman listesinin içine açar. Aynı üç nokta, destructuring tarafında kullanıldığında "rest" adını alır ve geri kalan öğeleri toplar.

Bu yazıda dizi ve nesne destructuring, varsayılan değerler, yeniden adlandırma, iç içe kalıplar, spread ve rest kullanımını Node.js 24 ile denenmiş örneklerle anlatıyoruz. Sonda en çok gözden kaçan konuya, spread ile yapılan kopyaların sığ olmasına ayrıca değiniyoruz. Genel yol haritası için JavaScript öğrenme rehberine bakabilirsiniz.

Dizi destructuring

Dizi destructuring

Dizi kalıbında değişkenler sıraya göre eşleşir. Virgül bırakarak öğe atlayabilir, kaynakta karşılığı olmayan değişkenlere undefined atanmasını bekleyebilirsiniz. Geçici değişken kullanmadan iki değişkenin değerini takas etmek de bu sözdizimiyle yapılır:

javascript
const renkler = ["kırmızı", "yeşil", "mavi"];

const [ilk, ikinci] = renkler;
console.log(ilk, ikinci); // kırmızı yeşil

const [, , ucuncu, dorduncu] = renkler;
console.log(ucuncu, dorduncu); // mavi undefined

// Takas
let a = 1;
let b = 3;
[a, b] = [b, a];
console.log(a, b); // 3 1

Dizi destructuring aslında yalnızca dizilerle değil, her iterable ile çalışır: metin, Map ve Set ya da generator çıktısı da açılabilir. Örneğin const [ilkHarf] = "Ankara" değişkene "A" atar.

Nesne destructuring, yeniden adlandırma ve varsayılan değer

Nesne kalıbında eşleşme sıraya göre değil, özellik adına göre yapılır. { ozellik: yeniAd } yazımı değeri farklı adlı bir değişkene alır, = deger eki ise varsayılan değer tanımlar. İkisi birlikte de kullanılabilir:

javascript
const yanit = { durum: 200, veri: { id: 7, ad: "Deniz" } };

const { durum, mesaj = "yok" } = yanit;
console.log(durum, mesaj); // 200 yok

// Yeniden adlandırma
const { durum: kod } = yanit;
console.log(kod); // 200

// Yeniden adlandırma + varsayılan değer
const { zamanAsimi: sure = 30 } = yanit;
console.log(sure); // 30

Varsayılan değer yalnızca undefined için çalışır

MDN'nin açıkça belirttiği bir ayrıntı: varsayılan değer, özellik hiç yoksa ya da değeri undefined ise kullanılır. Değer null ise varsayılan devreye girmez. API'den null gelebilecek alanlarda bu fark önemlidir; nullish coalescing (??) operatörü null değerini de kapsar.

javascript
const { x = 5 } = { x: undefined };
const { y = 5 } = { y: null };
console.log(x, y); // 5 null

const { z } = { z: null };
console.log(z ?? 5); // 5

Varsayılan değer bir ifade olabilir ve yalnızca gerektiğinde çalıştırılır. Özellik doluysa varsayılan ifadedeki fonksiyon hiç çağrılmaz.

İç içe destructuring

İç içe destructuring

Kalıplar iç içe yazılabilir; dizi ve nesne kalıplarını karıştırmak da serbesttir. Aşağıda bir API yanıtının derinindeki alanları tek ifadede alıyoruz:

javascript
const siparis = {
  no: 5012,
  musteri: { ad: "Selin", adres: { il: "İzmir" } },
  kalemler: [{ urun: "Kitap", adet: 2 }, { urun: "Kalem", adet: 10 }],
};

const {
  musteri: { ad, adres: { il } },
  kalemler: [{ urun: ilkUrun }],
} = siparis;

console.log(ad, il, ilkUrun); // Selin İzmir Kitap

Burada yalnızca ad, il ve ilkUrun değişken olarak oluşur; musteri, adres ve kalemler sadece kalıbın yoludur. Ara seviyelerden biri undefined gelirse destructuring TypeError fırlatır. Belirsiz yapılarda ara seviyeye varsayılan değer verin: { musteri: { ad } = {} } = siparis.

Fonksiyon parametrelerinde destructuring

Destructuring en çok fonksiyon parametrelerinde işe yarar. Ayar nesnesi alan bir fonksiyon, ihtiyaç duyduğu alanları varsayılanlarıyla birlikte imzasında belirtebilir. Parametrenin tamamına da = {} vermek, fonksiyon argümansız çağrıldığında hatayı önler:

javascript
function baglan({ host = "localhost", port = 5432, ssl = false } = {}) {
  return `${host}:${port} ssl=${ssl}`;
}

console.log(baglan({ port: 6543 })); // localhost:6543 ssl=false
console.log(baglan()); // localhost:5432 ssl=false

Varsayılan parametreler ve rest parametreleri (function f(...args)) default ve rest parametreler yazısında ayrıntılı anlatılıyor.

Rest: geri kalanları toplamak

Kalıbın sonuna yazılan ...ad, eşleşmeyen öğeleri toplar. Dizide geri kalan öğeler yeni bir diziye, nesnede ise henüz alınmamış kendi ve numaralandırılabilir özellikler yeni bir nesneye konur. Rest öğesi kalıbın son öğesi olmak zorundadır ve arkasından virgül gelemez. Nesneden bir alanı "çıkarmanın" pratik yolu budur:

javascript
const [bas, ...kuyruk] = [10, 20, 30, 40];
console.log(bas, kuyruk); // 10 [ 20, 30, 40 ]

const kullanici = { id: 1, ad: "Mert", sifre: "gizli" };
const { sifre, ...guvenli } = kullanici;
console.log(guvenli); // { id: 1, ad: 'Mert' }

Spread: dizileri ve nesneleri açmak

Spread üç yerde kullanılır: fonksiyon çağrısının argüman listesinde, dizi literallerinde ve nesne literallerinde. Dizi ve argüman listesinde yalnızca iterable değerler açılabilir. Nesne literalinde ise değerin kendi numaralandırılabilir özellikleri kopyalanır; aynı anahtar tekrar ederse sağdaki kazanır.

javascript
const sayilar = [3, 9, 1];
console.log(Math.max(...sayilar)); // 9

const tumu = [0, ...sayilar, 10];
console.log(tumu); // [ 0, 3, 9, 1, 10 ]

const varsayilan = { tema: "acik", dil: "tr" };
const ayar = { ...varsayilan, tema: "koyu" };
console.log(ayar); // { tema: 'koyu', dil: 'tr' }

// Koşullu özellik ekleme
const admin = true;
const menu = { ana: "/", ...(admin ? { panel: "/admin" } : {}) };
console.log(menu); // { ana: '/', panel: '/admin' }

console.log([..."çay"]); // [ 'ç', 'a', 'y' ]

Spread ile Object.assign() arasındaki farklar (setter çağrısı, hedefi değiştirme) Object metotları yazısında anlatılıyor.

Dikkat: spread ve rest sığ kopya üretir

[...dizi] veya { ...nesne } yeni bir dış kap oluşturur, ama içerideki nesneler kopyalanmaz; yeni kap aynı nesnelere referans tutar. MDN bunu açıkça belirtir: spread kopyalarken yalnızca bir seviye derine iner ve JavaScript'te yerel olarak derin kopya yapan bir operatör yoktur. Derin kopya için web platformundaki structuredClone() metodu kullanılabilir (Node.js'te de genel olarak tanımlıdır).

javascript
const orijinal = { ad: "Proje", etiketler: ["js"], sahip: { ad: "Ali" } };
const kopya = { ...orijinal };

kopya.ad = "Kopya";
kopya.etiketler.push("node");
kopya.sahip.ad = "Veli";

console.log(orijinal.ad); // Proje
console.log(orijinal.etiketler); // [ 'js', 'node' ]
console.log(orijinal.sahip.ad); // Veli

const derin = structuredClone(orijinal);
derin.sahip.ad = "Ayşe";
console.log(orijinal.sahip.ad); // Veli

Sözdizimi özeti

YazımNe yapar
const [a, b] = dizisıraya göre ilk iki öğeyi alır
const [, , c] = diziilk iki öğeyi atlar
const { ad } = objad özelliğini aynı adlı değişkene alır
const { ad: isim } = objad özelliğini isim değişkenine alır
const { ad = "x" } = objad undefined ise "x" kullanır (null ise kullanmaz)
const { a: { b } } = objiç içe özelliği alır
const [x, ...rest] = dizirest: geri kalanları yeni diziye toplar
const { a, ...rest } = objrest: kalan özellikleri yeni nesneye toplar
[...dizi1, ...dizi2]spread: dizileri birleştirir (sığ kopya)
{ ...obj, a: 1 }spread: nesneyi kopyalar, a alanını ezer
f(...args)spread: diziyi argüman listesine açar

Sık yapılan hatalar

Sık yapılan hatalar: Bildirim olmadan nesne destructuring, undefined veya null destructuring, Düz nesneyi dizi içine spread etmek

Bildirim olmadan nesne destructuring

Önceden tanımlı değişkenlere nesne kalıbıyla atama yaparken ifadeyi parantez içine almalısınız. { a, b } = obj; satırı başta süslü parantez olduğu için blok olarak yorumlanır ve sözdizimi hatası verir. Doğrusu ({ a, b } = obj); biçimidir. Satır sonlarında noktalı virgül kullanmıyorsanız bu satırın önüne bir noktalı virgül koymanız gerekebilir.

undefined veya null destructuring

javascript
try {
  const { ad } = undefined;
} catch (e) {
  console.log(e.message);
}
// Cannot destructure property 'ad' of 'undefined' as it is undefined.

Bu hata çoğunlukla fonksiyonun argümansız çağrılmasından ya da bir API alanının eksik gelmesinden kaynaklanır. Yukarıdaki = {} varsayılanı bu durumu önler. Diğer yaygın hata mesajları için sık JavaScript hata mesajları yazısına bakabilirsiniz.

Düz nesneyi dizi içine spread etmek

[...{ a: 1 }] çalışmaz ve TypeError: ... is not iterable verir, çünkü düz nesneler iterable değildir. Değerlere ihtiyacınız varsa [...Object.values(obj)] kullanın.

Sık Sorulan Sorular

Spread ile rest arasındaki fark nedir?

Yazımları aynıdır (...), görevleri terstir. Spread bir değeri açar ve sağ tarafta, argüman listesinde veya literal içinde kullanılır. Rest birden çok değeri toplar ve destructuring kalıbının ya da parametre listesinin sonunda yer alır.

[...dizi] ile dizi.slice() arasında fark var mı?

İkisi de dizinin sığ bir kopyasını üretir. Spread herhangi bir iterable ile çalıştığı için metin, Set veya Map kaynağından dizi oluşturmak için de kullanılabilir. Dizi kopyalama ve değiştirmeyen metotlar için dizi metotları yazısına bakın.

Bir fonksiyondan birden çok değer nasıl döndürülür?

JavaScript fonksiyonu tek bir değer döndürür, ama bu değer bir dizi ya da nesne olabilir. Çağıran taraf destructuring ile parçaları doğrudan değişkenlere alır. Nesne döndürmek, çağıranın sırayı ezberlemesini gerektirmediği için genellikle daha okunaklıdır:

javascript
function minMax(dizi) {
  return { min: Math.min(...dizi), max: Math.max(...dizi) };
}

const { min, max } = minMax([4, 9, 2]);
console.log(min, max); // 2 9

Destructuring for...of döngüsünde kullanılabilir mi?

Evet. for (const [anahtar, deger] of map) ya da for (const { ad } of kullanicilar) gibi döngü değişkenleri de bir bağlama kalıbı (binding pattern) olabilir. Aynı durum catch bloğundaki hata değişkeni için de geçerlidir.

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 · Default ve rest parametreler · Object metotları · Optional chaining ve nullish · Dizi metotları