J'ai du code que je dois absolument implémenter en utilisant goto
. Par exemple, je veux écrire un programme comme celui-ci:
start:
alert("RINSE");
alert("LATHER");
repeat: goto start
Existe-t-il un moyen de le faire en Javascript?
J'ai du code que je dois absolument implémenter en utilisant goto
. Par exemple, je veux écrire un programme comme celui-ci:
start:
alert("RINSE");
alert("LATHER");
repeat: goto start
Existe-t-il un moyen de le faire en Javascript?
Réponses:
Absolument! Il existe un projet appelé Summer of Goto qui vous permet d'utiliser JavaScript à son plein potentiel et va révolutionner la façon dont vous pouvez écrire votre code.
Cet outil de prétraitement JavaScript vous permet de créer une étiquette, puis d'y accéder en utilisant cette syntaxe:
[lbl] <label-name>
goto <label-name>
Par exemple, l'exemple de la question peut s'écrire comme suit:
[lbl] start:
alert("LATHER");
alert("RINSE");
[lbl] repeat: goto start;
Notez que vous n'êtes pas seulement limité à de simples programmes triviaux comme un LATHER
RINSE
cycle de répétition sans fin - les possibilités offertes par goto
sont infinies et vous pouvez même envoyer un Hello, world!
message à la console JavaScript 538 fois, comme ceci:
var i = 0;
[lbl] start:
console.log("Hello, world!");
i++;
if(i < 538) goto start;
Vous pouvez en savoir plus sur la façon dont goto est implémenté , mais en gros, il effectue un prétraitement JavaScript qui tire parti du fait que vous pouvez simuler un goto avec une boucle étiquetéewhile
. Donc, lorsque vous écrivez le "Bonjour, le monde!" programme ci-dessus, il est traduit en quelque chose comme ceci:
var i = 0;
start: while(true) {
console.log("Hello, world!");
i++;
if(i < 538) continue start;
break;
}
Il existe certaines limites à ce processus de prétraitement, car les boucles while ne peuvent pas s'étendre sur plusieurs fonctions ou blocs. Ce n'est pas un gros problème, je suis sûr que les avantages de pouvoir profiter de goto
JavaScript vous submergeront absolument.
Tous les liens ci-dessus qui mènent à la bibliothèque goto.js sont TOUT MORTS, voici les liens nécessaires:
goto.js (non compressé) --- parseScripts.js (non compressé)
Depuis Goto.js :
PS Pour tous ceux qui se demandent (jusqu'à présent, un total de zéro personne), Summer of Goto est un terme qui a été popularisé par Paul Irish, tout en discutant de ce script et de la décision de PHP d'ajouter goto dans leur langue.
Et pour ceux qui ne reconnaissent pas immédiatement que tout cela est une blague, pardonnez-moi s'il vous plaît. <- (assurance).
goto
est probablement sous-utilisé. Cela donne de très bons modèles de gestion des erreurs. Heck, nous utilisons switch
, ce qui est goto
dans tout sauf le nom, et personne n'a mal au ventre.
Non, ils n'ont pas inclus cela dans ECMAScript:
ECMAScript n'a pas d'instruction goto.
goto
s'intégrerait parfaitement bien dans le cocktail javascript de "fonctionnalités" stupides :)
goto
est cependant un mot-clé réservé pour une utilisation future. On ne peut qu'espérer :)
goto
serait utile lorsque vous souhaitez revenir à partir d'une fonction imbriquée. Par exemple, lors de l'utilisation de underscore.js, vous fournissez une fonction anonyme lors de l'itération sur des tableaux. Vous ne pouvez pas revenir de l'intérieur d'une telle fonction, ce goto end;
serait donc utile.
En fait, je vois que ECMAScript (JavaScript) DOES INDEED a une instruction goto. Cependant, JavaScript goto a deux saveurs!
Les deux versions JavaScript de goto sont appelées "continue" et "break". Il n'y a pas de mot-clé "goto" en JavaScript. Le goto est accompli en JavaScript en utilisant les mots-clés break et continue.
Et cela est plus ou moins explicitement indiqué sur le site Web de w3schools ici http://www.w3schools.com/js/js_switch.asp .
Je trouve la documentation du continue étiqueté et de la pause étiquetée quelque peu maladroitement exprimée.
La différence entre la continuation étiquetée et la pause étiquetée est l'endroit où elles peuvent être utilisées. Le continue étiqueté ne peut être utilisé que dans une boucle while. Voir w3schools pour plus d'informations.
===========
Une autre approche qui fonctionnera est d'avoir une déclaration while géante avec une déclaration de commutateur géante à l'intérieur:
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
et continue
peut également être utilisé dans les for
boucles. Mais ils ne sont vraiment pas équivalents à goto
étant donné qu'ils sont verrouillés dans la structure de la ou des boucles associées, par rapport à goto
ce qui peut bien sûr - dans les langues qui l'ont - aller n'importe où.
Dans JavaScript classique, vous devez utiliser des boucles do-while pour obtenir ce type de code. Je suppose que vous générez peut-être du code pour autre chose.
La façon de le faire, comme pour le backend du bytecode vers JavaScript, est d'envelopper chaque cible d'étiquette dans un do-while «étiqueté».
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);
Chaque boucle do-while étiquetée que vous utilisez ainsi crée en fait les deux points d'étiquette pour une étiquette. Un en haut et un à la fin de la boucle. Le saut en arrière continue et le saut en avant utilise la pause.
// 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)
Malheureusement, il n'y a pas d'autre moyen de le faire.
Exemple de code normal:
while (x < 10 && Ok) {
z = 0;
while (z < 10) {
if (!DoStuff()) {
Ok = FALSE;
break;
}
z++;
}
x++;
}
Donc, disons que le code est encodé en bytecodes, donc maintenant vous devez mettre les bytecodes en JavaScript pour simuler votre backend dans un certain but.
Style 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)
Donc, utiliser cette technique fait très bien le travail à des fins simples. A part ça, vous ne pouvez pas faire grand-chose d'autre.
Pour Javacript normal, vous ne devriez jamais avoir besoin d'utiliser goto, vous devriez donc probablement éviter cette technique ici, sauf si vous traduisez spécifiquement un autre code de style pour l'exécuter sur JavaScript. Je suppose que c'est ainsi qu'ils amènent le noyau Linux à démarrer en JavaScript par exemple.
REMARQUE! Tout cela est une explication naïve. Pour un bon backend Js des bytecodes, envisagez également d'examiner les boucles avant de sortir le code. De nombreuses boucles while simples peuvent être détectées en tant que telles et vous pouvez alors plutôt utiliser des boucles au lieu de goto.
continue
dans une do ... while
boucle continue à la condition de vérification . L'utilisation à l'envers goto
ici ne fonctionne do ... while (0)
donc pas. ecma-international.org/ecma-262/5.1/#sec-12.6.1
let doLoop
que cela fonctionne. Et boucle principale: let doLoop = false; do { if(condition){ doLoop = true; continue; } } while (doLoop)
github.com/patarapolw/HanziLevelUp/blob/…
C'est une vieille question, mais puisque JavaScript est une cible mouvante - il est possible dans ES6 sur une implémentation qui prend en charge les appels de queue appropriés. Sur les implémentations prenant en charge les appels de queue appropriés, vous pouvez avoir un nombre illimité d'appels de queue actifs (c.-à-d. Que les appels de queue ne "font pas grandir la pile").
A goto
peut être considéré comme un appel de queue sans paramètres.
L'exemple:
start: alert("RINSE");
alert("LATHER");
goto start
peut être écrit comme
function start() { alert("RINSE");
alert("LATHER");
return start() }
Ici, l'appel à start
est en position de queue, donc il n'y aura pas de débordement de pile.
Voici un exemple plus complexe:
label1: A
B
if C goto label3
D
label3: E
goto label1
Tout d'abord, nous divisons la source en blocs. Chaque étiquette indique le début d'un nouveau bloc.
Block1
label1: A
B
if C goto label3
D
Block2
label3: E
goto label1
Nous devons lier les blocs ensemble à l'aide de gotos. Dans l'exemple, le bloc E suit D, nous ajoutons donc un goto label3
après D.
Block1
label1: A
B
if C goto label2
D
goto label2
Block2
label2: E
goto label1
Maintenant, chaque bloc devient une fonction et chaque goto devient un appel final.
function label1() {
A
B
if C then return( label2() )
D
return( label2() )
}
function label2() {
E
return( label1() )
}
Pour démarrer le programme, utilisez label1()
.
La réécriture est purement mécanique et peut donc se faire avec un macro système tel que sweet.js si besoin.
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;
}
Et une for
boucle? Répétez autant de fois que vous le souhaitez. Ou une while
boucle, répétez jusqu'à ce qu'une condition soit remplie. Il existe des structures de contrôle qui vous permettront de répéter le code. Je me souviens GOTO
qu'en Basic ... ça faisait un si mauvais code! Les langages de programmation modernes vous offrent de meilleures options que vous pouvez réellement gérer.
Il existe un moyen de le faire, mais il faut le planifier soigneusement. Prenons par exemple le programme QBASIC suivant:
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."
Ensuite, créez votre JavaScript pour initialiser toutes les variables en premier, puis effectuez un appel de fonction initial pour lancer le bal (nous exécutons cet appel de fonction initial à la fin), et configurez des fonctions pour chaque ensemble de lignes dont vous savez qu'elles seront exécutées dans l'unité unique.
Suivez ceci avec l'appel de fonction initial ...
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();
Le résultat dans cette instance est:
a = 1
a = 2
a = 3
a = 4
a = 5
a = 6
a = 7
a = 8
a = 9
a = 10
That's the end.
En général, je préfère ne pas utiliser GoTo pour une mauvaise lisibilité. Pour moi, c'est une mauvaise excuse pour programmer des fonctions itératives simples au lieu d'avoir à programmer des fonctions récursives, ou encore mieux (si des choses comme un Stack Overflow sont redoutées), leurs vraies alternatives itératives (qui peuvent parfois être complexes).
Quelque chose comme ça ferait:
while(true) {
alert("RINSE");
alert("LATHER");
}
Ce droit il y a une boucle infinie. L'expression ("true") à l'intérieur des parantheses de la clause while est ce que le moteur Javascript va vérifier - et si l'expression est vraie, il maintiendra la boucle en cours d'exécution. Ecrire "vrai" ici vaut toujours vrai, d'où une boucle infinie.
Bien sûr, en utilisant la switch
construction, vous pouvez simuler goto
en JavaScript. Malheureusement, la langue ne fournit pas goto
, mais c'est un assez bon remplacement.
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
}
}
Vous devriez probablement lire quelques tutoriels JS comme celui- ci .
Je ne sais pas du tout s'il goto
existe dans JS, mais dans tous les cas, cela encourage un mauvais style de codage et doit être évité.
Vous pourriez faire:
while ( some_condition ){
alert('RINSE');
alert('LATHER');
}
Vous pouvez simplement utiliser une fonction:
function hello() {
alert("RINSE");
alert("LATHER");
hello();
}
Pour obtenir des fonctionnalités de type goto tout en gardant la pile d'appels propre, j'utilise cette méthode:
// 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();
}
// ...
Veuillez noter que ce code est lent car les appels de fonction sont ajoutés à la file d'attente des délais d'expiration, qui est évaluée plus tard, dans la boucle de mise à jour du navigateur.
Veuillez également noter que vous pouvez passer des arguments (en utilisant setTimeout(func, 0, arg1, args...)
dans un navigateur plus récent que IE9, ou setTimeout(function(){func(arg1, args...)}, 0)
dans des navigateurs plus anciens.
AFAIK, vous ne devriez jamais rencontrer un cas qui nécessite cette méthode à moins que vous n'ayez besoin de mettre en pause une boucle non parallélable dans un environnement sans support async / await.
aller au début et à la fin de toutes les fermetures de parents
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);
}
}
Une autre façon de parvenir à la même chose consiste à utiliser les appels de queue. Mais nous n'avons rien de tel en JavaScript. Donc, généralement, le goto est accompli dans JS en utilisant les deux mots-clés ci-dessous. break and continue , référence: déclaration Goto en JavaScript
Voici un exemple:
var number = 0;
start_position: while(true) {
document.write("Anything you want to print");
number++;
if(number < 100) continue start_position;
break;
}