162

I have some code that I absolutely must implement using goto. For example, I want to write a program like this:

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

Is there a way to do that in Javascript?

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • goto would be conviniend for compiled javascript. I've a JVM written in JavaScript. It would be much performanter and shorter with goto statement. – neoexpert Jan 27 '20 at 20:34

17 Answers17

178

Absolutely! There is a project called Summer of Goto that allows you use JavaScript at its fullest potential and will revolutionize the way you can write your code.

This JavaScript preprocessing tool allows you to create a label and then goto it using this syntax:

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

For example, the example in the question can be written as follows:

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

Note that you are not just limited to simple trivial programs like an endless LATHER RINSE repeat cycle—the possibilities afforded by goto are endless and you can even make a Hello, world! message to the JavaScript console 538 times, like this:

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

You can read more about how goto is implemented, but basically, it does some JavaScript preprocessing that takes advantage of the fact that you can simulate a goto with a labelled while loop. So, when you write the "Hello, world!" program above, it gets translated to something like this:

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

There are some limitations to this preprocessing process, because while loops cannot stretch across multiple functions or blocks. That's not a big deal, though—I'm sure the benefits of being able to take advantage of goto in JavaScript will absolutely overwhelm you.

All above link that lead to goto.js library is ALL DEAD, here is links needed:

goto.js (uncompressed) --- parseScripts.js (uncompressed)

From Goto.js:

