Goto
We wrześniu zastanawiałem się nad tym, jak obsługiwać asynchroniczność w ES3. Wspominałem tam o mechanizmach pozwalających na przekazywanie sterowania. Otóż myślałem nad tym potem trochę i uświadomiłem sobie, że istnieje jeszcze co najmniej jeden taki mechanizm: pętle. I nieco ich nadużywając można zrobić… goto
.
Etykiety
Ale zanim przejdziemy do pętli, pora poznać inny mechanizm, który będzie nam potrzebny: etykiety. Niemal każda instrukcja w JS może zostać w takową zaopatrzona. Jak wygląda etykieta? Dość prosto:
hublabubla: console.log( 'whatever' );
hublabubla
to właśnie nasza etykieta! Całość mocno przypomina definiowanie właściwości obiektu – tylko obiektu brakuje.
Na chwilę obecną etykiety w JS po prostu są. Nie da się ich zastosować niemal do niczego, a sam język przewiduje, że da się ich użyć wyłącznie ze słowami kluczowymi continue
i break
, czyli w pętlach. To pozwala na przykład przerywać zewnętrzną pętlę z poziomu tej zagnieżdżonej:
outer: while( true ) {
while( true ) {
break outer;
}
}
console.log( 'I wyskoczyliśmy!' );
Myślę, że Co Bardziej Rozgarnięci Czytelnicy dostrzegają już ten ukryty potencjał!
goto
w JS
Jeśli jesteśmy dostatecznymi masochistami, nic nie stoi na przeszkodzie, by podzielić nasz kod na wiele zagnieżdżonych i oetykietowanych pętli, między którymi będziemy przeskakiwać przy pomocy continue <etykieta>
. Tego typu program mógłby wyglądać następująco:
main: while( true ) { // 1
let name;
askForName: while( true ) { // 2
name = prompt( 'Podaj imię' );
checkName: while( !name ) { // 3
continue askForName; // 4
}
displayName: while( name ) { // 5
console.log( name );
break main; // 6
}
}
}
Sporo kodu jak dla tak prostego programu. Jego zadaniem jest wyświetlenie imienia podanego przez użytkownika. Na początku tworzymy pętlę main
(1), w której zamykamy cały program. Następnie tworzymy pętlę askForName
(2), której zadaniem jest pobranie nazwy od użytkownika. Kolejna pętla (3) sprawdza, czy imię zostało podane. Jeśli nie, przekazuje sterowanie z powrotem do pętli askForName
(4) – to jest właśnie nasze goto
. Ta pętla jest tak naprawdę odpowiednikiem instrukcji warunkowej if
– no bo po co nam ona, skoro wszystko da się ograć pętlami! Jeśli warunek pętli checkName
nie został spełniony (a więc użytkownik podał imię), wchodzimy do ostatniej pętli (5), która wyświetla imię w konsoli i przerywa główną pętlę (6).
Brawo, udało nam się przenieść jedną z największych abominacji programowania do JS! Niestety, nie byliśmy pierwsi, bo pomysł był znany od dawna. I mam nadzieję, że pozostanie tym, czym od zawsze był: żartem i ciekawostką. Nie chcę nosić do końca życia brzemienia osoby, która skalała JS goto
…
Komentarze
Przejdź do komentarzy bezpośrednio na Githubie.