JavaScript ES2025 - najnowsze funkcje i możliwości języka
JavaScript nieustannie ewoluuje, wprowadzając nowe funkcje, które ułatwiają programistom tworzenie lepszych aplikacji. W tym artykule poznasz najważniejsze nowości wprowadzone w ECMAScript 2025 oraz dowiesz się, jak wykorzystać je w swoich projektach.
Record i Tuple - niezmienne struktury danych
Jedną z najbardziej oczekiwanych nowości w ES2025 są niezmienne struktury danych - Record i Tuple:
// Record - niezmienny obiekt
const person = #{
name: "Anna",
age: 30,
city: "Warszawa"
};
// Tuple - niezmienne array
const coordinates = #[52.2297, 21.0122];
// Próba modyfikacji rzuci błąd
// person.name = "Maria"; // TypeError!
Te struktury oferują lepszą wydajność i bezpieczeństwo, szczególnie w aplikacjach React gdzie niezmienność jest kluczowa.
Pattern Matching - dopasowanie wzorców
Pattern matching to potężna funkcja znana z języków funkcyjnych, która w końcu trafia do JavaScript:
function processData(value) {
match (value) {
case { type: "user", name: String, age: Number } => {
console.log(`Użytkownik: ${name}, wiek: ${age}`);
}
case { type: "product", price: Number } when price > 100 => {
console.log("Drogi produkt");
}
case String if value.startsWith("http") => {
console.log("To jest URL");
}
case Number => {
console.log("To jest liczba");
}
default => {
console.log("Nierozpoznany typ danych");
}
}
}
Temporal API - nowy sposób pracy z datami
Temporal API zastępuje problematyczny obiekt Date z nowoczesnymi, intuicyjnymi klasami:
// Aktualna data i czas
const now = Temporal.Now.plainDateTimeISO();
// Precyzyjna data
const birthday = Temporal.PlainDate.from('1990-05-15');
// Operacje na datach
const nextWeek = now.add({ days: 7 });
const duration = nextWeek.since(now);
console.log(duration.days); // 7
// Formatowanie
const formatted = now.toLocaleString('pl-PL', {
year: 'numeric',
month: 'long',
day: 'numeric'
});
Decorators - dekoratory w JavaScript
Dekoratory pozwalają na modyfikację klas i ich składników w elegancki sposób:
// Dekorator dla logowania
function logged(target, context) {
return function(...args) {
console.log(`Wywoływanie ${context.name} z argumentami:`, args);
return target.apply(this, args);
};
}
// Dekorator dla walidacji
function validate(validator) {
return function(target, context) {
return function(value) {
if (!validator(value)) {
throw new Error(`Nieprawidłowa wartość: ${value}`);
}
return target.call(this, value);
};
};
}
class User {
constructor(name) {
this.name = name;
}
@logged
getName() {
return this.name;
}
@validate(name => name.length > 2)
setName(name) {
this.name = name;
}
}
Pipeline Operator - operator rurociągu
Pipeline operator (|>) znacznie poprawia czytelność kodu przy łączeniu funkcji:
// Tradycyjny sposób
const result = Math.round(Math.abs(Math.sqrt(16)));
// Z pipeline operator
const result = 16
|> Math.sqrt
|> Math.abs
|> Math.round;
// Z funkcjami strzałkowymi
const processText = text => text
|> (str => str.trim())
|> (str => str.toLowerCase())
|> (str => str.replace(/\s+/g, '-'))
|> (str => str.substring(0, 50));
const slug = processText(" JavaScript ES2025 Nowości ");
Import Assertions - asercje importu
Nowa składnia pozwala na bezpieczniejsze importowanie różnych typów plików:
// Import JSON
import config from './config.json' assert { type: 'json' };
// Import CSS
import styles from './styles.css' assert { type: 'css' };
// Import WebAssembly
import wasmModule from './calculate.wasm' assert { type: 'webassembly' };
// Dynamiczny import z asercją
const data = await import('./data.json', {
assert: { type: 'json' }
});
Array.fromAsync - asynchroniczne tworzenie tablic
Nowa metoda do tworzenia tablic z asynchronicznych iteratorów:
async function* asyncGenerator() {
for (let i = 0; i < 5; i++) {
yield new Promise(resolve =>
setTimeout(() => resolve(i * 2), 100)
);
}
}
// Tworzenie tablicy z async generatora
const results = await Array.fromAsync(asyncGenerator());
console.log(results); // [0, 2, 4, 6, 8]
// Z mapowaniem
const doubled = await Array.fromAsync(
asyncGenerator(),
x => x * 2
);
console.log(doubled); // [0, 4, 8, 12, 16]
Improved Error Cause - lepsze łączenie błędów
Nowe możliwości w konstruktorze Error pozwalają na lepsze śledzenie przyczyn błędów:
try {
throw new Error("Błąd w API", {
cause: "Brak połączenia z serwerem"
});
} catch (error) {
console.log(error.message); // "Błąd w API"
console.log(error.cause); // "Brak połączenia z serwerem"
// Ponowne rzucenie z dodatkowym kontekstem
throw new Error("Błąd w aplikacji", {
cause: error
});
}
WeakRef i FinalizationRegistry - zaawansowane zarządzanie pamięcią
Nowe API do precyzyjnego kontrolowania garbage collection:
class ResourceManager {
constructor() {
this.registry = new FinalizationRegistry((heldValue) => {
console.log(`Zwalnianie zasobu: ${heldValue}`);
// Cleanup logic
});
this.resources = new Map();
}
createResource(id, data) {
const resource = { id, data };
const ref = new WeakRef(resource);
this.resources.set(id, ref);
this.registry.register(resource, id);
return resource;
}
getResource(id) {
const ref = this.resources.get(id);
if (ref) {
const resource = ref.deref();
if (resource) {
return resource;
} else {
// Obiekt został usunięty przez GC
this.resources.delete(id);
}
}
return null;
}
}
String.prototype.at() - wygodniejszy dostęp do znaków
Nowa metoda pozwala na dostęp do znaków z użyciem indeksów ujemnych:
const text = "JavaScript";
// Tradycyjnie
console.log(text[text.length - 1]); // "t"
// Z metodą at()
console.log(text.at(-1)); // "t"
console.log(text.at(-2)); // "p"
console.log(text.at(0)); // "J"
// Działa również z tablicami
const arr = [1, 2, 3, 4, 5];
console.log(arr.at(-1)); // 5
Praktyczne zastosowania w projektach
1. Budowanie API klientów
class APIClient {
@logged
async fetchUser(id) {
return fetch(`/api/users/${id}`)
|> (response => response.json())
|> (data => new User(data));
}
match(response) {
case { status: 200, data: Object } => {
return this.processSuccess(data);
}
case { status: 404 } => {
throw new Error("Nie znaleziono użytkownika");
}
default => {
throw new Error("Nieznany błąd API");
}
}
}
2. Walidacja danych formularzy
const validateForm = data => data
|> (d => ({ ...d, email: d.email.trim().toLowerCase() }))
|> (d => match(d) {
case { email: String, age: Number } when d.age >= 18 => d,
default => { throw new Error("Nieprawidłowe dane formularza"); }
});
Wsparcie przeglądarek i narzędzia
Większość funkcji ES2025 jest już dostępna w:
- Chrome 95+
- Firefox 93+
- Safari 15+
- Node.js 18+
Do korzystania z najnowszych funkcji polecamy:
- Babel - transpilacja kodu
- TypeScript 4.8+ - wsparcie dla nowych funkcji
- ESLint - reguły dla nowej składni
Podsumowanie
ECMAScript 2025 wprowadza rewolucyjne zmiany, które znacznie poprawiają wydajność, czytelność i bezpieczeństwo kodu JavaScript. Funkcje takie jak pattern matching, pipeline operator czy niezmienne struktury danych przybliżają JavaScript do języków funkcyjnych, zachowując jednocześnie jego elastyczność.
Aby w pełni wykorzystać potencjał nowoczesnego JavaScript, warto systematycznie śledzić zmiany w języku i stopniowo wprowadzać nowe funkcje do swoich projektów.
Chcesz nauczyć się nowoczesnego JavaScript? Sprawdź nasz kurs JavaScript i React, gdzie poznasz wszystkie najnowsze funkcje języka!