Miniatura artykułu

Nowości w ECMAScript 2025

10+ minut

Skopiuj link

Data publikacji: 01.10.2025 10:26

Ostatnia aktualizacja: 01.10.2025

Najnowsza specyfikacja ECMAScript ujrzała światło dzienne w Lipcu, a większość zaproponowanych nowości jest już wspierane przez duże przeglądarki. Nadszedł zatem czas, żeby przyjrzeć się zmianom, które wnoszą najwięcej do naszej codziennej pracy.

Promise.try()

Większość z nas spotkała się z sytuacją, w której trzeba było opakować synchroniczny kod w Promise, żeby ujednolicić obsługę błędów. Było to niemal niezbędne, gdy część kodu działała synchronicznie, a część asynchronicznie, co wymagało dwóch różnych sposobów obsługi błędów. Najnowsza specyfikacja daje nam do dyspozycji nową, statyczną metodę w obiekcie Promise, która rozwiązuje ten problem.

Promise.try() przyjmuje funkcję jako argument i wykonuje ją natychmiast (synchronicznie), a dodatkowo obsługuje wszystkie możliwe rezultaty:

  • Jeśli funkcja zwraca wartość, Promise.try() zwraca obietnicę (promise), która zostaje spełniona (resolved) z tą wartością.

  • Jeśli w wyniku działania przekazanej funkcji, zostaje zgłoszony synchroniczny błąd, to Promise.try() przechwytuje ten błąd i zwraca obietnicę, która zostaje odrzucona (rejected).

  • Jeśli funkcja zwraca obietnicę, Promise.try() zwróci obietnicę w tym samym stanie.

Nowe metody obiektu Set

W JavaScript, Set stosuje się do przechowywania unikalnych wartości. Mimo że posiada on kilka podstawowych metod, to do tej pory brakowało mu możliwości, które dają inne języki programowania. Tegoroczna specyfikacja rozwiązuje ten problem i wprowadza kilka znanych z matematyki, operacji na zbiorach, takich jak suma czy iloczyn (część wspólna).

Do tej pory, aby znaleźć część wspólną dwóch zbiorów, musieliśmy pisać własne funkcje pomocnicze. Obecnie możemy to zrobić w znacznie łatwiejszy sposób.

Pełna lista nowych metod, wraz z opisem:

  • union: zwraca nowy zbiór zawierający wszystkie unikalne elementy obecne w oryginalnym zbiorze lub w drugim zbiorze. (Suma zbiorów)

  • intersection: zwraca nowy zbiór zawierający tylko te elementy, które są obecne zarówno w oryginalnym zbiorze, jak i w drugim zbiorze. (Część wspólna / Iloczyn zbiorów)

  • difference: zwraca nowy zbiór zawierający elementy, które są obecne w oryginalnym zbiorze, ale nie ma ich w drugim zbiorze. (Różnica zbiorów)

  • symmetricDifference: zwraca nowy zbiór zawierający elementy, które są obecne w oryginalnym zbiorze lub w drugim zbiorze, ale nie w obu jednocześnie. (Różnica symetryczna zbiorów)

  • isSubsetOf: zwraca true, jeśli każdy element oryginalnego zbioru jest również obecny w drugim zbiorze. (Czy jest podzbiorem)

  • isSupersetOf: zwraca true, jeśli każdy element drugiego zbioru jest również obecny w oryginalnym zbiorze. (Czy jest nadzbiorem)

  • isDisjointFrom: zwraca true, jeśli oba zbiory nie mają żadnych wspólnych elementów (ich część wspólna jest pusta). (Czy jest zbiorem rozłącznym)

Iterator Helpers

Iteratory to jeden z najważniejszych konceptów w JavaScript. Problem w tym, że często wymaga konwersji obiektu iterowalnego do tablicy. Obiekt ten implementuje Symbol.iterator (o symbolach pisałem w osobnym artykule). Wszystko po to, żeby móc skorzystać z dobrodziejstw metod takich jak map() czy filter(). To z kolei generuje niepotrzebne operacje, a tym samym zwiększa zużycie pamięci i spowalnia aplikację (zwłaszcza w przypadku dużych zbiorów danych).

ES2025 wprowadza Iterator Helpers, czyli zestaw metod, które możemy wywoływać bezpośrednio na iteratorach.

