У мене є якийсь код, який я абсолютно повинен реалізувати за допомогою goto
. Наприклад, я хочу написати таку програму:
start:
alert("RINSE");
alert("LATHER");
repeat: goto start
Чи є спосіб це зробити в Javascript?
У мене є якийсь код, який я абсолютно повинен реалізувати за допомогою goto
. Наприклад, я хочу написати таку програму:
start:
alert("RINSE");
alert("LATHER");
repeat: goto start
Чи є спосіб це зробити в Javascript?
Відповіді:
Абсолютно! Є проект під назвою 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
циклу . Отже, коли ви пишете "Привіт, світ!" Програма вище, вона перекладається приблизно так:
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 (нестиснений)
Від Goto.js :
PS Для тих, хто цікавиться (поки що це загальний нуль людей), Summer of Goto - це термін, популяризований Полом Ірландським, обговорюючи цей сценарій та рішення PHP про те, щоб додати goto на свою мову.
А для тих, хто не відразу визнає, що вся ця річ - жарт, пробачте, будь ласка. <- (страхування).
goto
, мабуть, недостатньо використаний. Це створює дуже приємні схеми обробки помилок. Чорт, ми використовуємо switch
, що є goto
у всіх, крім назви, і ніхто не болить.
Ні. Вони не включали це в ECMAScript:
У ECMAScript немає goto-заяви.
goto
просто чудово впишеться в коктейль javascript від дурних "рис" :)
goto
Однак це зарезервоване ключове слово для подальшого використання. Ми можемо лише сподіватися :)
goto
було б корисно, коли ви хочете повернутися з вкладеної функції. Наприклад, використовуючи underscore.js, ви надаєте анонімну функцію під час ітерації над масивами. Ви не можете повернутися зсередини до такої функції, тому goto end;
було б корисно.
Насправді, я бачу, що ECMAScript (JavaScript) НЕ ВКАЗАНІ має goto заяву. Однак JavaScript goto має два смаки!
Два аромати JavaScript goto називаються міченими продовженнями та міткою перерва. У JavaScript немає ключового слова "goto". Перехід до мови здійснюється за допомогою ключових слів перерви та продовження.
І це більш-менш чітко зазначено на веб-сайті w3schools тут http://www.w3schools.com/js/js_switch.asp .
Я вважаю, що документація із маркованим продовженням і мітка перерви дещо незграбно виражена.
Різниця між маркованим продовженням та маркованим розривом полягає в тому, де вони можуть бути використані. Позначене продовження можна використовувати лише в циклі "час". Додаткову інформацію див. У школах w3schools.
============
Інший підхід, який буде працювати - це мати гігантський оператор, а заяву з гігантським вимикачем перемикання всередині:
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. ...
}
}
break
і continue
може використовуватися і в for
петлях. Але вони насправді не еквівалентні тому, goto
що вони зафіксовані в структурі відповідних циклів, порівняно з goto
якими, звичайно, - мовами, які її мають - перейти куди завгодно.
У класичному JavaScript для використання цього типу коду потрібно використовувати цикли виконання часу. Я припускаю, що ви, можливо, генеруєте код для чогось іншого.
Спосіб зробити це, як і для введення байтового коду в JavaScript, - загортати кожну мітку мітки у "позначений" час виконання.
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);
Кожен мічений цикл виконання часу, який ви використовуєте так, фактично створює дві точки мітки для однієї мітки. Один вгорі і один в кінці петлі. Стрибки назад використовують продовження, а стрибки вперед використовують перерву.
// 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 backkend bytecodes також розглянути питання про циклі перед виведенням коду. Багато простих циклів у той час як можуть бути виявлені як такі, і тоді ви можете скоріше використовувати петлі замість goto.
continue
в do ... while
циклі продовжує перевіряти стан . Відставання goto
тут, використовуючи do ... while (0)
таким чином, не спрацьовує. ecma-international.org/ecma-262/5.1/#sec-12.6.1
let doLoop
для цього працювати. І головна петля: let doLoop = false; do { if(condition){ doLoop = true; continue; } } while (doLoop)
github.com/patarapolw/HanziLevelUp/blob/…
Це давнє питання, але оскільки 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
Тепер кожен блок стає функцією, і кожен перехід стає хвостиком.
function label1() {
A
B
if C then return( label2() )
D
return( label2() )
}
function label2() {
E
return( label1() )
}
Щоб запустити програму, використовуйте label1()
.
Перезапис є виключно механічним і, таким чином, може бути виконано з такою макросистемою, як sweet.js.
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
в Basic ... він зробив такий поганий код! Сучасні мови програмування дають вам кращі варіанти, які ви можете насправді підтримувати.
Є спосіб, як це можна зробити, але це потрібно ретельно спланувати. Візьмемо для прикладу наступну програму 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.
Як правило, я вважаю за краще не використовувати GoTo для поганої читабельності. Для мене це поганий привід для програмування простих ітеративних функцій замість того, щоб програмувати рекурсивні функції, а ще краще (якщо такі речі, як переповнення стека, побоюються), їх справжні ітеративні альтернативи (які часом можуть бути складними).
Щось подібне зробить:
while(true) {
alert("RINSE");
alert("LATHER");
}
Справа є нескінченна петля. Вираз ("true") в парантезах пункту "while" - це те, для чого перевірить двигун Javascript - і якщо вираз буде істинним, воно буде тримати цикл. Писання "істинного" тут завжди оцінюється як істинне, отже, нескінченна петля.
Звичайно, використовуючи 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); break
}
}
Ви , ймовірно , слід прочитати деякі JS підручники як цей один .
Не впевнений, чи goto
взагалі існує JS, але, в будь-якому випадку, це заохочує поганий стиль кодування і його слід уникати.
Ви можете зробити:
while ( some_condition ){
alert('RINSE');
alert('LATHER');
}
Ви можете просто скористатися функцією:
function hello() {
alert("RINSE");
alert("LATHER");
hello();
}
Для досягнення гото-функціональної функції, зберігаючи стек виклику в чистоті, я використовую цей метод:
// 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, ви ніколи не повинні наштовхуватися на випадок, що вимагає цього методу, якщо вам не потрібно призупиняти паралельний цикл у середовищі без асинхронізації / очікування підтримки.
починається і закінчується закриття всіх батьків
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);
// 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);
}
}
Ще один альтернативний спосіб досягти цього - використовувати хвостові дзвінки. Але у нас нічого подібного в JavaScript немає. Таким чином, goto здійснюється в JS за допомогою наведених нижче двох ключових слів. перерва та продовження , довідка: Goto Statement у JavaScript
Ось приклад:
var number = 0;
start_position: while(true) {
document.write("Anything you want to print");
number++;
if(number < 100) continue start_position;
break;
}