Co nowego w

ECMAScript 2020

Zmiany i nowości w najnowszej wersji ECMAScript 2020 (ES11).

W zamianach najnowszej wersji ES2020 znalazły się:

  • Dynamiczny import
  • Metoda Promise.allSettled
  • Operator Nullish coalescing
  • Operator Optional Chaining
  • Globalny obiekt globalThis
  • Nowy typ BigInt
  • Metoda String.protype.matchAll
  • Standaryzacja mechanizmu pętli for-in

Dynamiczny import

Dynamiczny import jest przydatną funkcjonalnością, która pozwala zmniejszyć czas pierwszego ładowania aplikacji. Dzieje się tak dzięki temu, że moduł zaimportowany dynamicznie jest ładowany dopiero w momencie kiedy jest potrzebny (w trakcie działania aplikacji), a nie podczas pierwszego ładowania.

Dynamiczny import pozwala zmniejszyć początkowy czas ładowania aplikacji, poprzez rozpoczęcie pobierania modułu dopiero w momencie kiedy jest potrzebny.

Przykładem użycia może być routing, gdzie kod potrzebny dla każdej strony możemy importować dynamicznie dopiero w momencie przejścia na nią, zamiast pobierać kod wszystkich stron przy początkowym załadowaniu strony.

Metoda import() zwraca Promise, której wynikiem będzie importowany moduł.

const calculateAverageAsync = async (a: number, b: number): Promise<number> => {
  const calculateAverage = await import('./calculateAverage');
  const average = calculateAverage(a, b);

  return average;
}

Metoda Promise.allSettled

Dotychczas dostępna metoda do obsługi kilku Promise o nazwie Promise.all jest przerywana i nie czeka na rezultat innych obietnic, kiedy jakikolwiek z podanych Promise zakończył się niepowodzeniem i wyrzucił błąd.

Nowa metoda Promise.allSettled pozwala na odczytanie rezultatu ze wszystkich Promise które przyjęła, nawet jeśli jakikolwiek Promise zakończył się wystąpieniem błędu.

Rezultatem nowej metody jest tablica z obiektami, które w zależności od statusu zakończenia danego Promise, zawierają pole value przy statusie fullfilled (spełnione), lub reason przy rejected (odrzucone).

Promise
  .allSettled([
    fetch('yourapi.com/users'),
    fetch('yourapi.com/posts'),
  ])
  .then(results => {
    // Przykładowy obiekt o statusie 'fulfilled' (brak błędu).
    { status: 'fulfilled', value: [{ userId: 1, name: 'John' }] }

    // Przykładowy obiekt o statusie 'rejected' (błąd).
    { status: 'rejected', reason: "Server Error" }
  })

Operator Nullish coalescing

Nowy operator nullish coalescing znajduje zastosowanie przy podawaniu wartości domyślnej, gdy tworzymy zmienną opartą na innej wartości.

Podanie wartości domyślnej powoduje, że zostanie ona użyta w momencie kiedy pierwotna wartość będzie typu nullary (null lub undefined) np. niezdefiniowana.

Dotychczas udawało się to osiągnąć za pomocą operatora logicznego OR ||.

const user = {
  name: null
};

const userName = user.name || 'admin';

Rozwiązanie z użyciem tego operatora może jednak powodować błędy, gdyż działa on nie tylko na wartości typu nullary, lecz również na inne fałszywe wartości (generujące logiczny fałsz) np. pusty string, czy 0;

Nullish coalescing w przeciwieństwie do operatora || działa jedynie na wartości typu null, oraz undefined.

Operator Optional Chaining

W JavaScript odczytywanie właściwości z wartości undefined lub null (typ nullary) skutkuje wyrzuceniem błędu: TypeError: Cannot read property {nazwa właściwości} of undefined. ES2020 dostarcza nam bardzo przydatną funkcjonalność, która pozwala na bezpieczne odczytywanie właściwości obiektu.

Odczytanie właściwości z wartości typu null lub undefined nie skutkuje wyrzuceniem błędu.

const user = {
  images: null
}

// Próba odczytania właściwości `avatar` z właściwości `images`,
// nie spowoduje wyrzuceniem błędu.
const userAvatar = user.images?.avatar; // null

Ciekawym przykładem zastosowania operatora optional chaining są opcjonalne propsy w React.js. Dzięki nowemu operatorowi możemy również bezpiecznie wywoływać metody, które mogą być niezdefiniowane, a operator zapewnia nam że metoda zostanie wywołana tylko jeśli wartość nie jest typu nullable. Wywołując metodę tym sposobem, musimy dodać znak ?. tuż przed nawiasem wywoływanej metody np:

interface ButtonProps {
  onClick?: () => void
}

const Button = (props: ButtonProps) => {
  return (
    <button onClick={() => props.onClick?.()}>
      Kliknij
    </button>
  );
}

Rozwiązanie bez użycia operatora optional chaining wyglądałoby tak:

<button onClick={() => props.onClick && props.onClick()}>

Globalny obiekt globalThis

ES11 dodaje nowy obiekt globalny o nazwie globalThis, który niezależnie od środowiska np. Node.js (global), czy przeglądarka (window) wskazuje na prawidłowy obiekt globalny.

Nowy typ BigInt

Nowy typ jest typem prymitywnym pozwalającym na tworzenie liczb większych niż 9007199254740991 (2^53). Wartość typu BigInt tworzymy dodając na końcu liczby literę n lub wywołując funkcję BigInt().

const firstBigInt = 123623232140991192n;
const secondBigInt = BigInt(783781048172569067);

Największą bezpieczną wartość liczbową możemy odczytać odnosząc się do stałej Number.MAX_SAFE_INTEGER.

Metoda String.protype.matchAll

Nowa metoda matchAll() zwraca obiekt typu iterator zawierający rezultat wyników, które spełniły warunek wyrażenia regularnego włącznie z capturing groups (wyrażenia zamknięte w nawiasach (...)).

Standaryzacja mechanizmu pętli for-in

Najnowsza wersja ECMAScript standaryzuje sposób odczytywania właściwości obiektu podczas iteracji pętli for-in i jest istotna z perspektywy twórców przeglądarek.

AL.
Github