Как я могу использовать goto в Javascript? - PullRequest
112 голосов
/ 17 марта 2012

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

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

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

Ответы [ 16 ]

139 голосов
/ 17 марта 2012

Абсолютно!Существует проект под названием 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;
}

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

Все приведенные выше ссылки, которые ведут в библиотеку goto.js, ВСЕ DEAD, вот ссылки, необходимые:

goto.js (без сжатия) --- parseScripts.js (без сжатия)

с Перейти.js :

PS Для тех, кто интересуется (пока всего ноль человек), Summer of Goto - это термин, который был популяризирован Полом Айришем при обсуждении этого сценария и PHPрешение добавить goto на их язык.

И для тех, кто не сразу понимает, что все это шутка, пожалуйста, прости меня.<- (страховка). </p>

106 голосов
/ 17 марта 2012

Нет. Они не включили это в ECMAScript:

ECMAScript не имеет оператора goto.

32 голосов
/ 30 декабря 2012

На самом деле, я вижу, что ECMAScript (JavaScript) действительно имеет оператор goto.Тем не менее, JavaScript goto имеет два вида!

Две разновидности JavaScript goto называются помеченными как продолжение и помеченными как разрыв.В JavaScript нет ключевого слова "goto".Goto выполняется в JavaScript с использованием ключевых слов break и continue.

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

Я нахожу документацию пос пометкой «продолжить» и с пометкой «разрыв» несколько неловко выражен.

Разница между помеченным продолжением и помеченным разрывом заключается в том, где они могут использоваться.Помеченный продолжить можно использовать только внутри цикла 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. ...
    }

}
30 голосов
/ 12 февраля 2013

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

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

14 голосов
/ 05 декабря 2012
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;
}
11 голосов
/ 20 июня 2017

Это старый вопрос, но, поскольку 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
               B
               if C goto label3
               D

  Block2    
     label3:   E
               goto label1

Нам нужно связать блоки, используя gotos. В примере блок E следует за D, поэтому мы добавляем 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, если это необходимо.

8 голосов
/ 17 марта 2012

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

7 голосов
/ 27 февраля 2014

Есть способ сделать это, но его нужно тщательно спланировать.Возьмем, к примеру, следующую программу 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."

Затем создайте свой 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's 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's the end.
5 голосов
/ 17 марта 2012

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

Что-то вроде этого сделало бы:

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

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

5 голосов
/ 17 марта 2012

Вероятно, вам следует прочитать некоторые учебные пособия по JS, например: one .

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

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

while ( some_condition ){
    alert('RINSE');
    alert('LATHER');
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...