Przejdź do głównej zawartości

Bug #065

🪲 Znajdź buga

const c = "constructor"
c[c][c](`console.log("It's alive!")`)()

Czy powyższy kod zadziała poprawnie i do konsoli zostanie zalogowany tekst It's alive!?

🧪 Rozwiązanie

const c = "constructor"
c[c][c](`console.log("It's alive!")`)()

Tak! W kodzie nie ma buga, wszystko zadziała poprawnie.

Wyjaśnienia wymaga jednak kwestia, dlaczego ciąg znaków został wykonany.

W procesie tworzenia obiektów udział biorą funkcje nazywane konstruktorami.

W utworzonym obiekcie możemy dostać się do takiej funkcji uruchamiając na niej metodę o nazwie constructor.

"".constructor zwróci więc funkcję konstruktora obiektu ciągu znaków, czyli String.

Przypisując ciąg znaków "constructor" do stałej, a później używając jej w c[c][c], uzyskamy ten sam efekt co wywołując kod "constructor".constructor.constructor.

Wiemy już, że konstruktorem ciągu znaków jest funkcja String.

Idąc krok dalej, sprawdzamy jaki konstruktor bierze udział w procesie tworzenia obiektu ciągu znaków, czyli ekwiwalent wywołania String.constructor.

Okazuje się, że zwrócony zostaje konstruktor funkcji, czyli Function.

c[c][c]() to więc finalnie to samo co Function().

W JavaScript do tworzenia funkcji możemy użyć funkcji konstruktora obiektu funkcji, przekazując jako argument ciąg znaków, który zostanie wykonany jako ciało funkcji.

Function(`console.log("It's alive!")`) tworzy więc nową funkcję, której ciałem staje się przekazany ciąg znaków.

Działaniem przypomina to funkcję eval(), która również przetwarza przekazany w argumencie ciąg znaków do postaci wykonywanego kodu.

Finalnie wykonujemy nowo utworzoną funkcję poprzez dodanie nawiasów na końcu Function(`console.log("It's alive!")`)().

Otrzymujemy ten sam efekt, który dało nam wywołanie\ c[c][c](`console.log("It's alive!")`)().

🎢 Plac zabaw

Otwórz edytor w nowym oknie

📑 Linki

❤️ Podobają Ci się bugi JS?

Podziel się linkiem ze znajomymi:
https://codisity.pl/100-bugow-js