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;
คุณสามารถอ่านเพิ่มเติมเกี่ยวกับวิธีการที่จะดำเนินการข้ามไปแต่โดยทั่วไปก็ไม่บาง preprocessing JavaScript ที่ใช้ประโยชน์จากความจริงที่ว่าคุณสามารถจำลองโกโตะที่มีการติดป้ายชื่อwhile
วง ดังนั้นเมื่อคุณเขียนข้อความ "Hello, world!" โปรแกรมด้านบนจะได้รับการแปลเป็นดังนี้:
var i = 0;
start: while(true) {
console.log("Hello, world!");
i++;
if(i < 538) continue start;
break;
}
มีข้อ จำกัด บางประการสำหรับกระบวนการก่อนการประมวลผลนี้เนื่องจากในขณะที่ลูปไม่สามารถขยายข้ามฟังก์ชันหรือบล็อกต่างๆได้ นั่นไม่ใช่เรื่องใหญ่ แต่ฉันมั่นใจว่าประโยชน์ของการใช้ประโยชน์จากgoto
JavaScript จะครอบงำคุณอย่างแน่นอน
ลิงก์ด้านบนทั้งหมดที่นำไปสู่ไลบรารี goto.js คือ DEAD ทั้งหมดนี่คือลิงค์ที่จำเป็น:
goto.js (ไม่บีบอัด) - parseScripts.js (ไม่บีบอัด)
จากGoto.js :
ป.ล. สำหรับใครก็ตามที่สงสัย (จนถึงขณะนี้มีคนเป็นศูนย์) Summer of Goto เป็นคำที่ Paul Irish ได้รับความนิยมในขณะที่พูดถึงสคริปต์นี้และการตัดสินใจของ PHP ในการเพิ่ม goto ลงในภาษาของพวกเขา
และสำหรับใครที่ไม่รู้ทันทีว่าเรื่องทั้งหมดนี้เป็นเรื่องตลกโปรดยกโทษให้ฉันด้วย <- (ประกันภัย)
goto
อาจใช้ไม่ได้ผล ทำให้มีรูปแบบการจัดการข้อผิดพลาดที่ดีมาก ห่าเราใช้switch
ซึ่งมีgoto
แต่ชื่อและไม่มีใครปวดท้อง
ไม่พวกเขาไม่ได้รวมไว้ใน ECMAScript:
ECMAScript ไม่มีคำสั่ง goto
goto
จะเข้ากันได้ดีกับค็อกเทล "คุณสมบัติ" โง่ ๆ ของจาวาสคริปต์ :)
goto
เป็นคำหลักที่สงวนไว้สำหรับการใช้งานในอนาคตอย่างไรก็ตาม เราทำได้แค่หวัง :)
goto
จะมีประโยชน์เมื่อคุณต้องการกลับจากฟังก์ชันที่ซ้อนกัน ตัวอย่างเช่นเมื่อใช้ underscore.js คุณจะต้องระบุฟังก์ชันที่ไม่ระบุชื่อเมื่อทำซ้ำบนอาร์เรย์ คุณไม่สามารถกลับมาจากภายในฟังก์ชันดังกล่าวได้ดังนั้นgoto end;
จะมีประโยชน์
จริงๆแล้วฉันเห็นว่า ECMAScript (JavaScript) DOES INDEED มีคำสั่ง goto อย่างไรก็ตาม JavaScript goto มีสองรสชาติ!
goto สองรสชาติของ JavaScript เรียกว่าดำเนินการต่อและติดป้ายกำกับว่าแบ่ง ไม่มีคำหลัก "goto" ใน JavaScript goto สามารถทำได้ใน JavaScript โดยใช้ตัวแบ่งและดำเนินการต่อ
และนี่คือมากกว่าหรือน้อยกว่าที่ระบุไว้อย่างชัดเจนบนเว็บไซต์ w3schools นี่http://www.w3schools.com/js/js_switch.asp
ฉันพบเอกสารของการดำเนินการที่มีป้ายกำกับและมีป้ายกำกับว่า break ค่อนข้างแสดงออกอย่างเชื่องช้า
ความแตกต่างระหว่างตัวแบ่งที่มีป้ายกำกับว่าดำเนินการต่อและตัวแบ่งที่มีป้ายกำกับคือจุดที่อาจใช้ การดำเนินการที่มีป้ายกำกับสามารถใช้ได้ภายในลูป while เท่านั้น ดู w3schools สำหรับข้อมูลเพิ่มเติม
===========
อีกวิธีหนึ่งที่จะได้ผลคือการมีคำสั่ง Giant 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. ...
}
}
break
และcontinue
อาจใช้ในfor
ลูปด้วย แต่จริงๆแล้วมันไม่เทียบเท่ากับการgoto
ที่พวกมันถูกล็อคไว้ในโครงสร้างของลูปที่เกี่ยวข้องเมื่อเทียบกับgoto
ที่แน่นอนในภาษาที่มีมันไปได้ทุกที่
ใน JavaScript แบบคลาสสิกคุณต้องใช้ do-while loops เพื่อให้ได้โค้ดประเภทนี้ ฉันคิดว่าคุณอาจกำลังสร้างรหัสสำหรับสิ่งอื่น
วิธีการทำเช่นเดียวกับการแบ็กเอนด์โค้ดโค้ดไปยัง 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++;
}
สมมติว่ารหัสได้รับการเข้ารหัสเป็น bytecodes ดังนั้นตอนนี้คุณต้องใส่ bytecodes ลงใน 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 ที่เหมาะสมของ 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 ในการใช้งานที่รองรับการเรียกหางที่เหมาะสม ในการใช้งานที่รองรับการโทรหางที่เหมาะสมคุณสามารถมีจำนวนการโทรหางที่ใช้งานได้โดยไม่ จำกัด (เช่นการเรียกหางจะไม่ "เพิ่มจำนวนสแต็ก")
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
หลัง 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 หากจำเป็น
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 สำหรับการอ่านที่ไม่ดี สำหรับฉันแล้วมันเป็นข้ออ้างที่ไม่ดีสำหรับการเขียนโปรแกรมฟังก์ชันวนซ้ำอย่างง่ายแทนที่จะต้องตั้งโปรแกรมฟังก์ชันแบบวนซ้ำหรือดีกว่านั้น (หากกลัวว่าจะมีสิ่งต่างๆเช่น Stack Overflow) ทางเลือกในการทำซ้ำที่แท้จริง (ซึ่งบางครั้งอาจซับซ้อน)
สิ่งนี้จะทำ:
while(true) {
alert("RINSE");
alert("LATHER");
}
นั่นคือการวนซ้ำที่ไม่มีที่สิ้นสุด นิพจน์ ("true") ภายใน parantheses ของ while clause คือสิ่งที่เอ็นจิ้น 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
}
}
คุณสามารถใช้ฟังก์ชันง่ายๆ:
function hello() {
alert("RINSE");
alert("LATHER");
hello();
}
เพื่อให้ได้ฟังก์ชันที่เหมือน goto ในขณะที่ทำให้ call stack สะอาดฉันใช้วิธีนี้:
// 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
ไปเริ่มต้นและสิ้นสุดของการปิดพ่อแม่ทั้งหมด
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;
}