Jak Mogę używać goto w Javascript?

Mam jakiś kod, który bezwzględnie muszę zaimplementować używając goto. Na przykład Chcę napisać taki program:

start:
alert("RINSE");
alert("LATHER");
repeat: goto start

Czy jest na to sposób w Javascript?

Author: Peter Olson, 2012-03-17

14 answers

Absolutnie! Istnieje projekt o nazwie Summer of Goto , który pozwala korzystać z JavaScript w pełni i zrewolucjonizuje sposób pisania kodu.

To narzędzie do wstępnego przetwarzania JavaScript pozwala na utworzenie etykiety, a następnie goto go używając tej składni:

[lbl] <label-name>
goto <label-name>

Na przykład, przykład w pytaniu można zapisać w następujący sposób:

[lbl] start:
alert("LATHER");
alert("RINSE");
[lbl] repeat: goto start;

Zauważ, że nie ograniczasz się tylko do prostych trywialnych programów, takich jak niekończące się LATHER RINSE powtórz cykl-możliwości oferowane przez goto są nieograniczone i możesz nawet wysłać Hello, world! wiadomość do konsoli JavaScript 538 razy, tak:

var i = 0;
[lbl] start:
console.log("Hello, world!");
i++;
if(i < 538) goto start;

Możesz przeczytać więcej o tym, jak goto jest zaimplementowane , ale zasadniczo wykonuje pewne wstępne przetwarzanie JavaScript, które wykorzystuje fakt, że możesz symulować goto za pomocą oznakowanej while pętli. Więc, kiedy piszesz " Hello, world!"program powyżej, zostaje przetłumaczony na coś takiego jak to:

var i = 0;
start: while(true) {
  console.log("Hello, world!");
  i++;
  if(i < 538) continue start;
  break;
}

Istnieją pewne ograniczenia tego procesu wstępnego przetwarzania, ponieważ pętle nie mogą rozciągać się między wieloma funkcjami lub blokami. Nie jest to jednak wielka sprawa-jestem pewien, że korzyści płynące z możliwości korzystania z goto w JavaScript absolutnie Cię przytłoczą.

Wszystkie powyższe linki prowadzące do goto.biblioteka js jest martwa, tutaj potrzebne są linki:

Goto.js (nieskompresowany) --- parseScripts.js (uncompressed)

Od Goto.js :

P. S. dla każdego, kto się zastanawia (jak na razie zero osób), Summer of Goto to termin, który spopularyzował Paul Irish, omawiając ten skrypt i decyzję PHP o dodaniu goto do swojego języka.

A dla tych, którzy nie od razu uznają, że to wszystko jest żartem, proszę, wybacz mi.
 123
Author: Peter Olson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-12 03:32:47

Nie. nie uwzględnili tego w ECMAScript:

ECMAScript nie posiada instrukcji goto.

 96
Author: pimvdb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-17 15:31:08

Właściwie, widzę, że ECMAScript (JavaScript) rzeczywiście ma polecenie goto. Jednak JavaScript goto ma dwa smaki!

Dwa smaki JavaScript goto nazywa się continue i break. W JavaScript nie ma słowa kluczowego "goto". Goto jest realizowane w JavaScript za pomocą słów kluczowych break I continue.

I jest to mniej lub bardziej wyraźnie powiedziane na stronie w3schools tutaj http://www.w3schools.com/js/js_switch.asp .

I znajdź dokumentację oznaczoną dalej i oznaczoną break nieco niezręcznie wyrażoną.

Różnica między znakami continue i break polega na tym, gdzie mogą być używane. Znak continue może być używany tylko wewnątrz pętli while. Zobacz w3schools, aby uzyskać więcej informacji.

===========

Innym podejściem, które będzie działać, jest posiadanie instrukcji Giant while z instrukcją giant switch wewnątrz:

while (true)
{
    switch (goto_variable)
    {
        case 1:
            // some code
            goto_variable = 2
            break;
        case 2:
            goto_variable = 5   // case in etc. below
            break;
        case 3:
            goto_variable = 1
            break;

         etc. ...
    }

}
 30
Author: Indinfer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-05 19:49:39

W klasycznym JavaScript musisz użyć pętli do-while, aby osiągnąć ten typ kodu. Zakładam, że może generujesz kod do innej rzeczy.

Sposobem na to, jak w przypadku backendowania kodu bajtowego do JavaScript jest zawijanie każdego obiektu docelowego etykiety w" etykiecie " do-while.

LABEL1: do {
  x = x + 2;
  ...
  // JUMP TO THE END OF THE DO-WHILE - A FORWARDS GOTO
  if (x < 100) break LABEL1;
  // JUMP TO THE START OF THE DO WHILE - A BACKWARDS GOTO...
  if (x < 100) continue LABEL1;
} while(0);

Każda pętla do-while, której używasz w ten sposób, tworzy dwa punkty etykiety dla jednej etykiety. Jeden na górze i jeden na końcu pętli. Skoki do tyłu forwards używa break.

// NORMAL CODE

