All Articles

Nowości w standardzie ECMAScript 2020&2021

Pracując na co dzień w języku JavaScript oraz TypeScript staram się być na bieżąco z nowościami wprowadzanymi w nowych wersjach obu tych języków, tak aby zamiast korzystać z przestarzałych sposobów na rozwiązywanie pewnych problemów w kodzie - używać nowszych i sprytniejszych rozwiązań językowych.

Wersje EcmaScript numerowane jako 2020 oraz 2021 funkcjonują już dłuższy jakiś czas, a z ich dobrodziejstw możemy bez problemu korzystać w projektach pisanych za pomocą JavaScript.

Jako że sam już wykorzystałem kilka rozwiązań z najnowszych wersji, chciałbym je przedstawić tobie, a być może i ty znajdziesz miejsce na ich użycie podczas swojej pracy.

nullish coalescing ??

Operator podwójnego znaku zapytania. Sprawdza czy wartości są nullish (zerowe?) zamiast sprawdzać czy są falsey (fałszywe). Różnica między tymi dwoma typami wartości jest taka, że wartości falsey to 0, -0, undefined, null, false, NaN czy pusty string “ “ oraz kilka innych. Często jednak chcielibyśmy sprawdzić czy wartość jest rzeczywiście wartościa nullish czyli undefined lub null a nie obchodzi nas czy zmienna jest pustym stringiem lub wartością false.

Napisałem prostą funkcję, która przyjmuje jeden argument. Argument jest sprawdzany przy pomocy podwójnego znaku zapytania i rezultatem tej operacji w przypadku przekazanej wartości null lub undefined jest tekst 'argument someValue is either null or undefined'.

W przypadku podania czegoś innego co nie jest ani nullem ani undefined, zwracana jest ta wartość.

let someNull = null let someString = 'some string value' const testMyValue = someValue => someValue ?? 'argument someValue is either null or undefined' console.log(testMyValue(someString)) // "some string value" console.log(testMyValue(someNull)) // "argument someValue is either null or undefined"

Ale działa to także w wielu innych przypadkach gdzie chcemy przypisać do zmiennej jakąś wartość w przypadku gdy inna zmienna, do której się odnosimy będzie nullem lub undefined.

const searchParams = new URLSearchParams(window.location.search); const currentPage = parseInt(searchParams.get('page'), 10); const currentPaginationPage = currentPage ?? 0 // with ternary operator const currentPaginationPage = currentPage ? currentPage : 0

Promise.allSettled

Nowa metoda, która możemy wykorzystać gdy chcemy uruchomić kilka Promiseów na raz. Wcześniej musielibyśmy każdy Promise pakować osobno w blok .then, teraz możemy uruchomić wszystkie na raz i wykorzystać ich wynik w jakimś celu.

const promise1 = new Promise((res, rej) => setTimeout(res, 250)) const promise2 = new Promise((res, rej) => setTimeout(res, 450)) const promise3 = new Promise((res, rej) => setTimeout(res, 650)) Promise.allSettled([promise1, promise2, promise3]).then(res => res.forEach(res => console.log(res)))

Wcześniej co prawda była metoda .all, ale ona sprawiała że w momencie gdy któryś Promise nie powiódł się to automatycznie zwracany był tylko błąd dotyczący nieudanego Promisea.

Optional chaining

Kolejne ułatwienie, która pozwala sprawić że kod jest bardziej przejrzysty i nie wyrzuca niepotrzebnych błędów. Przejdę od razu do przykładu czyli zagnieżdżonego obiektu oraz if’a, w którym chcemy wylogować do konsoli nazwę samochodu, którego nie ma w obiekcie.

const obj = { data: { person: { name: 'Mateusz', country: 'Poland', id: 541234, } } } if (obj.data.car.name) { console.log(obj.data.car.name) }

Taki kod wyrzuci w konsoli następujący błąd.

error: Uncaught TypeError: Cannot read properties of undefined (reading 'name')

Aby temu zaradzić z reguły robi się sprawdzenie czy aby na pewno w obiekcie data jest zagnieżdżony obiekt car.

if (obj && obj.data && obj.data.car && obj.data.car.name) { console.log(obj.data.car.name) }

Na nasze szczęście w ES2020 został wprowadzony optional chaning, dzięki czemu nie musimy sprawdzać czy aby na pewno coś znajduje się w obiekcie, do którego próbujemy wejść.

if (obj.data.car?.name) { console.log(obj.data.car.name) }

Powyższy zapis jest tożsamy z poprzednim ifem.

.replaceAll

Nowość, która weszła nie w EcmScript2020 a już w EcmaScript2021. Pozwala na podmienianie wybranego elementu w ciągu znaków. Teraz można pomyśleć, że po co nam taka dodatkowa metoda skoro mamy już .replace. Niestety .replace podmienia tylko pierwszy napotkany ciąg znaków, a dla reszty musimy pisać wyrażenie regularne, które wyłapie wszystkie wybrane elementy.

const someString = 'Here is our new team member, Mateusz. Mateusz is React Developer with 5 years experience.' // .replace console.log(someString.replace('Mateusz', 'Tadeusz')) // Here is our new team member, Tadeusz. Mateusz is React Developer with 5 years experience. // .replaceAll console.log(someString.replaceAll('Mateusz', 'Tadeusz')) // Here is our new team member, Tadeusz. Tadeusz is React Developer with 5 years experience.

Promise.any

Kolejny dodatek do asynchronicznego JavaScriptu. Metoda .any sprawie że w rezultacie wykonania któregoś z dodanych Promiseów dodanych do metody, wywoływane są rzeczy dodane w callbacku.

const promise1 = new Promise((res, rej) => setTimeout(res('Promise1'), Math.floor(Math.random() * 1000))) const promise2 = new Promise((res, rej) => setTimeout(res('Promise2'), Math.floor(Math.random() * 1000))) const promise3 = new Promise((res, rej) => setTimeout(res('Promise3'), Math.floor(Math.random() * 1000))) async function callEveryPromise() { const result = await Promise.any([promise1, promise2, promise3]) console.log(result) }; callEveryPromise()

Podsumowanie

Oczywiście nowości, które weszły w obu najnowszych wersjach EcmaScript jest więcej, między innymi:

  • numeric separators
  • aggregate error
  • weak ref
  • zmiany w importowaniu modułów
  • bigInt
  • matchAll
  • operatory ??=, &&=, ||=

Osobiście skupiłem i starałem się wam przedstawić te elementy, które według mnie ja jestem na co dzień w stanie wykorzystywać i uważam za przydatne, a inne elementy pewnie też znajdą zastosowanie i warto wiedzieć że takie coś już istnieje w języku, w którym piszemy.