Как я могу использовать goto в Javascript?

У меня есть код, который я должен выполнить с помощью goto. Например, я хочу написать такую ​​программу:

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

Есть ли способ сделать это в Javascript?

Ответ 1

Абсолютно! Существует проект под названием Summer of Goto, который позволяет использовать JavaScript в полном объеме и революционизирует способ написания кода.

Этот инструмент предварительной обработки JavaScript позволяет вам создать ярлык и затем перейти к нему с помощью этого синтаксиса:

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

Например, пример в вопросе может быть записан следующим образом:

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

Обратите внимание, что вы не просто ограничены простыми тривиальными программами, такими как бесконечный цикл повторения LATHER RINSE - возможности, предоставляемые goto, бесконечны, и вы даже можете сделать сообщение Hello, world! на консоли JavaScript 538 раз, например:

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

Вы можете узнать больше о том, как goto реализован, но в основном он выполняет некоторую предварительную обработку JavaScript, которая использует тот факт, что вы можете имитировать goto с с надписью while loop. Итак, когда вы пишете "Привет, мир!". выше, он переводится на что-то вроде этого:

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

Существуют некоторые ограничения для этого процесса предварительной обработки, поскольку циклы не могут растягиваться через несколько функций или блоков. Однако это не очень важно, я уверен, что преимущества использования goto в JavaScript будут абсолютно подавлять вас.

Все выше ссылки, которые приводят к библиотеке goto.js, являются ВСЕМИ МЕРТВОЙ, здесь нужны ссылки:

goto.js(несжатый) --- parseScripts.js(несжатый)

Ответ 3

На самом деле, я вижу, что ECMAScript (JavaScript) DOES INDEED имеет инструкцию goto. Тем не менее, JavaScript goto имеет два вкуса!

Два JavaScript-метода goto называются помеченными continue и помечены как break. В JavaScript нет ключевого слова "goto". Goo выполняется в JavaScript, используя ключевые слова break и continue.

И это более или менее явно указано на веб-сайте w3schools здесь http://www.w3schools.com/js/js_switch.asp.

Я нахожу, что документация по помеченному продолжению и помеченному слову несколько неудобно выражена.

Разница между помеченным продолжением и помеченным перерывом заключается в том, где они могут использоваться. Метка continue может использоваться только внутри цикла while. Для получения дополнительной информации см. W3schools.

===========

Другим подходом, который будет работать, будет иметь гигантский оператор while с гигантским выражением switch внутри:

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

}

Ответ 4

В классическом JavaScript вам нужно использовать циклы do-while для достижения этого типа кода. Я предполагаю, что вы, возможно, генерируете код для какой-то другой вещи.

Способ сделать это, как и для бэкэтин-байта для JavaScript, - это обернуть каждую метку в "помеченную" кнопку 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);

Каждый помеченный цикл do-while, который вы используете так, фактически создает две метки для одной метки. Один в верхней части и один в конце цикла. Прыжки назад используют продолжение и прыжки вперед использует 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)

К сожалению, нет другого способа сделать это.

Нормальный пример кода:

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

Итак, скажите, что код закодирован для байт-кодов, поэтому теперь вы должны поместить байт-коды в JavaScript, чтобы имитировать ваш сервер для какой-то цели.

Стиль 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)

Таким образом, использование этой методики отлично подходит для простых целей. Помимо этого вы не можете больше ничего сделать.

Для обычного Javacript вам не нужно использовать goto когда-либо, поэтому вам, вероятно, следует избегать этой техники здесь, если вы специально не переводите другой код стиля для работы на JavaScript. Я предполагаю, что именно они заставляют ядро ​​Linux загружаться в JavaScript, например.

ВНИМАНИЕ! Это все наивное объяснение. Для правильного Js-бэкенда байт-кодов также рассмотрим проверку циклов перед выдачей кода. Многие простые циклы while могут быть обнаружены как таковые, и тогда вы скорее можете использовать циклы вместо goto.

Ответ 5

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

Ответ 6

Как насчет цикла for? Повторяйте столько раз, сколько хотите. Или цикл while, повторите, пока не будет выполнено условие. Существуют структуры управления, которые позволят вам повторить код. Я помню GOTO в Basic... он сделал такой плохой код! Современные языки программирования дают вам лучшие варианты, которые вы можете фактически поддерживать.