MYLOOP:
  DoStuff();
  x = x + 1;
  if (x > 100) goto DONE_LOOP;
  GOTO MYLOOP;


// JAVASCRIPT STYLE
MYLOOP: do {
  DoStuff();
  x = x + 1;
  if (x > 100) break MYLOOP;
  continue MYLOOP;// Not necessary since you can just put do {} while (1) but it     illustrates
} while (0)
Niestety nie ma innego sposobu, aby to zrobić.

Normalny Przykładowy Kod:

while (x < 10 && Ok) {
  z = 0;
  while (z < 10) {
    if (!DoStuff()) {
      Ok = FALSE;
      break;
    }
    z++;
  }
  x++;
} 

Więc powiedzmy, że kod zostanie zakodowany do bajtowych kodów, więc teraz musisz umieścić bajtowe kody w JavaScript, aby symulować swój backend w jakimś celu.

Styl JavaScript:

LOOP1: do {
  if (x >= 10) break LOOP1;
  if (!Ok) break LOOP1;
  z = 0;
  LOOP2: do {
    if (z >= 10) break LOOP2;
    if (!DoStuff()) {
      Ok = FALSE;
      break LOOP2;
    }
    z++;
  } while (1);// Note While (1) I can just skip saying continue LOOP2!
  x++;
  continue LOOP1;// Again can skip this line and just say do {} while (1)
} while(0)

Więc korzystanie z tej techniki robi dobrze zadanie dla prostych celów. Poza tym niewiele więcej możesz zrobić.

Dla zwykłego Javacriptu nie powinieneś nigdy używać goto, więc prawdopodobnie powinieneś unikać tej techniki, chyba że tłumaczysz inny kod stylów na JavaScript. Zakładam, że w ten sposób dostają jądro Linuksa do rozruchu na przykład w JavaScript.

Uwaga! To wszystko naiwne Wyjaśnienie. Dla poprawnego backendu js bajtekodów rozważ również sprawdzenie pętli przed wysłaniem kodu. Wiele prostych pętli while można wykryć jako takie i wtedy można raczej używać pętli zamiast goto.

 28
Author: Scimonster,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-24 09:38:44
const
    start = 0,
    more = 1,
    pass = 2,
    loop = 3,
    skip = 4,
    done = 5;

var label = start;


while (true){
    var goTo = null;
    switch (label){
        case start:
            console.log('start');
        case more:
            console.log('more');
        case pass:
            console.log('pass');
        case loop:
            console.log('loop');
            goTo = pass; break;
        case skip:
            console.log('skip');
        case done:
            console.log('done');

    }
    if (goTo == null) break;
    label = goTo;
}
 13
Author: Henri Gourvest,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-05 20:16:25

A może pętla for? Powtarzaj tyle razy, ile chcesz. Lub pętli while, powtarzaj do momentu spełnienia warunku. Istnieją struktury kontrolne, które pozwolą Ci powtórzyć kod. Pamiętam GOTO w Basic... stworzył taki zły kod! Nowoczesne języki programowania dają lepsze opcje, które można faktycznie utrzymać.

 8
Author: Surreal Dreams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-17 15:32:35

Jest to stare pytanie, ale ponieważ JavaScript jest ruchomym celem - możliwe jest w ES6 na implementacji, które obsługują odpowiednie wywołania ogonowe. W implementacjach z obsługą prawidłowych wywołań tail, możesz mieć nieograniczoną liczbę aktywnych wywołań tail (tzn. wywołania tail nie "powiększają stosu").

A goto może być traktowane jako wywołanie ogonowe bez parametrów.

Przykład:

start: alert("RINSE");
       alert("LATHER");
       goto start

Można zapisać jako

 function start() { alert("RINSE");
                    alert("LATHER");
                    return start() }

Tutaj wezwanie do start jest w ogonie pozycji, więc nie będzie przepełnień stosu.

Oto bardziej złożony przykład:

 label1:   A
           B
           if C goto label3
           D
 label3:   E
           goto label1

Najpierw podzieliliśmy źródło na bloki. Każda etykieta wskazuje początek nowego bloku.

 Block1
     label1:   A
               B
               if C goto label3
               D

  Block2    
     label3:   E
               goto label1

Musimy połączyć bloki razem za pomocą gotos. W przykładzie Blok E podąża za D, więc dodajemy goto label3 po D.

 Block1
     label1:   A
               B
               if C goto label2
               D
               goto label2

  Block2    
     label2:   E
               goto label1

Teraz każdy blok staje się funkcją, a każdy goto staje się wywołaniem ogonowym.

 function label1() {
               A
               B
               if C then return( label2() )
               D
               return( label2() )
 }

 function label2() {
               E
               return( label1() )
 }

Aby uruchomić program, użyj label1().

The przepisywanie jest czysto mechaniczne i dlatego można to zrobić za pomocą systemu makr, takiego jak sweet.js w razie potrzeby.

 8
Author: soegaard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-16 04:53:13

