Wraz z wersją języka JavaScript ES6 dostaliśmy potężne narzędzia umożliwiające metaprogramowanie, a dokładnie podpinanie się pod wbudowane mechanizmy języka. W tym poście przedstawie jakie nowe funkcje weszły do ES6, które umożliwiają metaprogramowanie.
Do ES6 weszły dwa mechanizmy obiekt Proxy oraz symbole. Poniżej opis obu tych mechanizmów:
Symbole
Symbole to nowy typ danych wbudowanych, aby utworzyć symbol stosujemy:
to wywołanie za każdym razem utworzy nowy symbol, nawet jeśli użyjemy tej samej nazwy, tzn.:
zwróci wartość false
, czyli działa to tak jak funkcja gensym
z języka lisp. Jeśli jednak chcemy pobrać ten sam symbol możemy skorzystać z funkcji Symbol.for
:
powyższy kod z kolei zwróci wartość true
.
Można ich np. używać jako stałych do przechowywania wartości np. jeśli potrzebujemy utworzyć stałe, które określają typ:
możemy zamiast liczb lub stringów skorzystać z symboli:
Ciekawsze są jednak wbudowane Symbole, które można dodawać jako wartości obiektów. Działają one jak magiczne metody z Pythona lub PHP. Oto one:
Symbole do wyrażeń regularnych
Dają one możliwość używania dowolnego obiektu jak wyrażenia regularnego, czyli jako argument do metod obiektu string: split
, match
, search
, replace
Poniżej przykładowy kod obiektu, który działa dla każdej z tych funkcji:
Jest w tym kodzie trochę powtórzeń, na końcu artykułu będzie link do kodu na Codepen, gdzie użyłem funkcji wyższego poziomu (ang. Higher Order Function) aby utworzyć wszystkie 4 funkcje w pętli.
Aby użyć danej funkcji tworzymy nowy obiekt tej „klasy” (osobiście nie przepadam za nowym tworzeniem klas za pomocą słowa kluczowego class
i nadal tworze zwykłe funkcje) np:
wynikiem będzie:
["ssss"]
null
"__www_x__"
["foo","bar","baz"]
Symbol iteracji
Symbol.iterator
to symbol, który daje nam możliwość podpięcia się pod pętle for..of
(to nowa pętla służąca do iterowania po obiektach takich jak Array, Map, Set, String, TypedArray, arguments). Poniżej krótki kod, który dodaje możliwość iterowania po obiekcie Todos:
w tej „klasie” użyto funkcji generatora (gwiazdka) oraz słowa kluczowego yield nowe w ES6. Mając instancje tej funkcji/klasy można użyć pętli for..of
aby iterować po wartościach todo:
Symbol.species
To symbol, który służy do podpięcia się pod tworzenie nowego obiektu tego samego typu np. w funkcji map:
Tutaj skorzystałem z klas bo chyba nie da się za pomocą zwykłych funkcji stworzyć klasę pochodną po obiekcie Array
.
Gdyby nie było Symbol.species
tylko ostatnia wartość byłaby prawdziwa.
Konwersja typów
Mamy możliwość podpięcia się pod automatyczne konwertowanie typów JavaScript. Służy do tego symbol Symbol.toPrimitive
:
Niestety dodanie do liczby albo do łańcucha znaków nie przekazuje wartości 'number'
i 'string'
tylko wartość 'default'
przynajmniej w przeglądarkach Chromium i Chrome.
Proxy
Drugim elementem języka, dającym możliwości metaprogramowania, są obiekty typu proxy. Są to obiekty, które są pośrednikami dla jakieś innego obiektu. Obiekt proxy posiada tzw. pułapki (ang. trap), które dają możliwość podpięcia się pod pobieranie wartości obiektu, przypisanie wartości, usuwanie wartości, użycie operatora new (możemy używać obiektu proxy jako konstruktora/klasy) oraz wywołania jak funkcji (ten ostatni wymaga aby obiektem, dla którego tworzony jest proxy, była funkcja - może być pusta). Poniżej funkcja, która tworzy nowy obiekt proxy dla każdego wymienionych pułapek:
zauważ że nie przekazujemy oryginalnego obiektu do konstruktora proxy tylko korzystamy z domknięcia, zazwyczaj korzysta się z obiektu proxy w ten sposób:
Funkcji proxify można użyć w ten sposób:
Dzięki temu że pułapka construct zwraca nowy obiekt proxy można używać takich dziwnych konstrukcji:
Jeśli zastanawiasz się czy można łączyć obiekt proxy z symbolami, odpowiedź brzmi tak. Aby dodać metodę symbolu do obiektu Proxy, trzeba skorzystać z pułapki get
i sprawdzać czy jest to odpowiedni symbol. Jeśli tak to zwracać odpowiednią funkcje np. poniżej nasza poprzednia funkcja z dodanym symbolem Symbol.toPrimitive
:
Możesz zobaczyć wsparcie dla zdefiniowanych symboli na stronie kangax.github.io/compat-table/es6. Wszystkie nowoczesne przeglądarki przeszły testy oprócz IE oraz Edge.
Wsparcie dla obiektu Proxy możesz zobaczyć na Can I Use podobnie jak z Symbolami ale tym razem w Edge są dostępne, IE niestety ich nie posiada.
I jak obiecałem link do dema na Codepen.
Komentarze
Hasło, które podasz umożliwi ponowne zalogowanie się i np. usunięcie komentarza, jest dobrowolne. Email jest szyfrowany i używany do wysyłania powiadomień o odpowiedziach do komentarzy oraz do pobierania awatara dzięki usłudze Gravatar.com.