Ответ 7

Есть способ сделать это, но его нужно тщательно спланировать. Возьмем, к примеру, следующую программу QBASIC:

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

Затем создайте свой JavaScript, чтобы сначала инициализировать все переменные, а затем выполнить начальный вызов функции для запуска шариковой качки (мы выполняем этот начальный вызов функции в конце) и настраиваем функции для каждого набора строк, которые вы знаете выполняться в одном блоке.

Следуйте этому с помощью вызова начальной функции...

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 the end.<br>");
    }
}
fa();

Результат в этом случае:

a = 1
a = 2
a = 3
a = 4
a = 5
a = 6
a = 7
a = 8
a = 9
a = 10
That the end.

Ответ 8

Вероятно, вы должны прочитать некоторые обучающие материалы JS, например один.

Не уверен, что goto существует в JS вообще, но в любом случае он поощряет плохой стиль кодирования и его следует избегать.

Вы можете сделать:

while ( some_condition ){
    alert('RINSE');
    alert('LATHER');
}

Ответ 9

Как правило, я бы предпочел не использовать GoTo для плохой читаемости. Для меня это плохое оправдание для программирования простых итеративных функций вместо необходимости программировать рекурсивные функции или даже лучше (если опасаются такие вещи, как Stack Overflow), их истинные итеративные альтернативы (которые иногда могут быть сложными).

Что-то вроде этого:

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

Это право есть бесконечный цикл. Выражение ( "истина" ) внутри скобок предложения while - это то, что проверяет механизм Javascript - и если выражение истинно, оно будет поддерживать цикл. Запись "истина" здесь всегда оценивается как истина, следовательно, бесконечный цикл.

Аналогичный пример (для объяснения этих условий и предложения while), следующее было бы одинаково:

while(2 + 2 == 4) {
   alert("RINSE");
   alert("LATHER");
}

Можно (однако) утверждать, почему вам нужен бесконечный цикл предупреждающих ящиков. Надеюсь, вы используете это для чего-то хорошего, а не для чего-то плохого.

Ответ 10

Это старый вопрос, но поскольку JavaScript - движущаяся цель - в ES6 можно реализовать реализацию, поддерживающую правильные хвостовые вызовы. В реализациях с поддержкой правильных хвостовых вызовов вы можете иметь неограниченное количество активных хвостовых вызовов (т.е. Хвостовые вызовы не "увеличивают стек" ).

A goto можно рассматривать как хвостовой вызов без параметров.

Пример:

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

может быть записано как

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

Здесь вызов start находится в хвостовом положении, поэтому переполнение стека не будет.

Вот более сложный пример:

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

Сначала мы разделим источник на блоки. Каждая метка указывает начало нового блока.    block1        label1: A                  В                  если C goto label3                  D

  Block2    
     label3:   E
               goto label1

Нам нужно связать блоки вместе с помощью gotos. В примере блок E следует D, поэтому мы добавляем a goto label3 после D.

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

  Block2    
     label2:   E
               goto label1

Теперь каждый блок становится функцией, и каждый goto становится хвостом.

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

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

Чтобы запустить программу, используйте label1().

Переписывание чисто механическое и, таким образом, может быть выполнено с помощью макросистемы, такой как sweet.js, если это необходимо.

Ответ 11

Вы можете просто использовать функцию:

function hello() {
    alert("RINSE");
    alert("LATHER");
    hello();
}

Ответ 12

перейти начало и конец всех закрытий родителей

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

Ответ 13

Для достижения подобной функции, сохраняя при этом стек вызовов чистым, я использую этот метод:

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

// ...

Обратите внимание, что этот код работает медленно, так как вызовы функций добавляются в очередь тайм-аутов, которая затем оценивается в петле обновления браузера.

Также обратите внимание, что вы можете передавать аргументы (используя setTimeout(func, 0, arg1, args...) в браузере выше IE9 или setTimeout(function(){func(arg1, args...)}, 0) в старых браузерах.

AFAIK, вы никогда не должны запускаться в случае, требующем этого метода, если вам не нужно приостанавливать непараллельный цикл в среде без поддержки async/await.