Modern JavaScript ES2024 Özellikleri

JavaScript sürekli gelişen bir dil ve her yıl yeni özellikler ekliyor. 2024 yılında eklenen özellikler, geliştiricilerin daha temiz ve etkili kod yazmasına yardımcı oluyor.

Array Grouping

ES2024 ile gelen en heyecan verici özelliklerden biri Array.prototype.group() ve Array.prototype.groupToMap() metodları.

const products = [
  { name: 'Laptop', category: 'Electronics', price: 1000 },
  { name: 'Phone', category: 'Electronics', price: 500 },
  { name: 'Book', category: 'Education', price: 20 },
  { name: 'Pen', category: 'Stationery', price: 2 }
];

// Array.prototype.group() kullanımı
const groupedByCategory = products.group(product => product.category);
console.log(groupedByCategory);
// {
//   Electronics: [
//     { name: 'Laptop', category: 'Electronics', price: 1000 },
//     { name: 'Phone', category: 'Electronics', price: 500 }
//   ],
//   Education: [{ name: 'Book', category: 'Education', price: 20 }],
//   Stationery: [{ name: 'Pen', category: 'Stationery', price: 2 }]
// }

// Array.prototype.groupToMap() kullanımı
const priceRanges = products.groupToMap(product => {
  if (product.price < 50) return 'budget';
  if (product.price < 500) return 'mid-range';
  return 'premium';
});

console.log(priceRanges.get('premium'));
// [{ name: 'Laptop', category: 'Electronics', price: 1000 }]

Pratik Kullanım Senaryoları

// E-ticaret uygulamasında ürünleri gruplama
const orderItems = [
  { productId: 1, category: 'elektronik', quantity: 2 },
  { productId: 2, category: 'kitap', quantity: 1 },
  { productId: 3, category: 'elektronik', quantity: 1 },
  { productId: 4, category: 'giyim', quantity: 3 }
];

const itemsByCategory = orderItems.group(item => item.category);

// Her kategori için toplam miktar hesaplama
Object.entries(itemsByCategory).forEach(([category, items]) => {
  const totalQuantity = items.reduce((sum, item) => sum + item.quantity, 0);
  console.log(`${category}: ${totalQuantity} adet`);
});

Decorators

ES2024 ile beraber Decorators resmi olarak JavaScript'e eklendi. Sınıfları ve metotları daha deklaratif şekilde genişletmenizi sağlar.

// Method decorator örneği
function log(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value;
  
  descriptor.value = function(...args) {
    console.log(`${propertyKey} metodu çağrıldı:`, args);
    const result = originalMethod.apply(this, args);
    console.log(`${propertyKey} sonucu:`, result);
    return result;
  };
  
  return descriptor;
}

// Class decorator örneği
function sealed(target) {
  Object.seal(target);
  Object.seal(target.prototype);
  return target;
}

@sealed
class Calculator {
  @log
  add(a, b) {
    return a + b;
  }
  
  @log
  multiply(a, b) {
    return a * b;
  }
}

const calc = new Calculator();
calc.add(5, 3); // Console'da log görürsünüz

Gelişmiş Decorator Örnekleri

// Performance monitoring decorator
function measure(target, propertyKey, descriptor) {
  const originalMethod = descriptor.value;
  
  descriptor.value = function(...args) {
    const start = performance.now();
    const result = originalMethod.apply(this, args);
    const end = performance.now();
    console.log(`${propertyKey} ${end - start} ms sürdü`);
    return result;
  };
}