Peter Olson
  • 139,199
  • 49
  • 202
  • 242
  • 15
    @SurrealDreams It may be a joke, but it actually works. You can click the jsFiddle links and see that they actually work. – Peter Olson Mar 17 '12 at 15:36
  • 1
    Oh, I believe that it's been implemented. I mean to say that the project itself is a joke, they creators were being funny. – Surreal Dreams Mar 17 '12 at 15:37
  • 2
    @PeterOlson No one cares if it actually works. The points is that it isn't actually useful. It isn't even javascript, it's pre-processing. – GoldenNewby Mar 17 '12 at 15:38
  • 27
    The article you linked to actually states it's a joke :) – pimvdb Mar 17 '12 at 15:39
  • 2
    @pimvdb I never denied that it was, I'm just saying that it's fully functional. Just because it's a joke doesn't mean you can't use it. ;) – Peter Olson Mar 17 '12 at 15:40
  • 9
    @PeterOlson, But stackoverflow is intended to help people learn programming. The questions and answers should be useful to do that with. No one is being helped by this. – GoldenNewby Mar 17 '12 at 15:41
  • 5
    Peter, people [are taking this seriously](http://stackoverflow.com/q/14335353/447356) and actually using this joke for real. Can you please delete this and that site (assuming it's yours) for the love of JavaScript and programming? – Shadow The GPT Wizard Jan 15 '13 at 11:07
  • 11
    @ShadowWizard This answer is already surrounded by plenty of disclaimers and people talking about why this shouldn't be used. I feel no shame in letting people who willfully ignore that face the consequences of doing so. – Peter Olson Jan 15 '13 at 21:44
  • " Goto.js is a parsescripts hook to implement the classic 'goto' functionality into native javascript. If you are seriously considering using this script, please don't. " This cooment is in the goto script in the answer – Mohamed El-Nakeep Feb 15 '14 at 14:33
  • I am developing the same attitude towards "magical" functions and over abstraction in code. It has similar effect to GOTO – Itay Moav -Malimovka Jul 04 '14 at 11:52
  • It would be useful to have goto in javascript for some purposes, such as implementing client-side coroutines. Unfortunately the "joke" goto stuff linked is not very useful, being unable to jump forwards. – Sam Watkins Feb 05 '15 at 00:26
  • 1
    this might be really useful to act as break; continue; statements in functional programming loops/constructs – Alexander Mills Jul 13 '15 at 18:54
  • 19
    +1 for @AlexMills . Honestly, I think `goto` is probably under-utilized. It makes for some very nice error handling patterns. Heck, we use `switch`, which is `goto` in all but name, and nobody belly-aches. – 0x1mason Dec 15 '15 at 14:55
  • I'd give you a double upvote if i could. You just made my day :D – Mensur Grišević Sep 29 '16 at 12:18
  • 3
    Should still put a disclaimer at the top that the answer is a joke – user May 16 '17 at 16:22
  • 2
    @0x1mason, [Goto is way better than switch](https://stackoverflow.com/a/119103/632951). Bill Gates once observed that surprisingly programming hasn't gotten very much simpler or faster over the years. The reason for this is that earlier languages have goto, and newer langauges though having new features, lack the simplicity and of goto. "*Goto-considered-harmful*" hereby considered harmful. – Pacerier May 23 '17 at 01:21
  • ECMAScript doesn't have such a statement. – Power Engineering May 04 '18 at 15:58
  • 2
    How do you break out of nested loops without goto? – Jens Mander Dec 06 '18 at 14:10
  • 1
    Can't believe I landed on this on the April Fool's day!! – Jay Dadhania Apr 01 '20 at 12:27
  • 1
    Bonus points for any programmer who isn't afraid to try something just because everyone else screeches that it's bad and awful and wrong. 99% of the time `goto` is the worst solution, but once in a blue moon it's the simplest, most elegant solution. The look of senseless indignation on everyone else's face is just a bonus. – snarf Sep 29 '20 at 01:49
  • goto is necessary when writting super-performant code (mainly for drivers, which have relatively small code and processing is critical) - however, in many cases this is just renamed to "break" and "continue" and preventing jump out of functions calls. – Xerix Oct 08 '21 at 07:08
  • @ShadowTheKidWizard There are plenty of usecases where goto is completely necessary and the most obvious and readable construct. – 0x777C Oct 20 '22 at 12:39
151

No. They did not include that in ECMAScript:

ECMAScript has no goto statement.

Josh DeLong
  • 475
  • 6
  • 24
pimvdb
  • 151,816
  • 78
  • 307
  • 352
  • 1
    I was wondering if GOTO would be useful while debugging JavaScript. Afaik, only IE provides GOTO in its debugger... and I actually found a use-case for it, but I'm not sure if it could be useful generally... to jump around while debugging JavaScript. What do you think? – Šime Vidas Apr 30 '12 at 20:41
  • 3
    @Šime Vidas: I'm not sure whether debugging with goto functionality is useful. Basically you'd be messing around with the code path in a way that would never happen without debugging anyway. – pimvdb May 01 '12 at 07:44
  • 31
    What a pity ... IMHO `goto` would fit just perfectly well into javascript's cocktail of stupid "features" :) – Yuriy Nakonechnyy Apr 09 '13 at 15:35
  • 10
    `goto` is a reserved keyword for future use, however. We can only hope :) – Azmisov Aug 02 '13 at 19:18
  • 8
    `goto` would be useful when you want to return from a nested function. For example, when using underscore.js, you provide an anonymous function when iterating over arrays. You can't return from inside such a function, so `goto end;` would be useful. – Hubro Mar 24 '15 at 07:11
  • is this still true in 2015, will goto and labels not be supported – Muhammad Umer Aug 09 '15 at 13:44
  • A nested function is merely a lexical construct. I've never seen a programming language that lets you, from one function, `goto` another. What would happen if you *returned* the nested function instead of calling directly into it, and then later when the nested function were invoked it tried to `goto` the outer function? What happens if you recurse through both functions and `goto` from the inner to the outer? *Which* invocation of the outer do you `goto`? – snarf Sep 29 '20 at 01:53
  • 1
    @Azmisov Yeah, just make `goto` syntactic sugar for `throw Error();` – General Grievance Jan 20 '22 at 21:17
  • @snarf — You've never seen Basic then? I take it you were not around when programming was young. Goto statements crossing function boundaries was all the rage. Actually, that was initially how subroutines were implements. #fwiw – MikeSchinkel Oct 24 '22 at 18:35
  • @MikeSchinkel Have *you* ever seen BASIC? Old school BASIC doesn't have nested functions (or functions, period) and what happens when you `GOTO` from one routine to another is well-defined. If you try to pull the same stunt in a more modern language you're doing something conceptually broken and if the compiler were to try to oblige, all you would end up with is a corrupted stack. Oh, and being the sweet summer child I am, I learned to program in AppleSoft BASIC and 6502 ASM, #fwiw – snarf Oct 25 '22 at 22:28
  • ECMA should add `goto` keyword, sometimes it's important to goto the last block in function to do something the same in all logic branches; avoid duplicating code lines – Dee Nov 17 '22 at 14:02
46

In classic JavaScript you need to use do-while loops to achieve this type of code. I presume you are maybe generating code for some other thing.

The way to do it, like for backending bytecode to JavaScript is to wrap every label target in a "labelled" 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);

