¿Cómo puedo usar goto en Javascript?


Tengo un código que absolutamente debo implementar usando goto. Por ejemplo, quiero escribir un programa como este:

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

¿Hay alguna manera de hacer eso en Javascript?

Author: Peter Olson, 2012-03-17

14 answers

Absolutamente! Hay un proyecto llamado Summer of Goto que te permite usar JavaScript en su máximo potencial y revolucionará la forma en que puedes escribir tu código.

Esta herramienta de preprocesamiento de JavaScript le permite crear una etiqueta y luego ir usando esta sintaxis:

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

Por ejemplo, el ejemplo de la pregunta se puede escribir de la siguiente manera:

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

Tenga en cuenta que no se limita a simples programas triviales como un endless LATHER RINSE repeat cycle-las posibilidades que ofrece goto son infinitas e incluso puede hacer un mensaje Hello, world! a la consola JavaScript 538 veces, como esto:

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

Puede leer más sobre cómo se implementa goto, pero básicamente, hace un preprocesamiento de JavaScript que aprovecha el hecho de que puede simular un goto con un etiquetado while loop. Entonces, cuando escribes el " Hola, mundo!"programa anterior, se traduce a algo como esto:

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

Hay algunas limitaciones a este proceso de preprocesamiento, porque los bucles while no pueden extenderse a través de múltiples funciones o bloques. Eso no es un gran problema, sin embargo, estoy seguro de que los beneficios de poder aprovechar goto en JavaScript lo abrumarán absolutamente.

Todos los enlaces anteriores que conducen a goto.la biblioteca js está MUERTA, aquí hay enlaces necesarios:

Goto.js (sin comprimir) --- parseScripts.js (sin comprimir)

De Goto.js :

P.d. Para cualquiera que se pregunte (hasta ahora un total de cero personas), Summer of Goto es un término que fue popularizado por Paul Irish, mientras discutía este script y la decisión de PHP de agregar goto a su lenguaje.

Y para aquellos que no reconocen inmediatamente que todo esto es una broma, por favor perdónenme.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-12 03:32:47

No. No incluyeron eso en ECMAScript:

ECMAScript no tiene instrucción 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-17 15:31:08

En realidad, veo que ECMAScript (JavaScript) TIENE UNA sentencia goto. Sin embargo, el goto JavaScript tiene dos sabores!

Los dos tipos de JavaScript de goto se llaman etiquetados continue y etiquetados break. No hay ninguna palabra clave "goto" en JavaScript. El goto se logra en JavaScript usando las palabras clave break y continue.

Y esto se indica más o menos explícitamente en el sitio web de w3schools aquí http://www.w3schools.com/js/js_switch.asp .

I encontrar la documentación de la etiquetada continuar y etiquetado romper algo torpemente expresado.

La diferencia entre el continuar etiquetado y el descanso etiquetado es donde se pueden usar. La etiqueta continue solo se puede usar dentro de un bucle while. Vea w3schools para más información.

===========

Otro enfoque que funcionará es tener una sentencia giant while con una sentencia giant switch dentro:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-11-05 19:49:39

En JavaScript clásico necesita usar bucles do-while para lograr este tipo de código. Supongo que tal vez estás generando código para alguna otra cosa.

La forma de hacerlo, como para backending bytecode a JavaScript es envolver cada destino de etiqueta en un do-while "etiquetado".

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);

Cada bucle do-while etiquetado que utilices de esta manera crea los dos puntos de etiqueta para una etiqueta. Uno en la parte superior y otro al final del bucle. Jumping back usos continuar y saltar forwards usa 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)

Desafortunadamente no hay otra manera de hacerlo.

Código de ejemplo normal:

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

Así que digamos que el código se codifica en bytecodes por lo que ahora debe poner los bytecodes en JavaScript para simular su backend para algún propósito.

Estilo 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)

Así que el uso de esta técnica hace el trabajo bien para fines simples. Aparte de eso, no hay mucho más que puedas hacer.

Para Javacript normal no debería necesitar usar goto nunca, por lo que probablemente debería evitar esta técnica aquí a menos que esté traduciendo específicamente otro código de estilo para ejecutarse en JavaScript. Supongo que así es como consiguen que el kernel de Linux arranque en JavaScript, por ejemplo.

