JavaScript nieustannie ewoluuje, wprowadzając nowe funkcje, które ułatwiają życie programistom. ES2025 przynosi kolejne przydatne dodatki do języka. Poznaj najważniejsze nowoczesne funkcje JavaScript, które powinieneś znać jako developer.
1. Optional Chaining (?.) - Bezpieczny dostęp do właściwości
Optional chaining to jedna z najczęściej używanych nowoczesnych funkcji JavaScript:
// Stary sposób
if (user && user.address && user.address.street) {
console.log(user.address.street);
}
// Nowoczesny sposób
console.log(user?.address?.street);
// Z metodami
user?.getName?.();
Korzyści:
- Krótszy i czytelniejszy kod
- Brak błędów TypeError
- Łatwiejsze debugowanie
2. Nullish Coalescing (??) - Inteligentne wartości domyślne
Operator ?? sprawdza tylko null i undefined, ignorując falsy values jak 0 czy '':
// Problem z ||
const width = settings.width || 500; // 0 zostanie zamienione na 500!
// Rozwiązanie z ??
const width = settings.width ?? 500; // 0 pozostanie 0
// Praktyczne zastosowania
const name = user.name ?? 'Anonymous';
const timeout = config.timeout ?? 3000;
3. Destructuring - Wydobywanie wartości
Destructuring pozwala na eleganckie wydobywanie wartości z obiektów i tablic:
// Obiekty
const { name, age, email } = user;
const { name: userName, age = 18 } = user; // aliasy i domyślne
// Tablice
const [first, second, ...rest] = numbers;
const [, , third] = arr; // pomijanie elementów
// Zagnieżdżone
const { address: { street, city } } = user;
// W parametrach funkcji
function createUser({ name, age = 18, email }) {
return { name, age, email };
}
4. Spread i Rest (...) - Uniwersalny operator
Operator trzech kropek ma różne zastosowania w zależności od kontekstu:
// Spread w tablicach
const newArray = [...oldArray, newItem];
const combined = [...array1, ...array2];
// Spread w obiektach
const updatedUser = { ...user, age: 25 };
const merged = { ...defaults, ...userConfig };
// Rest w funkcjach
function sum(...numbers) {
return numbers.reduce((a, b) => a + b, 0);
}
// Rest w destructuring
const { id, ...userData } = user;
5. Async/Await - Czytelne operacje asynchroniczne
Async/await to rewolucja w obsłudze operacji asynchronicznych:
// Stary sposób z Promises
fetchUser(id)
.then(user => fetchPosts(user.id))
.then(posts => console.log(posts))
.catch(error => console.error(error));
// Nowoczesny sposób
async function getUserPosts(id) {
try {
const user = await fetchUser(id);
const posts = await fetchPosts(user.id);
return posts;
} catch (error) {
console.error('Error:', error);
}
}
// Równoległe operacje
async function getMultipleData() {
const [users, posts, comments] = await Promise.all([
fetchUsers(),
fetchPosts(),
fetchComments()
]);
}
6. Template Literals - Inteligentne stringi
Template literals oferują znacznie więcej niż standardowe stringi:
// Podstawowe użycie
const message = `Hello, ${name}! You have ${count} messages.`;
// Multiline stringi
const html = `
<div class="user-card">
<h2>${user.name}</h2>
<p>${user.email}</p>
</div>
`;
// Tagged templates
function highlight(strings, ...values) {
return strings.reduce((result, string, i) => {
const value = values[i] ? `<mark>${values[i]}</mark>` : '';
return result + string + value;
}, '');
}
const highlighted = highlight`Search for ${term} found ${count} results`;
7. Array Methods - Potężne metody tablicowe
Nowoczesne metody do pracy z tablicami znacznie upraszczają kod:
// map - transformacja
const userNames = users.map(user => user.name);
// filter - filtrowanie
const activeUsers = users.filter(user => user.isActive);
// find - znajdowanie
const user = users.find(user => user.id === targetId);
// reduce - redukcja
const totalAge = users.reduce((sum, user) => sum + user.age, 0);
// some/every - warunki
const hasAdults = users.some(user => user.age >= 18);
const allActive = users.every(user => user.isActive);
// flatMap - spłaszczenie i mapowanie
const allTags = posts.flatMap(post => post.tags);
8. Modules (ES6) - Organizacja kodu
System modułów pozwala na lepszą organizację kodu:
// Eksport
export const API_URL = 'https://api.example.com';
export function fetchData(url) { /* ... */ }
export default class UserService { /* ... */ }
// Import
import UserService, { API_URL, fetchData } from './userService.js';
import * as utils from './utils.js';
// Dynamic imports
const module = await import('./dynamicModule.js');
const { heavyFunction } = await import('./heavyModule.js');
9. Proxies - Metaprogramowanie
Proxy pozwala na przechwytywanie i definiowanie własnych operacji na obiektach:
// Logging proxy
const user = new Proxy(originalUser, {
get(target, prop) {
console.log(`Getting property: ${prop}`);
return target[prop];
},
set(target, prop, value) {
console.log(`Setting ${prop} to ${value}`);
target[prop] = value;
return true;
}
});
// Validation proxy
const validatedUser = new Proxy({}, {
set(target, prop, value) {
if (prop === 'age' && value < 0) {
throw new Error('Age cannot be negative');
}
target[prop] = value;
return true;
}
});
10. Nowe metody String
ES2025 wprowadza nowe przydatne metody do pracy ze stringami:
// padStart/padEnd
const id = '123';
const paddedId = id.padStart(6, '0'); // '000123'
// includes/startsWith/endsWith
const filename = 'document.pdf';
const isPDF = filename.endsWith('.pdf');
// repeat
const divider = '-'.repeat(20);
// trimStart/trimEnd
const cleaned = ' hello '.trimStart(); // 'hello '
11. Object.entries() i Object.fromEntries()
Przydatne metody do pracy z obiektami:
// Object.entries
const user = { name: 'John', age: 30, city: 'Warsaw' };
const entries = Object.entries(user);
// [['name', 'John'], ['age', 30], ['city', 'Warsaw']]
// Filtrowanie właściwości obiektu
const filtered = Object.fromEntries(
Object.entries(user).filter(([key, value]) => typeof value === 'string')
);
// Transformacja wartości
const upperCased = Object.fromEntries(
Object.entries(user).map(([key, value]) => [key, String(value).toUpperCase()])
);
12. WeakMap i WeakSet - Pamięć bezpieczne kolekcje
WeakMap i WeakSet pozwalają na przechowywanie danych bez blokowania garbage collection:
// WeakMap dla prywatnych danych
const privateData = new WeakMap();
class User {
constructor(name, secret) {
this.name = name;
privateData.set(this, { secret });
}
getSecret() {
return privateData.get(this).secret;
}
}
// WeakSet dla śledzenia obiektów
const processedItems = new WeakSet();
function processItem(item) {
if (processedItems.has(item)) return;
// proces...
processedItems.add(item);
}
Best Practices dla nowoczesnego JavaScript
1. Używaj const i let zamiast var
// ✅ Dobrze
const API_URL = 'https://api.example.com';
let currentUser = null;
// ❌ Unikaj
var globalVariable = 'something';
2. Preferuj arrow functions dla krótkich funkcji
// ✅ Dobrze
const multiply = (a, b) => a * b;
const users = data.map(user => ({ ...user, active: true }));
// ✅ Dla funkcji z this
class Component {
handleClick = () => {
this.setState({ clicked: true });
}
}
3. Używaj default parameters
// ✅ Dobrze
function createUser(name, age = 18, role = 'user') {
return { name, age, role };
}
// ✅ Z destructuring
function processConfig({ timeout = 5000, retries = 3 } = {}) {
// ...
}
Narzędzia dla nowoczesnego JavaScript
- Babel - transpilacja najnowszych funkcji
- ESLint - linting z nowoczesnymi regułami
- Prettier - formatowanie kodu
- TypeScript - static typing dla JavaScript
- Vite/Webpack - modern bundling
Wsparcie przeglądarek
Większość nowoczesnych funkcji JavaScript jest wspierana przez:
- Chrome/Edge - pełne wsparcie ES2025
- Firefox - bardzo dobre wsparcie
- Safari - dobre wsparcie z niewielkim opóźnieniem
- Node.js - najnowsze wersje wspierają ES2025
Podsumowanie
Nowoczesne funkcje JavaScript znacznie upraszczają pisanie kodu i poprawiają jego czytelność. Kluczem jest systematyczne wprowadzanie nowych pattern do swojego stylu kodowania. Zacznij od podstawowych funkcji jak optional chaining i destructuring, a następnie eksploruj bardziej zaawansowane możliwości.
Chcesz opanować nowoczesny JavaScript? Dołącz do naszych kursów i naucz się od ekspertów branży.