Every labelled do-while loop you use like this actually creates the two label points for the one label. One at the the top and one at the end of the loop. Jumping back uses continue and jumping forwards uses 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)

Unfortunately there is no other way to do it.

Normal Example Code:

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

So say the code gets encoded to bytecodes so now you must put the bytecodes into JavaScript to simulate your backend for some purpose.

JavaScript style:

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)

So using this technique does the job fine for simple purposes. Other than that not much else you can do.

For normal Javacript you should not need to use goto ever, so you should probably avoid this technique here unless you are specificaly translating other style code to run on JavaScript. I assume that is how they get the Linux kernel to boot in JavaScript for example.

NOTE! This is all naive explanation. For proper Js backend of bytecodes also consider examining the loops before outputting the code. Many simple while loops can be detected as such and then you can rather use loops instead of goto.

Edward Brey
  • 40,302
  • 20
  • 199
  • 253
  • 2
    `continue` in a `do ... while` loop continues *to the check condition*. The backwards `goto` here using `do ... while (0)` thus does not work. http://www.ecma-international.org/ecma-262/5.1/#sec-12.6.1 – ZachB Nov 30 '17 at 22:31
  • 2
    Doesn't work. I have to `let doLoop` for this to work. And main loop: `let doLoop = false; do { if(condition){ doLoop = true; continue; } } while (doLoop)` https://github.com/patarapolw/HanziLevelUp/blob/83eb0e3539a247a5cfc69d243e6a6e5ef373eda5/webapp/static/js/common.js#L90 – Polv Jun 05 '18 at 18:23
33

Actually, I see that ECMAScript (JavaScript) DOES INDEED have a goto statement. However, the JavaScript goto has two flavors!

The two JavaScript flavors of goto are called labeled continue and labeled break. There is no keyword "goto" in JavaScript. The goto is accomplished in JavaScript using the break and continue keywords.

And this is more or less explicitly stated on the w3schools website here http://www.w3schools.com/js/js_switch.asp.

I find the documentation of the labeled continue and labeled break somewhat awkwardly expressed.

The difference between the labeled continue and labeled break is where they may be used. The labeled continue can only be used inside a while loop. See w3schools for some more information.

===========

Another approach that will work is to have a giant while statement with a giant switch statement inside:

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. ...
    }

}
natevw
  • 16,807
  • 8
  • 66
  • 90
Indinfer
  • 915
  • 9
  • 6
  • 11
    _"The labeled continue can only be used inside a while loop."_ - No, labelled `break` and `continue` may be used in `for` loops too. But they're really _not_ equivalent to `goto` given that they are locked into the structure of the related loop(s), as compared to `goto` which can of course - in languages that have it - go to anywhere. – nnnnnn Apr 26 '14 at 23:36
  • What @nnnnnn said, they are not equivalent to `goto` because you must use a loop and the label must come before the `break`/`continue`. – MikeSchinkel Oct 24 '22 at 18:38
18