Co ważne, metody takie jak map(), filter(), take(), drop(), reduce() i forEach() działają "leniwie" (lazy), co oznacza, że operacje są wykonywane dopiero w momencie, gdy zażądamy wartości (np. przez toArray() lub pętlę for...of).

Pełna lista nowych metod, wraz z opisem:

  • map(callback): zwraca nowy iterator, który zawiera elementy ze źródłowego iteratora przekształcone za pomocą funkcji callback. 

  • filter(callback): zwraca nowy iterator, który zawiera tylko te elementy z iteratora źródłowego, dla których funkcja callback zwraca wartość true (lub truthy).

  • flatMap(callback): Połączenie metod map i flat. Wykonuje przekazaną funkcję na każdym elemencie (zwróconą wartością powinien być również obiekt iterowalny), a następnie sekwencyjnie generuje elementy z każdego zwróconego obiektu iterowalnego. 

  • take(limit): Zwraca nowy iterator, który generuje co najwyżej tyle elementów  z iteratora źródłowego, ile wskazuje limit. Jest to szczególnie przydatne do skracania nieskończonych iteratorów.

  • drop(limit): Zwraca nowy iterator, który pomija limit pierwszych elementów iteratora źródłowego, a następnie generuje wszystkie kolejne elementy.

  • some(callback): Zwraca true, jeśli callback zwróci wartość true (lub truthy) dla co najmniej jednego elementu. W przeciwnym razie zwraca false. Przerywa działanie po znalezieniu pierwszego dopasowania.

  • every(callback): Zwraca true, jeśli callback zwróci wartość true (lub truthy) dla wszystkich elementów. W przeciwnym razie zwraca false. Przerywa działanie przy pierwszym niepowodzeniu.

  • find(callback): Zwraca pierwszy element, dla którego callback zwróci wartość true (lub truthy). Zwraca undefined, jeśli żaden taki element nie zostanie znaleziony.

  • reduce(callback, initialValue): Stosuje funkcję callback dla akumulatora i każdego elementu, aby zredukować iterator do pojedynczej wartości.

  • forEach(callback): wykonuje funkcję callback dla każdego elementu iteratora.

  • toArray(): "zużywa" cały iterator i zwraca nową tablicę zawierającą wszystkie wygenerowane przez niego elementy.

Import Attributes i natywne moduły JSON

Ładowanie plików JSON jako modułów było do tej pory możliwe głównie dzięki bundlerom, takim jak Webpack czy Rollup. Żadna z wiodących przeglądarek nie wspierała natywnego wczytywania pliku o rozszerzeniu json, w postaci modułu. ES2025 wprowadza Import Attributes, czyli sposób na określenie typu importowanego zasobu, otwierając tym samym drogę dla natywnego wsparcia modułów JSON.

Składnia with { type: "json" } informuje silnik JavaScript, jak ma zinterpretować dany plik. Takie rozwiązanie ma dwie zalety:

  • Zwiększa bezpieczeństwo: wiele podatności wynika z pomyłek w typach MIME. Błędnie skonfigurowany lub przejęty serwer WWW mógłby dostarczyć plik z rozszerzeniem .json, ale z nagłówkiem HTTP Content-Type: text/javascript. Bez jawnego zadeklarowania typu po stronie frontendu, przeglądarka wykorzysta typ MIME dostarczony przez serwer. W efekcie może podjąć próbę wykonania zawartości pliku jako kodu JavaScript. Gdyby atakujący był w stanie wstrzyknąć do tego pliku złośliwy kod, stworzyłoby to podatność na ataki Cross-Site Scripting (XSS). Atrybut with { type: "json" } instruuje silnik JavaScript, aby traktował zasób jako dane JSON i zgłosił błąd, jeśli serwer dostarczy sprzeczny, wykonywalny typ MIME.

  • Zmniejsza potrzebę używania bundlerów: współczesne strony internetowe w zdecydowanej większości wymagają wykorzystania bundlerów. Częściowo jest to spowodowane faktem, że JavaScript nie wspiera importowania popularnych zasobów innych niż JavaScript (takich jak np. JSON) w postaci modułu. Najnowsza specyfikacja ECMAScript stara się ustandaryzować sposób ich wczytywania przenosząc tym samym odpowiedzialność z bundlerów na silniki JS. Jest to kolejny krok w kierunku aplikacji buildless, czyli takich, które nie wymagają kroku związanego z ich zbudowaniem.