Można to zrobić w pewien sposób, ale trzeba to dokładnie zaplanować. Weźmy na przykład następujący program QBASIC:

1 A = 1; B = 10;
10 print "A = ",A;
20 IF (A < B) THEN A = A + 1; GOTO 10
30 PRINT "That's the end."

Następnie utwórz swój JavaScript, aby najpierw zainicjować wszystkie zmienne, a następnie wykonać początkowe wywołanie funkcji, aby rozpocząć toczenie piłki (wykonujemy to początkowe wywołanie funkcji na końcu) i skonfigurować funkcje dla każdego zestawu linii, które wiesz, że będą wykonywane w jednej jednostce.

Wykonaj to przy pierwszym wywołaniu funkcji...

var a, b;
function fa(){
    a = 1;
    b = 10;
    fb();
}
function fb(){
    document.write("a = "+ a + "<br>");
    fc();
}
function fc(){
    if(a<b){
        a++;
        fb();
        return;
    }
    else
    {
    document.write("That's the end.<br>");
    }
}
fa();

The wynik w tej instancji to:

a = 1
a = 2
a = 3
a = 4
a = 5
a = 6
a = 7
a = 8
a = 9
a = 10
That's the end.
 7
Author: Eliseo d'Annunzio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-27 04:33:52

Prawdopodobnie powinieneś przeczytać kilka samouczków JS takich jak ten jeden.

Nie wiem, czy goto istnieje w JS, ale tak czy inaczej, zachęca do złego stylu kodowania i należy go unikać.

Możesz zrobić:

while ( some_condition ){
    alert('RINSE');
    alert('LATHER');
}
 5
Author: Jovan Perovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-17 15:31:38

Ogólnie, wolałbym nie używać GoTo dla złej czytelności. Dla mnie jest to zła wymówka dla programowania prostych funkcji iteracyjnych zamiast konieczności programowania funkcji rekurencyjnych, a nawet lepiej (jeśli obawiamy się przepełnienia stosu), ich prawdziwych alternatyw iteracyjnych (które czasami mogą być złożone).

Coś takiego by się przydało:

while(true) {
   alert("RINSE");
   alert("LATHER");
}

To jest nieskończona pętla. Wyrażenie ("true") wewnątrz parantezy klauzuli while jest tym, co Javascript silnik sprawdzi - a jeśli wyrażenie jest prawdziwe, utrzyma pętlę. Zapis "true" tutaj zawsze ocenia się na true, stąd nieskończona pętla.

 5
Author: Mathias Lykkegaard Lorenzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 14:34:29

Możesz w prosty sposób użyć funkcji:

function hello() {
    alert("RINSE");
    alert("LATHER");
    hello();
}
 4
Author: andlrc,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-15 10:55:19

Goto begin and end of all parents closures

var foo=false;
var loop1=true;
LABEL1: do {var LABEL1GOTO=false;
    console.log("here be 2 times");
    if (foo==false){
        foo=true;
        LABEL1GOTO=true;continue LABEL1;// goto up
    }else{
        break LABEL1; //goto down
    }
    console.log("newer go here");
} while(LABEL1GOTO);
 3
Author: Tito100,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-20 11:22:25

Aby osiągnąć funkcjonalność podobną do goto przy zachowaniu czystego stosu wywołań, używam tej metody:

// in other languages:
// tag1:
// doSomething();
// tag2:
// doMoreThings();
// if (someCondition) goto tag1;
// if (otherCondition) goto tag2;

function tag1() {
    doSomething();
    setTimeout(tag2, 0); // optional, alternatively just tag2();
}

function tag2() {
    doMoreThings();
    if (someCondition) {
        setTimeout(tag1, 0); // those 2 lines
        return;              // imitate goto
    }
    if (otherCondition) {
        setTimeout(tag2, 0); // those 2 lines
        return;              // imitate goto
    }
    setTimeout(tag3, 0); // optional, alternatively just tag3();
}

// ...

Należy pamiętać, że ten kod jest powolny, ponieważ wywołania funkcji są dodawane do kolejki timeouts, która jest oceniana później, w pętli aktualizacji przeglądarki.

Należy również pamiętać, że można przekazać argumenty (używając setTimeout(func, 0, arg1, args...) w przeglądarce nowszej niż IE9 lub setTimeout(function(){func(arg1, args...)}, 0) w starszych przeglądarkach.

AFAIK, nigdy nie powinieneś napotkać sprawy, która wymaga tej metody, chyba że musisz wstrzymać pętla non-parallelable w środowisku bez obsługi asynchronicznej / oczekującej.

 3
Author: pzmarzly,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-09 16:30:25

Oczywiście, używając konstrukcji switch możesz symulować goto w JavaScript. Niestety, język nie zapewnia goto, ale jest to wystarczająco dobry zamiennik.

let counter = 10
function goto(newValue) {
  counter = newValue
}
while (true) {
  switch (counter) {
    case 10: alert("RINSE")
    case 20: alert("LATHER")
    case 30: goto(10)
  }
}
 2
Author: Konrad Borowski,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-24 07:40:55