This is an old question, but since JavaScript is a moving target - it is possible in ES6 on implementation that support proper tail calls. On implementations with support for proper tail calls, you can have an unbounded number of active tail calls (i.e. tail calls doesn't "grow the stack").

A goto can be thought of as a tail call with no parameters.

The example:

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

can be written as

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

Here the call to start is in tail position, so there will be no stack overflows.

Here is a more complex example:

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

First, we split the source up into blocks. Each label indicates the start of a new block.

 Block1
     label1:   A
               B
               if C goto label3
               D

  Block2    
     label3:   E
               goto label1

We need to bind the blocks together using gotos. In the example the block E follows D, so we add a goto label3 after D.

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

  Block2    
     label2:   E
               goto label1

Now each block becomes a function and each goto becomes a tail call.

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

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

To start the program, use label1().

The rewrite is purely mechanical and can thus be done with a macro system such as sweet.js if need be.

soegaard
  • 30,661
  • 4
  • 57
  • 106
  • 1
    "it is possible in ES6 on implementation that support proper tail calls". AFAIK tail calls are disabled in all major browsers. – J D Oct 20 '18 at 22:23
  • 1
    Safari supports proper tail calls, I believe. At the time the answer was given, it was possible to enable proper tail calls in Chrome via a command line switch. Let’s hope they reconsider - or at least begins to support explicitly marked tail calls. – soegaard Oct 20 '18 at 23:07
  • 2
    Explicitly marked tail calls would probably make everyone happy. – J D Oct 21 '18 at 00:12
  • 1
    @soegaard -One way to explicitly mark tail call would be "goto". – Craig Hicks Jan 21 '22 at 03:54
  • 1
    @CraigHicks Except `goto` doesn't take arguments (in most languages). I think, the suggested syntax was: `return continue f(a,b,c)`. See Crowder's answer here: https://stackoverflow.com/questions/42788139/es6-tail-recursion-optimisation-stack-overflow For the current status of tail calls in Node see: https://javascript.plainenglish.io/tail-calls-in-javascript-will-there-be-a-comeback-63ac3a0523a5 – soegaard Jan 21 '22 at 05:49
15
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;
}
Henri Gourvest
  • 989
  • 8
  • 12
10

Sure, using the switch construct you can simulate goto in JavaScript. Unfortunately, the language doesn't provide goto, but this is a good enough of a replacement.

let counter = 10
function goto(newValue) {
  counter = newValue
}
while (true) {
  switch (counter) {
    case 10: alert("RINSE")
    case 20: alert("LATHER")
    case 30: goto(10); break
  }
}
Konrad Borowski
  • 11,584
  • 3
  • 57
  • 71
7

There is a way this can be done, but it needs to be planned carefully. Take for example the following QBASIC program:

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."

Then create your JavaScript to initialize all variables first, followed by making an initial function call to start the ball rolling (we execute this initial function call at the end), and set up functions for every set of lines that you know will be executed in the one unit.

Follow this with the initial function call...

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 result in this instance is:

a = 1
a = 2
a = 3
a = 4
a = 5
a = 6
a = 7
a = 8
a = 9
a = 10
That's the end.
Eliseo D'Annunzio
  • 592
  • 1
  • 10
  • 26
7

How about a for loop? Repeat as many times as you like. Or a while loop, repeat until a condition is met. There are control structures that will let you repeat code. I remember GOTO in Basic... it made such bad code! Modern programming languages give you better options that you can actually maintain.

Surreal Dreams
  • 26,055
  • 3
  • 46
  • 61
  • The infinite production loop: Prototype, scratch, better prototype, scratch, better better prototype, scratch. **Maintenance is often a fallacy.** Not many code needs to be maintained. Most code are rewritten, not maintained. – Pacerier May 23 '17 at 00:34
  • Code with deeply nested decision trees (such as parsing code) is most readably and maintainably expressed as a state machine, and all state machine implementations have the same structure, but goto is fastest. – Seth W. Klein Nov 12 '21 at 15:42
6