Usprawnienia w Wyrażeniach Regularnych

Wyrażenia regularne również doczekały się kilku istotnych ulepszeń, które ułatwią tworzenie bardziej skomplikowanych (na wypadek gdyby regex nie był już wystarczająco skomplikowany) i czytelnych wzorców.

Najważniejszą zmianą jest dodanie nowej metody RegExp.escape(). Jej celem jest "oczyszczenie" tekstu przekazywanego do wyrażenia regularnego. Zapobiega to błędom i atakom typu ReDoS (Regular Expression Denial of Service).

Kolejna zmiana to możliwość stosowania flag (np. i dla ignorowania wielkości liter) tylko do fragmentu wyrażenia regularnego. Funkcjonalność ta jest znana pod nazwą inline flags i wygląda następująco: (?<flaga>:<regex>). W praktyce oznacza to, że możemy pisać wyrażenia, które sprawdzają np. wielkość liter w środku ciągu znaków.

Dodatkowo dostaliśmy do dyspozycji nową flagę v, która jest niejako rozszerzeniem istniejącej już flagi u (wsparcie dla unicode w regex). Jej głównym zastosowaniem jest wykonywanie operacji na klasach znaków ([...]), takich jak znajdowanie części wspólnych. 

Float16Array TypedArray

JavaScript nigdy nie należał do najbardziej wydajnych języków pod względem zużycia pamięci. Ten problem jest szczególnie widoczny podczas pracy z liczbami - JS posiada tylko jeden typ liczbowy i wykorzystuje on aż 64 bity. Od jakiegoś czasu mamy również do dyspozycji Float32Array, który w pewnym stopniu pozwalał kontrolować, jak dużo bitów zostanie wykorzystanych do przechowywania liczb. 

ES2025 idzie o krok dalej i daje nam do dyspozycji typ Float16Array. Jak sama nazwa wskazuje, pozwala ona na stworzenie tablicy, w której każda liczba zajmuje 16 bitów. Daje to jeszcze większą kontrolę nad zużyciem pamięci.

Oczywiście nie ma nic za darmo. Mniej wykorzystanej pamięci oznacza mniejszą precyzję i mniejszy zakres liczb, które możemy przechowywać w danej tablicy. W tabeli pod spodem porównałem poszczególne typy i ich możliwości.


Float16Array

Float32Array

Float64Array (standard)

Bajty wykorzystywane przez jeden element

2

4

8

Zakres liczb

(w przybliżeniu)

±65,504

±3.4×1038

±1.8×10308

Precyzja dziesiętna

(w przybliżeniu)

~3 liczby dziesiętne

~7 liczb dziesiętnych

~15 liczb dziesiętnych

Przykładowe zastosowanie

Tekstury GPU, modele ML, wszystkie inne operacje, gdzie pamięć i przepustowość są kluczowe

Grafika ogólnego przeznaczenia, symulacje fizyczne, standardowe obliczenia na GPU

Obliczenia naukowe o wysokiej precyzji, obliczenia finansowe, domyślne operacje numeryczne w pamięci

Podsumowanie

ECMAScript 2025 przynosi szereg praktycznych i wyczekiwanych ulepszeń. Od uproszczenia pracy z asynchronicznością i iteratorami, przez potężne narzędzia do operacji na zbiorach, aż po usprawnienia w imporcie modułów i wyrażeniach regularnych.

Choć na pełne wsparcie we wszystkich przeglądarkach i środowiskach będziemy musieli jeszcze chwilę poczekać, warto już teraz zapoznać się z nadchodzącymi zmianami. Pozwoli to nie tylko pisać lepszy i bardziej nowoczesny kod w przyszłości, ale także lepiej zrozumieć kierunek, w którym zmierza JavaScript. To ewolucja, która sprawia, że język staje się coraz bardziej dojrzały, wydajny i przyjazny programistom.

Avatar: Wojciech Rygorowicz

Software Engineer

Wojciech Rygorowicz

pogadajmy@wojciechrygorowicz.pl

Podziel się na

Dodaj komentarz

Komentarze (0)

Brak komentarzy