NOTA! Todo esto es una explicación ingenua. Para un backend Js apropiado de bytecodes también considere examinar los bucles antes de emitir el código. Muchos bucles while simples se pueden detectar como tales y luego puede usar bucles en lugar de 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-05 20:16:25

¿Qué tal un bucle for? Repite tantas veces como quieras. O un bucle while, repita hasta que se cumpla una condición. Hay estructuras de control que le permitirán repetir código. Recuerdo GOTO en Basic... ¡hizo un código tan malo! Los lenguajes de programación modernos te dan mejores opciones que puedes mantener.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-17 15:32:35

Esta es una pregunta antigua, pero dado que JavaScript es un objetivo en movimiento, es posible en ES6 en implementación que admita llamadas de cola adecuadas. En implementaciones con soporte para llamadas tail adecuadas, puede tener un número ilimitado de llamadas tail activas (es decir, las llamadas tail no "hacen crecer la pila").

Un goto puede ser considerado como una llamada de cola sin parámetros.

El ejemplo:

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

Se Puede escribir como

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

Aquí la llamada a start está en cola posición, por lo que no habrá desbordamientos de pila.

Aquí hay un ejemplo más complejo:

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

Primero, dividimos la fuente en bloques. Cada etiqueta indica el inicio de un nuevo bloque.

 Block1
     label1:   A
               B
               if C goto label3
               D

  Block2    
     label3:   E
               goto label1

Necesitamos unir los bloques usando gotos. En el ejemplo el bloque E sigue a D, así que añadimos a goto label3 después de D.

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

  Block2    
     label2:   E
               goto label1

Ahora cada bloque se convierte en una función y cada goto se convierte en una llamada de cola.

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

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

Para iniciar el programa, utilice label1().

El la reescritura es puramente mecánica y, por lo tanto, se puede hacer con un sistema macro como sweet.js si es necesario.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-16 04:53:13

Hay una manera de hacer esto, pero necesita ser planeado cuidadosamente. Tomemos por ejemplo el siguiente programa 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."

Luego cree su JavaScript para inicializar todas las variables primero, seguido de hacer una llamada a la función inicial para iniciar el balanceo de la bola (ejecutamos esta llamada a la función inicial al final), y configure funciones para cada conjunto de líneas que sepa que se ejecutarán en la unidad única.

Siga esto con la llamada a la función inicial...

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();

El el resultado en esta instancia es:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-27 04:33:52

Probablemente deberías leer algunos tutoriales de JS como este uno.

No estoy seguro de si goto existe en JS, pero, de cualquier manera, fomenta un mal estilo de codificación y debe evitarse.

Usted podría hacer:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-17 15:31:38

En general, preferiría no usar GoTo para una mala legibilidad. Para mí, es una mala excusa para programar funciones iterativas simples en lugar de tener que programar funciones recursivas, o incluso mejor (si se teme cosas como un Desbordamiento de pila), sus verdaderas alternativas iterativas (que a veces pueden ser complejas).

Algo como esto haría:

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

Ese derecho hay un bucle infinito. La expresión ("true") dentro de las parantesis de la cláusula while es lo que el Javascript motor comprobará - y si la expresión es verdadera, mantendrá el bucle en funcionamiento. Escribir "verdadero" aquí siempre se evalúa como verdadero, de ahí un bucle infinito.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-02-21 14:34:29

Puede usar una función simple:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-01-15 10:55:19

Ir a comenzar y terminar todos los cierres de padres

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-20 11:22:25

Para lograr una funcionalidad similar a goto mientras mantengo limpia la pila de llamadas, estoy usando este método:

// 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();
}

// ...

Tenga en cuenta que este código es lento ya que las llamadas a la función se agregan a la cola de tiempos de espera, que se evalúa más tarde, en el bucle de actualización del navegador.

También tenga en cuenta que puede pasar argumentos (usando setTimeout(func, 0, arg1, args...) en un navegador más reciente que IE9, o setTimeout(function(){func(arg1, args...)}, 0) en navegadores más antiguos.

AFAIK, nunca debería encontrarse con un caso que requiera este método a menos que necesite pausar un bucle no paralelable en un entorno sin soporte async / await.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-09 16:30:25

Claro, usando la construcción switch puede simular goto en JavaScript. Desafortunadamente, el lenguaje no proporciona goto, pero este es un reemplazo suficientemente bueno.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-24 07:40:55