// Memoization decorator
function memoize(target, propertyKey, descriptor) {
  const cache = new Map();
  const originalMethod = descriptor.value;
  
  descriptor.value = function(...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    
    const result = originalMethod.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

class DataProcessor {
  @measure
  @memoize
  expensiveCalculation(n) {
    // Karmaşık hesaplama simülasyonu
    let result = 0;
    for (let i = 0; i < n * 1000000; i++) {
      result += Math.random();
    }
    return result;
  }
}

Pipeline Operator

Pipeline Operator (|>), fonksiyonel programlama paradigmasını JavaScript'e getiren güçlü bir özellik.

// Geleneksel yaklaşım
const data = [1, 2, 3, 4, 5];
const result = data
  .map(x => x * 2)
  .filter(x => x > 5)
  .reduce((sum, x) => sum + x, 0);

// Pipeline operator ile
const pipeline = data
  |> (arr => arr.map(x => x * 2))
  |> (arr => arr.filter(x => x > 5))
  |> (arr => arr.reduce((sum, x) => sum + x, 0));

// Daha karmaşık pipeline örneği
const processUserData = (userData) => 
  userData
  |> validateUser
  |> normalizeData
  |> enrichWithPermissions
  |> formatForAPI;

function validateUser(user) {
  if (!user.email || !user.name) {
    throw new Error('Eksik kullanıcı bilgisi');
  }
  return user;
}

function normalizeData(user) {
  return {
    ...user,
    email: user.email.toLowerCase(),
    name: user.name.trim()
  };
}

function enrichWithPermissions(user) {
  return {
    ...user,
    permissions: user.role === 'admin' ? ['read', 'write', 'delete'] : ['read']
  };
}

function formatForAPI(user) {
  return {
    id: user.id,
    displayName: user.name,
    email: user.email,
    accessLevel: user.permissions.length
  };
}

Temporal API

Temporal API, JavaScript'te tarih ve saat işlemlerini daha güvenilir hale getiren yeni bir API.

// Mevcut Date API'sinin sorunları
const badDate = new Date('2024-01-31');
badDate.setMonth(1); // Şubat ayı, 31 gün yok -> Mart'a kayar!
console.log(badDate); // 2024-03-02 (beklenmedik!)

// Temporal API ile güvenli tarih işlemleri
import { Temporal } from '@js-temporal/polyfill';

// PlainDate - sadece tarih
const date = Temporal.PlainDate.from('2024-01-31');
const nextMonth = date.with({ month: 2 }); // Güvenli ay değişimi
console.log(nextMonth.toString()); // 2024-02-29 (leap year)

// PlainTime - sadece saat
const time = Temporal.PlainTime.from('14:30:45');
const laterTime = time.add({ hours: 2, minutes: 15 });
console.log(laterTime.toString()); // 16:45:45

// PlainDateTime - tarih + saat
const datetime = Temporal.PlainDateTime.from('2024-01-15T10:30:00');
const nextWeek = datetime.add({ days: 7 });
console.log(nextWeek.toString()); // 2024-01-22T10:30:00

// ZonedDateTime - saat dilimi ile
const zonedDateTime = Temporal.ZonedDateTime.from(
  '2024-01-15T10:30:00[Europe/Istanbul]'
);

const inNewYork = zonedDateTime.withTimeZone('America/New_York');
console.log(inNewYork.toString()); // 2024-01-15T03:30:00-05:00[America/New_York]

Temporal API Pratik Örnekleri

// İş günleri hesaplama
function addBusinessDays(startDate, days) {
  let current = Temporal.PlainDate.from(startDate);
  let remaining = days;
  
  while (remaining > 0) {
    current = current.add({ days: 1 });
    // Hafta sonu değilse
    if (current.dayOfWeek < 6) {
      remaining--;
    }
  }
  
  return current;
}

const start = Temporal.PlainDate.from('2024-01-15'); // Pazartesi
const businessDate = addBusinessDays(start, 5); // 5 iş günü sonra
console.log(businessDate.toString()); // 2024-01-22

// Yaş hesaplama
function calculateAge(birthDate, referenceDate = Temporal.PlainDate.from(Temporal.Now.plainDate())) {
  const birth = Temporal.PlainDate.from(birthDate);
  const duration = referenceDate.since(birth);
  return duration.years;
}

console.log(calculateAge('1990-05-15')); // Mevcut yaş

// Toplantı zamanı koordinasyonu
function scheduleMeeting(localTime, participants) {
  const baseTime = Temporal.ZonedDateTime.from(localTime);
  
  return participants.map(participant => ({
    name: participant.name,
    localTime: baseTime.withTimeZone(participant.timezone).toString(),
    timezone: participant.timezone
  }));
}

const meeting = scheduleMeeting(
  '2024-01-15T14:00:00[Europe/Istanbul]',
  [
    { name: 'Ali', timezone: 'Europe/Istanbul' },
    { name: 'John', timezone: 'America/New_York' },
    { name: 'Yuki', timezone: 'Asia/Tokyo' }
  ]
);

Kod Örnekleri ve Best Practices

Array Grouping Best Practices

// Performanslı gruplama için Map kullanın
const groupByPerformant = (array, keyFn) => {
  return array.groupToMap(keyFn);
};

// Çoklu kritere göre gruplama
const multiGroupBy = (array, ...keyFns) => {
  return array.group(item => 
    keyFns.map(fn => fn(item)).join('|')
  );
};

const users = [
  { name: 'Ali', department: 'IT', level: 'senior' },
  { name: 'Ayşe', department: 'HR', level: 'junior' },
  { name: 'Mehmet', department: 'IT', level: 'junior' }
];

const grouped = multiGroupBy(
  users,
  user => user.department,
  user => user.level
);
// { 'IT|senior': [...], 'HR|junior': [...], 'IT|junior': [...] }

Decorator Patterns

// Retry decorator - hata durumunda yeniden deneme
function retry(maxAttempts = 3, delay = 1000) {
  return function(target, propertyKey, descriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = async function(...args) {
      let attempts = 0;
      
      while (attempts < maxAttempts) {
        try {
          return await originalMethod.apply(this, args);
        } catch (error) {
          attempts++;
          if (attempts >= maxAttempts) {
            throw error;
          }
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
    };
  };
}

// Rate limiting decorator
function rateLimit(requestsPerMinute = 60) {
  const calls = new Map();
  
  return function(target, propertyKey, descriptor) {
    const originalMethod = descriptor.value;
    
    descriptor.value = function(...args) {
      const now = Date.now();
      const windowStart = now - 60000; // 1 dakika
      
      if (!calls.has(this)) {
        calls.set(this, []);
      }
      
      const instanceCalls = calls.get(this);
      const recentCalls = instanceCalls.filter(time => time > windowStart);
      
      if (recentCalls.length >= requestsPerMinute) {
        throw new Error('Rate limit exceeded');
      }
      
      recentCalls.push(now);
      calls.set(this, recentCalls);
      
      return originalMethod.apply(this, args);
    };
  };
}

class APIClient {
  @retry(3, 2000)
  @rateLimit(30)
  async fetchData(url) {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP ${response.status}`);
    }
    return response.json();
  }
}

Pipeline Operator Kullanım Alanları

// Veri analizi pipeline'ı
const salesData = [
  { month: 'Jan', sales: 1000, region: 'North' },
  { month: 'Feb', sales: 1200, region: 'North' },
  { month: 'Jan', sales: 800, region: 'South' },
  { month: 'Feb', sales: 900, region: 'South' }
];

const analysis = salesData
  |> (data => data.group(item => item.region))
  |> (grouped => Object.entries(grouped).map(([region, sales]) => ({
      region,
      totalSales: sales.reduce((sum, item) => sum + item.sales, 0),
      averageSales: sales.reduce((sum, item) => sum + item.sales, 0) / sales.length
    })))
  |> (results => results.sort((a, b) => b.totalSales - a.totalSales));

console.log(analysis);
// [
//   { region: 'North', totalSales: 2200, averageSales: 1100 },
//   { region: 'South', totalSales: 1700, averageSales: 850 }
// ]

Sonuç

ES2024'ün getirdiği bu yeni özellikler, JavaScript geliştiricilerinin kod yazma deneyimini önemli ölçüde iyileştiriyor:

  • Array Grouping: Veri manipülasyonunu kolaylaştırıyor
  • Decorators: Metaprogramming ve kod organizasyonunu güçlendiriyor
  • Pipeline Operator: Fonksiyonel programlamayı destekliyor
  • Temporal API: Tarih/saat işlemlerini güvenilir hale getiriyor

Bu özellikler, daha temiz, okunabilir ve maintainable kod yazmanıza yardımcı olacak. Modern JavaScript geliştirme sürecinizde bu yenilikleri deneyerek, kod kalitenizi artırabilirsiniz.

// Kategoriye göre grupla const groupedByCategory = products.group(product => product.category); console.log(groupedByCategory); // { // Electronics: [{ name: 'Laptop', ... }, { name: 'Phone', ... }], // Education: [{ name: 'Book', ... }], // Stationery: [{ name: 'Pen', ... }] // }


## Promise.withResolvers()

Promise oluşturma işlemini daha da kolaylaştıran yeni bir metod:

```javascript
// Eski yöntem
let resolve, reject;
const promise = new Promise((res, rej) => {
  resolve = res;
  reject = rej;
});

// Yeni yöntem
const { promise, resolve, reject } = Promise.withResolvers();

// Kullanım örneği
function createTimer(ms) {
  const { promise, resolve } = Promise.withResolvers();
  setTimeout(resolve, ms);
  return promise;
}

await createTimer(1000); // 1 saniye bekle

Temporal API Gelişmeleri

Tarih ve saat işlemleri için çok daha güçlü bir API:

// Temporal.PlainDate ile tarih işlemleri
const today = Temporal.PlainDate.from('2024-01-15');
const nextWeek = today.add({ days: 7 });

console.log(nextWeek.toString()); // "2024-01-22"

// Temporal.Duration ile süre hesaplamaları
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });
const result = duration.total({ unit: 'minutes' }); // 150 dakika

Top-level await Geliştirmeleri

Modüller arası daha iyi async/await desteği:

// config.mjs
const config = await fetch('/api/config').then(r => r.json());
export default config;

// main.mjs
import config from './config.mjs';
console.log(config); // Config yüklendikten sonra çalışır

Regex v Flag

Unicode özelliklerini daha iyi destekleyen yeni regex flag'i:

// Emoji ve Unicode karakterleri için gelişmiş destek
const emojiRegex = /\p{Emoji}/v;
const text = "Merhaba 👋 dünya 🌍";
console.log(text.match(emojiRegex)); // ['👋']

Pratik Örnekler

1. Veri İşleme Pipeline'ı

const data = [
  { name: 'Ali', age: 25, department: 'IT' },
  { name: 'Ayşe', age: 30, department: 'HR' },
  { name: 'Mehmet', age: 28, department: 'IT' },
];

// Departmana göre grupla ve yaş ortalaması hesapla
const departmentStats = data
  .group(person => person.department)
  .map(([dept, people]) => ({
    department: dept,
    count: people.length,
    averageAge: people.reduce((sum, p) => sum + p.age, 0) / people.length
  }));

2. Async İşlem Yöneticisi

class AsyncTaskManager {
  constructor() {
    this.tasks = new Map();
  }
  
  async createTask(id, taskFn) {
    const { promise, resolve, reject } = Promise.withResolvers();
    
    this.tasks.set(id, { promise, resolve, reject });
    
    try {
      const result = await taskFn();
      resolve(result);
    } catch (error) {
      reject(error);
    }
    
    return promise;
  }
  
  getTask(id) {
    return this.tasks.get(id)?.promise;
  }
}

Sonuç

ES2024 özellikleri JavaScript'i daha güçlü ve kullanışlı hale getiriyor. Bu yeni özellikler sayesinde:

  • Daha temiz ve okunabilir kod yazabiliyoruz
  • Array işlemleri daha kolay hale geliyor
  • Async işlemler daha kontrollü oluyor
  • Tarih/saat hesaplamaları daha doğru yapılabiliyor

Bu özellikleri projelerinizde kullanmaya başlayarak modern JavaScript geliştirme deneyimini yaşayabilirsiniz.

Not: Bu özelliklerin tarayıcı desteği için Can I Use sitesini kontrol etmeyi unutmayın.

Bu yazıda ES2024'ün en önemli özelliklerini ele aldık. Hangi özelliği en çok beğendiniz? Yorumlarda paylaşabilirsiniz!