İçeriğe geç
JavaScript

JavaScript 2025 Yenilikleri: ECMAScript Güncellemeleri

Tarık Tunç
JavaScript 2025 Yenilikleri: ECMAScript Güncellemeleri

JavaScript 2025 Yenilikleri: ECMAScript Güncellemeleri

JavaScript ekosistemi her yıl yeni özelliklerle genişlemeye devam ediyor. ECMAScript 2025 (ES2025) ve yakın dönemde Stage 3-4 aşamasına ulaşan teklifler, dilin ifade gücünü ve geliştiricilerin üretkenliğini önemli ölçüde artırıyor. Bu rehberde Decorators, Record/Tuple, Pattern Matching, Temporal API ve Iterator Helpers gibi öne çıkan yenilikleri gerçek dünya örnekleriyle inceleyeceğiz.

1. Decorators: Sınıf ve Metod Dekoratörleri

Decorators, sınıflar, metotlar, erişimciler ve alanlar üzerine meta-programlama yapmanın standart yolunu sunar. TypeScript'te yıllardır deneysel olarak kullanılan bu özellik artık JavaScript standardının parçası haline geldi.

// Metod dekoratörü: önbellek (memoize)
function memoize(target, context) {
  const cache = new Map();
  return function (...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) return cache.get(key);
    const result = target.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

// Metod dekoratörü: loglama
function log(target, context) {
  return function (...args) {
    console.log(`[${context.name}] çağrıldı:`, args);
    const result = target.apply(this, args);
    console.log(`[${context.name}] döndü:`, result);
    return result;
  };
}

// Sınıf dekoratörü: singleton
function singleton(Class) {
  let instance;
  return class extends Class {
    constructor(...args) {
      if (instance) return instance;
      super(...args);
      instance = this;
    }
  };
}

@singleton
class ConfigService {
  @log
  @memoize
  fetchConfig(key) {
    return expensiveConfigLookup(key);
  }
}

const c1 = new ConfigService();
const c2 = new ConfigService();
console.log(c1 === c2); // true — singleton
Bilgi: Decorators Stage 3 aşamasından geçerek ES2025 ile standarda dahil oldu. TypeScript 5.0+ ve modern Babel konfigürasyonlarıyla bugünden kullanabilirsiniz. Eski experimentalDecorators API'siyle uyumsuz olduğuna dikkat edin.

2. Record ve Tuple: Değişmez Veri Yapıları

Record ve Tuple, nesne ve dizilerin değişmez (immutable) ve değere göre eşitlik özelliğine sahip muadilleridir. React state yönetiminde ve fonksiyonel programlamada büyük kolaylık sağlar.

// Record: Değişmez nesne (# prefix ile)
const k1 = #{ x: 10, y: 20 };
const k2 = #{ x: 10, y: 20 };
console.log(k1 === k2); // true! Değer karşılaştırması

const obj1 = { x: 10 };
const obj2 = { x: 10 };
console.log(obj1 === obj2); // false (referans)

// Tuple: Değişmez dizi
const p1 = #[1, 2, 3];
const p2 = #[1, 2, 3];
console.log(p1 === p2); // true

// Map key olarak kullanım — büyük avantaj
const ziyaretler = new Map();
ziyaretler.set(#{ x: 0, y: 0 }, 'Başlangıç noktası');
console.log(ziyaretler.get(#{ x: 0, y: 0 })); // 'Başlangıç noktası'

// Spread ile güncelleme
let state = #{ count: 0, user: #{ name: 'Ali' } };
state = #{ ...state, count: state.count + 1 };
console.log(state.count); // 1
İpucu: Record ve Tuple, React ve Redux gibi state yönetim kütüphanelerinde shallow equality karşılaştırmalarını doğru sonuç verecek hale getirir. Artık derin karşılaştırma (deep equal) fonksiyonlarına gerek kalmaz.

3. Pattern Matching: switch'in Güçlü Halefi

Pattern Matching, karmaşık koşullu mantığı açık ve okunabilir sözdizimi ile ifade etmeyi sağlar. Rust ve F# gibi dillerden ilham alınan bu özellik JavaScript'e match ifadesi olarak geliyor.

// Temel pattern matching
const mesaj = match (response) {
  when { status: 200, body } => `Başarı: ${body}`,
  when { status: 404 }       => 'Bulunamadı',
  when { status: 500 }       => 'Sunucu hatası',
  when { status }            => `Bilinmeyen: ${status}`,
};

// Tip kontrolü ile
function formatDeger(deger) {
  return match (deger) {
    when (x: number) if x < 0  => `Negatif: ${x}`,
    when (x: number)            => `Pozitif: ${x}`,
    when (x: string) if x === '' => 'Boş string',
    when (x: string)            => `Metin: "${x}"`,
    when null | undefined       => 'Değer yok',
    when (x: Array)             => `${x.length} öğeli dizi`,
    else                        => 'Bilinmeyen tip',
  };
}

// Derin nesne desenleri
const isle = (sinyal) => match (sinyal) {
  when { type: 'HATA',   hata: { kod: 404 } } => tekrarDene(),
  when { type: 'HATA',   hata: { kod }      } => logla(kod),
  when { type: 'BAŞARI', veri               } => isleVeri(veri),
  when { type: 'YÜKLEME'                    } => gosterSpinner(),
};

4. Temporal API: Tarih/Saat Yönetiminde Devrim

JavaScript'in Date nesnesi onlarca yıldır geliştiricileri zorladı. Temporal API, sezgisel, değişmez (immutable) ve timezone-aware bir tarih/saat kütüphanesi sunuyor.

// Anlık zaman
const simdi = Temporal.Now.plainDateTimeISO();
console.log(simdi.toString()); // "2025-03-27T14:30:00"

const zonlu = Temporal.Now.zonedDateTimeISO('Europe/Istanbul');
console.log(zonlu.toString());
// "2025-03-27T14:30:00+03:00[Europe/Istanbul]"

// Tarih oluşturma ve aritmetik (değişmez!)
const toplanti = Temporal.PlainDateTime.from('2025-04-10T09:00:00');
const birHaftaSonra = toplanti.add({ weeks: 1, hours: 2 });
console.log(birHaftaSonra.toString()); // "2025-04-17T11:00:00"

// Gün sayısı hesaplama
const bugun  = Temporal.Now.plainDateISO();
const hedef  = Temporal.PlainDate.from('2025-12-31');
const fark   = bugun.until(hedef);
console.log(`${fark.days} gün kaldı`);

// Timezone dönüşümü
const ist  = Temporal.ZonedDateTime.from('2025-04-01T10:00:00[Europe/Istanbul]');
const tkyo = ist.withTimeZone('Asia/Tokyo');
console.log(tkyo.toString());
// "2025-04-01T16:00:00+09:00[Asia/Tokyo]"

// Karşılaştırma
const t1 = Temporal.PlainDate.from('2025-01-15');
const t2 = Temporal.PlainDate.from('2025-06-20');
console.log(Temporal.PlainDate.compare(t1, t2)); // -1 (t1 önce)
Dikkat: Temporal API Stage 3 aşamasındadır ve henüz tüm tarayıcılarda yerel destek yoktur. Üretim kullanımı için temporal-polyfill paketini kullanın.

5. Iterator Helpers: Tembel Veri İşleme

Iterator Helpers, büyük veri setlerini belleğe tamamen yüklemeden işleme imkânı sunar. Tüm ara sonuçlar için yeni dizi oluşturmak yerine lazy (tembel) değerlendirme yapılır.

// Sonsuz iterator + lazy zincirleme
function* sayiUret(bas = 0) {
  let n = bas;
  while (true) yield n++;
}

const sonuclar = sayiUret(1)
  .map(x => x * x)
  .filter(x => x % 2 === 0)
  .take(5)
  .toArray();
console.log(sonuclar); // [4, 16, 36, 64, 100]

// flatMap ile kelime listesi
const cumleler = ['Merhaba Dünya', 'TypeScript harika'];
const kelimeler = cumleler[Symbol.iterator]()
  .flatMap(c => c.split(' '))
  .toArray();
console.log(kelimeler); // ['Merhaba', 'Dünya', 'TypeScript', 'harika']

// reduce
const toplam = [1, 2, 3, 4, 5][Symbol.iterator]()
  .filter(x => x % 2 !== 0)
  .reduce((acc, x) => acc + x, 0);
console.log(toplam); // 9 (1+3+5)

// Sayfalanmış API üzerinde lazy okuma
async function* kayitlar() {
  let sayfa = 1;
  while (true) {
    const data = await fetchPage(sayfa++);
    if (!data.length) return;
    yield* data;
  }
}

const aktifler = await kayitlar()
  .filter(u => u.active)
  .take(10)
  .toArray();

6. Diğer ES2025 Yenilikleri

// Promise.try — senkron hatalar için
const sonuc = await Promise.try(() => {
  if (Math.random() > 0.5) throw new Error('Hata');
  return 'Başarılı';
}).catch(e => `Yakalandı: ${e.message}`);

// RegExp.escape — güvenli regex oluşturma
const aramaMetni = 'kullanıcı@email.com (test)';
const pattern = new RegExp(RegExp.escape(aramaMetni), 'i');
// Nokta ve parantezler otomatik escape edilir

// Object.groupBy (artık yerleşik)
const urunler = [
  { ad: 'Elma',    kategori: 'meyve' },
  { ad: 'Patates', kategori: 'sebze' },
];
const gruplar = Object.groupBy(urunler, u => u.kategori);
// { meyve: [...], sebze: [...] }

// String.isWellFormed / toWellFormed
const bozuk = 'Merhaba \uD800 Dünya';
console.log(bozuk.isWellFormed()); // false
console.log(bozuk.toWellFormed()); // 'Merhaba  Dünya'
İpucu: ES2025 özelliklerini bugünden kullanmak için Babel'in @babel/preset-env veya TypeScript'in yeni sürümlerini kullanabilirsiniz. TC39 Proposals sayfasından hangi özelliklerin hangi aşamada olduğunu takip edin.

Sonuç

JavaScript 2025 ve yakın dönem ECMAScript güncellemeleri dilin ifade gücünü önemli ölçüde artırıyor. Decorators ile meta-programlama artık standart, Temporal API ile tarih sorunları tarih oluyor, Pattern Matching ile karmaşık koşullu mantık okunabilir hale geliyor, Record/Tuple ile değer eşitliği sorunu çözülüyor ve Iterator Helpers ile büyük veri setleri verimli biçimde işleniyor. Polyfill ve transpiler araçlarıyla bu özellikleri bugünden deneyebilirsiniz.

Kaynaklar

İlgili Yazılar