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


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

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

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

14 100

14 ответов:

абсолютно! Есть проект под названием лето Гото это позволяет использовать JavaScript в полном объеме и революционизирует способ написания кода.

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

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

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

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

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

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

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

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

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

все выше ссылки, которые приводят к Гото.JS библиотека все мертвы, вот ссылки, необходимые:

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

С Гото.js:

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

и для тех, кто не сразу понимает, что все это шутка, пожалуйста, простите меня.

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

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

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

два JavaScript-варианта goto называются labeled continue и labeled break. В JavaScript нет ключевого слова "goto". Переход осуществляется в JavaScript с использованием ключевых слов break и continue.

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

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

разница между помеченным продолжением и помеченным разрывом заключается в том, где они могут быть использованы. Помеченный continue может использоваться только внутри цикла while. Увидеть w3schools для Больше информации.

===========

другой подход, который будет работать, чтобы иметь гигантский оператор while с гигантский переключатель заявление внутри:

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

}

в классическом 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 могут быть обнаружены как таковые, а затем вы можете использовать циклы вместо Гото.

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

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

это старый вопрос, но поскольку 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, поэтому мы добавляем a goto label3 Д.

 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, если понадобится.

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

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

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

вы могли бы сделать:

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

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

что-то вроде этого будет делать:

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

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

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

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

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

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

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

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

конечно, с помощью switch построить Вы можете имитировать goto в JavaScript. К сожалению, язык не предоставляет goto, но это достаточно хорошая замена.

let counter = 10
function goto(newValue) {
  counter = newValue
}
while (true) {
  switch (counter) {
    case 10: alert("RINSE")
    case 20: alert("LATHER")
    case 30: goto(10)
  }
}