Destructuring: Şekle Göre Kalıp Eşleştirme
JavaScript'te destructuring (ayrıştırma), bir nesnenin ya da dizinin şeklini birebir yansıtan bir kalıp yazmanıza ve değerleri isme veya konuma göre tek satırda çekip almanıza olanak tanır. Değere tek tek özellik üzerinden ulaşmak yerine, ne istediğinizi tarif edersiniz; JavaScript de onu size uzatır.
İki çeşidi var:
Süslü parantezler nesneyi property adına göre eşler. Köşeli parantezler ise diziyi sıraya göre eşler. Her iki durumda da soldaki değişkenler yeni tanımlamalardır — değerin içine indeksle erişmiyorsunuz; parçaları çıkaran bir kalıp tarif ediyorsunuz.
Destructuring hayatımıza girmeden önce aynı kod şöyle yazılırdı:
const name = user.name;
const age = user.age;
const first = scores[0];
const second = scores[1];
Dünyanın sonu değil elbette, ama her fonksiyonda aynı şeyi tekrar tekrar yazmak bir süre sonra yoruyor.
Nesne ayrıştırmada anahtar isimleri kullanılır
Nesnelerde süslü parantez içine yazdığın isimlerin, kaynak nesnedeki property isimleriyle birebir aynı olması gerekir. Sıra önemli değil — JavaScript değerleri key üzerinden eşleştirir.
Nesnede olmayan bir özelliği almaya çalışırsanız hata almazsınız; değişken sadece undefined olur:
Anahtar adındaki bir yazım hatası yüzünden gecenin bir yarısı kafanızı duvara vurmamak için, bu sessizce undefined döndürme davranışını aklınızın bir köşesinde tutun.
Değişken İsmini Değiştirme
Bazen nesnedeki property adı, değişkene vermek istediğiniz isimle uyuşmaz — belki aynı kapsamda başka bir şeyle çakışıyordur ya da API'nin kullandığı isimlendirme tarzını pek sevmiyorsunuzdur. Böyle durumlarda orijinalAd: yeniAd söz dizimiyle yeni bir isme bağlayabilirsiniz:
Bunu şöyle okuyun: "id property'sini al, adını userId yap." Önce property adı gelir, iki noktadan sonra da yeni değişken adı. Başka dillerden gelen tip tanımı (type annotation) gibi görünse de öyle değil.
Varsayılan Değerler
Bir property'nin olmama ihtimali varsa, varsayılan değerini doğrudan pattern'in içinde verin:
Varsayılan değerler yalnızca değer undefined olduğunda devreye girer. null, 0 ve "" olduğu gibi geçer, varsayılana düşmez:
Bu detay çoğu kişiyi yakalıyor. null değerinin de varsayılanı tetiklemesini istiyorsan, ya açıkça kontrol etmen gerekir ya da destructuring sonrasında nullish coalescing operatörü ?? kullanmalısın.
Varsayılan değerleri yeniden adlandırmayla birlikte de kullanabilirsin:
Dizi Ayrıştırmada Sıra Önemlidir
Dizilerin isimleri yoktur, sadece indeksleri vardır; bu yüzden array destructuring işlemi pozisyona göre eşleşir. İlgilenmediğin elemanları atlamak için virgül kullanabilirsin:
Baştaki iki virgül, "0. ve 1. indeksi atla" anlamına geliyor. Görsel olarak biraz yoğun duruyor, ama ortadaki tek bir değeri çekmek istediğinizde işinizi fazlasıyla görüyor.
Dizi ayrıştırma asıl gücünü, tuple tarzı değer döndüren fonksiyonlarda gösteriyor:
React hook'larında sürekli aynı kalıbı görürsün: const [count, setCount] = useState(0).
Rest Pattern: Geriye Kalanları Toplamak
Bir destructuring ifadesinin içinde ...isim yazdığında, isim veya konum olarak eşleşmeyen ne varsa yeni bir değişkende toplanır.
Dizilerde rest, geriye kalan elemanları yakalar:
Nesnelerde rest, ismen yakalamadığınız tüm property'leri toparlar:
Bir nesneden tek bir alanı, nesneyi mutasyona uğratmadan soyup almanın deyimsel yolu budur — rest, id dışındaki her şeyi içeren yeni bir nesnedir.
Rest, kalıbın en sonunda yer almalıdır. const [...init, last] sözdizimi hatası verir.
İç İçe Destructuring
Kalıplar iç içe geçebilir. Bir özellik kendisi de nesne ya da diziyse, aynı ifade içinde onu da ayrıştırabilirsin:
Güçlü bir özellik, ama dikkatli kullanmak lazım. Üç seviye iç içe süslü parantez görünce mesele bulmaca çözmeye dönüyor. O noktaya geldiyseniz, ara değerleri ayrı değişkenlere alın — zekice yazmaktansa okunur yazmak her zaman daha değerli.
Dikkat edilmesi gereken bir nokta: kalıptaki data: { user } ifadesi data adında bir değişken oluşturmaz. Bu sadece "data'nın içine in ve ayrıştırmaya devam et" demenin yoludur. data'nın kendisine de ihtiyacınız varsa onu ayrıca eklemelisiniz:
Fonksiyon Parametrelerinde Destructuring
Destructuring'i en sık kullanacağınız yer, fonksiyonların parametre listesidir. "Bir options nesnesi alalım" dediğiniz kodu, kendi kendini belgeleyen bir imzaya dönüştürür:
Çağrı tarafında, diğer tüm options-object çağrılarından farksız görünür. Fonksiyonun içinde ise varsayılan değerleri olan adlandırılmış değişkenlere kavuşursun — artık options.name || "default" tarzı tekrar eden kodlara gerek yok.
Ama dikkat etmen gereken bir nokta var: bu fonksiyonu hiç argüman vermeden çağırırsan hata alırsın, çünkü undefined üzerinde destructuring yapılamaz. Çözüm olarak parametrenin tamamına bir varsayılan değer ver:
Şablonun arkasındaki = {} kısmı şunu söylüyor: "Eğer hiç argüman gelmezse, boş bir nesne gelmiş gibi davran." Ondan sonra içerideki varsayılanlar devreye giriyor.
Değer Takası ve Yeniden Atama
Destructuring, önceden tanımlanmış değişkenlerle de çalışır; ancak nesne şablonunu parantez içine almanız gerekir (aksi halde JavaScript { karakterini bir blok başlangıcı olarak algılar):
Dizi takası bu şekilde oldukça temiz duruyor. Nesne yeniden atama işini daha nadir kullanırsın ama şu parantez numarasını bir köşede tutmakta fayda var; ihtiyacın olduğunda işini görecektir.
Gerçek Hayattan Bir Örnek
Şimdiye kadar gördüklerimizin büyük çoğunluğunu tek bir örnekte birleştirelim — bir API yanıtını işleyen bir fonksiyon:
Destructuring'in her katmanında bir varsayılan değer var; böylece fonksiyon, eksik veriyle de bir yığın if kontrolüne ihtiyaç duymadan ayakta kalıyor. Asıl kazanç da bu: hem net hem de esnek imzalar.
Sırada: Object Spread
Destructuring, nesnelerden değer çıkarmaya yarar. Spread ise tam tersi — değerleri içeri koyar, kopyalar, birleştirir ve üzerine yazar. Modern JavaScript'te bu ikisi neredeyse her zaman yan yana gelir. Şimdi sırada spread var.
Sıkça Sorulan Sorular
JavaScript'te destructuring nedir?
Destructuring, obje veya dizilerdeki değerleri tek satırda çıkarıp değişkenlere atamaya yarayan bir sözdizimidir. const { name } = user; ifadesi user nesnesindeki name özelliğini alır. const [first, second] = list; ise list dizisinin ilk iki elemanını çeker. Kısacası = işaretinin solunda, sağdaki değerin şeklini taklit eden bir desen yazıyorsun.
Destructuring sırasında değişken ismini nasıl değiştiririm?
{ orijinalAd: yeniAd } sözdizimini kullan. Örneğin const { name: username } = user; satırı, user içindeki name özelliğini alır ve yerel değişkene username adını verir. İlk bakışta tip tanımıyla karıştırılabiliyor — unutma: iki noktadan önce özellik adı, sonra yeni değişken adı gelir.
Destructuring ile varsayılan değer atanabilir mi?
Evet. const { timeout = 5000 } = options; yazdığında, eğer options.timeout undefined ise 5000 kullanılır. Default değerler yalnızca undefined için devreye girer — null, 0 ve '' olduğu gibi geçer. Yeniden adlandırmayla da birleştirebilirsin: const { t: timeout = 5000 } = options;.
Destructuring ile spread arasındaki fark nedir?
Görünüş olarak benzerler ama tam tersi işler yaparlar. Destructuring (const { a, b } = obj) bir yapının içinden değer çeker. Spread (const copy = { ...obj }) ise değerleri yeni bir yapının içine aktarır. Destructuring deseninin içinde gördüğün ... ise rest pattern'dır — kalan özellikleri yeni bir değişkende toplar.