Generally, I'd prefer not using GoTo for bad readability. To me, it's a bad excuse for programming simple iterative functions instead of having to program recursive functions, or even better (if things like a Stack Overflow is feared), their true iterative alternatives (which may sometimes be complex).

Something like this would do:

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

That right there is an infinite loop. The expression ("true") inside the parantheses of the while clause is what the Javascript engine will check for - and if the expression is true, it'll keep the loop running. Writing "true" here always evaluates to true, hence an infinite loop.

Mathias Lykkegaard Lorenzen
  • 15,031
  • 23
  • 100
  • 187
4

You can simple use a function:

function hello() {
    alert("RINSE");
    alert("LATHER");
    hello();
}
Andreas Louv
  • 46,145
  • 13
  • 104
  • 123
  • 7
    This is a really bad idea as it will keep pushing the return address on the call stack until the system runs out of memory. – Paul Hutchinson Mar 19 '14 at 21:26
  • 2
    Indeed however the user will have CTRL-ALT-DELETEd long before from the endless modal RINSE-LATHER dialogues! – Shayne Jun 16 '14 at 08:46
4

To achieve goto-like functionality while keeping the call stack clean, I am using this method:

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

// ...

Please note that this code is slow since the function calls are added to timeouts queue, which is evaluated later, in browser's update loop.

Please also note that you can pass arguments (using setTimeout(func, 0, arg1, args...) in browser newer than IE9, or setTimeout(function(){func(arg1, args...)}, 0) in older browsers.

AFAIK, you shouldn't ever run into a case that requires this method unless you need to pause a non-parallelable loop in an environment without async/await support.

pzmarzly
  • 778
  • 15
  • 29
  • 1
    Nasty. I love it. FWIW, that technique is called trampolining. – J D Oct 20 '18 at 22:26
  • I can verify this works. I'm manually transpiling some HP RPN with GTO statements which leads to deep recursion when implemented as function calls; the setTimeout() method shown above collapses the stack and recursion is no longer an issue. But it is much slower. Oh, and I'm doing this in Node.js. – Jeff Lowery Jul 09 '19 at 21:34
4
// example of goto in javascript:

var i, j;
loop_1:
    for (i = 0; i < 3; i++) { //The first for statement is labeled "loop_1"
        loop_2:
            for (j = 0; j < 3; j++) { //The second for statement is labeled "loop_2"
                if (i === 1 && j === 1) {
                    continue loop_1;
                }
                console.log('i = ' + i + ', j = ' + j);
            }
        }
3

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);
Tito100
  • 1,660
  • 1
  • 12
  • 12
3

You should probably read some JS tutorials like this one.

Not sure if goto exists in JS at all, but, either way, it encourages bad coding style and should be avoided.

You could do:

while ( some_condition ){
    alert('RINSE');
    alert('LATHER');
}
Jovan Perovic
  • 19,846
  • 5
  • 44
  • 85
2

Another alternative way to achieve the same is to use the tail calls. But, we don’t have anything like that in JavaScript. So generally, the goto is accomplished in JS using the below two keywords. break and continue, reference: Goto Statement in JavaScript

Here is an example:

var number = 0;
start_position: while(true) {
document.write("Anything you want to print");
number++;
if(number < 100) continue start_position;
break;
}
1

Throwing my 2 cents at this since I found my own solution without loops or cluttering functions everywhere:

function rinseLatherSwitch(label) 
{
    function goto(to)
    {
        switch(to)
        {
            case "rinse": alert("RINSE"); return goto("lather");
            case "lather": alert("LATHER"); return goto("end");
            case "end": break;
        }
    }

    return goto(label);
}

rinseLatherSwitch("rinse");

This format has 3 benefits:

  1. The structure of the code matches other languages switches with goto's (such as C#)
  2. It is all self-contained within a single function so it won't clutter up any other code
  3. It can handle any goto situation without extra work, not just endless loops (in fact the loop won't be endless due to stack overflow which in my books is a handy fail-safe)
Perry Monschau
  • 883
  • 8
  • 22