Symbole
Typ danych symbol to prymitywny typ danych, który zawsze zawiera unikalną wartość. Nie wiemy ile ona wynosi, wiemy jedynie to, że jest unikalna, niepowtarzalna. Aby wygenerować taką wartość, posłużymy się funkcją Symbol():
const sym = Symbol();
console.log(typeof sym); //symbolPodczas generowania symbolu możemy podać dodatkową opcjonalną wartość, która będzie opisem danego symbolu. Opis ten nie zmienia wartości, a najczęściej używany jest do celów debugowania.
const a = Symbol("foo");
const b = Symbol("foo");
console.log(a === b); //falseZastosowanie
Symbole przydają się w sytuacjach gdzie chcemy dodawać do obiektów dodatkowe funkcjonalności, a równocześnie nie chcemy się martwić o to, że przypadkowo w takim obiekcie coś nadpiszemy.
const a = "pet";
const sym1 = Symbol();
const ob = {
[a] : "pies",
[sym1] : "nowa ważna wartość",
};
console.log( ob[a], ob.pet, ob["pet"], ); //"pies", "pies", "pies"
//W przypadku symbolu nie znamy wartości, jedyną możliwością jest użycie danego symbolu
console.log( ob[sym1] ) //"nowa ważna wartość"Właściwości kryjące się za symbolem nie są dodatkowo iterowalne, więc idealnie nadają się do tworzenia "ukrytych" właściwości:
Może się zdarzyć sytuacja, że nie będziemy mieli zmiennej z danym symbolem.
Podstawiając pod tą samą zmienną drugi symbol straciliśmy odniesienie do pierwszego.
W takiej sytuacji możemy skorzystać z metody Object.getOwnPropertySymbols(ob), która zwraca symbole użyte w danym obiekcie:
Globalny rejestr symboli
Globalny rejestr symboli to takie miejsce, w którym możemy przechowywać globalne symbole, które są dostępne dla wszystkich skryptów (ale też oddzielnych środowisk, gdzie każde ma swój główny obiekt).
Może to przyrównać do listy, w której zapisujemy symbole, a dzięki temu możemy się do nich odwoływać z każdego miejsca.
Do manipulacji symbolami w tym rejestrze mamy 2 funkcje:
Symbol.keyFor(variable)
Jeżeli dana zmienna wskazuje na symbol, możemy pobrać jego klucz z globalnego rejestru (lub undefined, jeżeli go tam nie ma)
Dobrze znane symbole
Javascript zawiera kilka wbudowanych symboli, które zwą się "well know symbols.
Wprowadzają one dodatkowe funkcjonalności do istniejących od lat obiektów, ale też pozwalają modyfikować zachowanie niektórych działań jakie wykonujemy na co dzień.
Kryją się one jako właściwości funkcji Symbol(). Ich pełną listę znajdziesz na stronie MDN. W przeglądarce Firefox możesz też w konsoli wpisać nazwę funkcji Symbol, po czym zbadać jej wygląd: 
Te najczęściej używane to:
Symbol.hasInstance
Symbol.toPrimitive
Symbol.isConcatSpreadable
Symbol.iterator
Dla uproszczenia symbole takie mają też skrótowe nazwy poprzedzone @@nazwa. I tak Symbol.hasInstance w skrócie nazywa się @@hasInstance, Symbol.iterator to @@iterator itp.
Do czego one służą? A właśnie sobie je omówimy.
Symbol.hasInstance
W rozdziale o dziedziczeniu w Javascript sprawdzaliśmy czy dana instancja jest egzemplarzem danej klasy za pomocą konstrukcji instanceof. Za pomocą tego symbolu możemy zmienić działanie operatora instanceof dla danej klasy:
Tablica oczywiście nie jest instancją klasy Car. Dzięki powyższemu symbolowi możemy dodać własny warunek testujący:
Symbol.toPrimitive
Innymi dość ciekawymi Symbolem jest Symbol.toPrimitive. Opisuje go dobrze artykuł pod adresem https://blog.comandeer.pl/kwacze-jak-kaczka.html.
Używając obiektów dość często zachodzi konieczność konwersji ich na typy prymitywne. W przypadku boolean (np. obiekt stosowany jako wyrażenie wewnątrz funkcji if) obiekty zawsze zwracają true. Podczas innych operacji może zajść potrzeba konwersji na typ string lub number.
Robiąc taką konwersję, Javascript stara się wykryć na jaki typ ma przeprowadzić konwersję. Preferowany wariant konwersji zwany "hint" może przyjąć trzy wartości: "string", "number" lub "default".
Domyślnie do takiej konwersji wykorzystywane są 2 funkcje: toString() oraz valueOf(), które każdy obiekt dziedziczy z prototypu wszystkich obiektów czyli Object.prototype. Funkcja toString() zwraca obiekt w postaci tekstu [object Object]. Funkcja valueOf() w większości przypadków zwraca obiekt sam w sobie:
Podczas konwersji funkcje te odpalane są w kolejności toString(), valueOf() jeżeli "hint" wynosi "string", oraz w przeciwnej jeżeli "hint" wynosi inną wartość. Oznacza to, że w większości przypadków wynikiem konwersji będzie string, natomiast w nielicznych sytuacjach dostaniemy NaN gdy obiekt ma być skonwertowany na liczbę (ale nie zawsze, bo np. gdy odejmujemy od siebie datę, wynik będzie liczbą).
Dzięki omawianemu symbolowi możemy dodać własną metodę, która będzie wykorzystywana przy konwersji.
Symbol.isConcatSpreadable
Podczas łączenia dwóch tablic za pomocą concat() ich elementy są rozbijane na poszczególne kawałki.
Dzięki temu symbolowi możemy włączyć lub wyłączyć rozbijanie danego obiektu na poszczególne części:
Dla obiektów tablico podobnych (np. kolekcje elementów pobranych ze strony) zastosowanie tego symbolu umożliwi nam sprawienie, że podczas concatowania dana kolekcja będzie rozbijana na poszczególne elementy:
Symbol.iterator
Jak wiemy, bez problemu możemy robić klasyczne pętle for, a dzięki nim wyciągać poszczególne elementy z tablic ale i tablico podobnych struktur (w tym stringów):
Wraz z wprowadzeniem symboli dostaliśmy też możliwość stosowania bardzo wygodnej pętli iteracyjnej for of:
Pętla ta do wykonywania iteracji wykorzystuje omawiany symbol. Tablico podobne struktury (String, Array, Map, Set) mają pod tym symbolem wstawioną odpowiednią funkcję iterującą.
Po bardziej rozbudowanych strukturach (obiektach) takiej pętli zrobić nie możemy, chyba, że podpowiemy Javascriptowi jak taką pętlę ma robić ustawiając dla nich ich własną metodę dla tego symbolu:
Last updated