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!