Tôi có một số mã mà tôi hoàn toàn phải thực hiện bằng cách sử dụng goto
. Ví dụ, tôi muốn viết một chương trình như thế này:
start:
alert("RINSE");
alert("LATHER");
repeat: goto start
Có cách nào để làm điều đó trong Javascript không?
Tôi có một số mã mà tôi hoàn toàn phải thực hiện bằng cách sử dụng goto
. Ví dụ, tôi muốn viết một chương trình như thế này:
start:
alert("RINSE");
alert("LATHER");
repeat: goto start
Có cách nào để làm điều đó trong Javascript không?
Câu trả lời:
Chắc chắn rồi! Có một dự án tên là Summer of Goto cho phép bạn sử dụng JavaScript với tiềm năng tối đa của nó và sẽ cách mạng hóa cách bạn có thể viết mã của mình.
Công cụ tiền xử lý JavaScript này cho phép bạn tạo nhãn và sau đó lấy nó bằng cú pháp này:
[lbl] <label-name>
goto <label-name>
Ví dụ, ví dụ trong câu hỏi có thể được viết như sau:
[lbl] start:
alert("LATHER");
alert("RINSE");
[lbl] repeat: goto start;
Lưu ý rằng bạn không chỉ giới hạn ở các chương trình tầm thường đơn giản như LATHER
RINSE
chu kỳ lặp lại vô tận mà các khả năng có goto
được là vô tận và bạn thậm chí có thể Hello, world!
gửi tin nhắn tới bảng điều khiển JavaScript 538 lần, như sau:
var i = 0;
[lbl] start:
console.log("Hello, world!");
i++;
if(i < 538) goto start;
Bạn có thể đọc thêm về cách triển khai goto , nhưng về cơ bản, nó thực hiện một số tiền xử lý JavaScript có lợi cho thực tế là bạn có thể mô phỏng một goto với một vòng lặp được gắn nhãnwhile
. Vì vậy, khi bạn viết "Xin chào, thế giới!" chương trình trên, nó được dịch sang một cái gì đó như thế này:
var i = 0;
start: while(true) {
console.log("Hello, world!");
i++;
if(i < 538) continue start;
break;
}
Có một số hạn chế đối với quá trình tiền xử lý này, bởi vì trong khi các vòng lặp không thể trải dài trên nhiều chức năng hoặc khối. Đó không phải là vấn đề lớn, mặc dù tôi chắc chắn rằng những lợi ích của việc có thể tận dụng lợi thế goto
trong JavaScript sẽ hoàn toàn áp đảo bạn.
Tất cả các liên kết ở trên dẫn đến thư viện goto.js là TẤT CẢ CHẾT, đây là các liên kết cần thiết:
goto.js (không nén) --- parseScripts.js (không nén)
Từ Goto.js :
PS Đối với bất cứ ai đang tự hỏi (cho đến nay có tổng số người không), Summer of Goto là một thuật ngữ được phổ biến bởi Paul Irish, trong khi thảo luận về kịch bản này và quyết định của PHP để thêm goto vào ngôn ngữ của họ.
Và đối với những người không ngay lập tức nhận ra rằng toàn bộ điều này là một trò đùa, xin vui lòng tha thứ cho tôi. <- (bảo hiểm).
goto
có lẽ không được tận dụng. Nó làm cho một số mẫu xử lý lỗi rất tốt đẹp. Heck, chúng tôi sử dụng switch
, goto
trong tất cả trừ tên, và không ai đau bụng.
Không. Họ không bao gồm điều đó trong ECMAScript:
ECMAScript không có tuyên bố goto.
goto
sẽ hoàn toàn phù hợp với loại cocktail "tính năng" ngu ngốc của javascript :)
goto
là một từ khóa dành riêng để sử dụng trong tương lai, tuy nhiên. Chúng ta chỉ có thể hy vọng :)
goto
sẽ hữu ích khi bạn muốn trở về từ một hàm lồng nhau. Ví dụ: khi sử dụng underscore.js, bạn cung cấp một hàm ẩn danh khi lặp qua các mảng. Bạn không thể quay lại từ bên trong một chức năng như vậy, vì vậy goto end;
sẽ rất hữu ích.
Trên thực tế, tôi thấy rằng ECMAScript (JavaScript) DOE INDEED có một câu lệnh goto. Tuy nhiên, goto JavaScript có hai hương vị!
Hai hương vị JavaScript của goto được gọi là tiếp tục được gắn nhãn và phá vỡ nhãn. Không có từ khóa "goto" trong JavaScript. Goto được hoàn thành trong JavaScript bằng cách sử dụng các từ khóa break và tiếp tục.
Và điều này ít nhiều được nêu rõ trên trang web w3schools tại đây http://www.w3schools.com/js/js_switch.asp .
Tôi tìm thấy các tài liệu của nhãn tiếp tục và phá vỡ nhãn được thể hiện hơi lúng túng.
Sự khác biệt giữa tiếp tục được gắn nhãn và phá vỡ nhãn là nơi chúng có thể được sử dụng. Tiếp tục được dán nhãn chỉ có thể được sử dụng trong một vòng lặp while. Xem w3schools để biết thêm thông tin.
===========
Một cách tiếp cận khác sẽ hoạt động là có một câu lệnh khổng lồ với câu lệnh chuyển đổi khổng lồ bên trong:
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
và continue
cũng có thể được sử dụng trong for
các vòng lặp. Nhưng chúng thực sự không tương đương với goto
việc chúng bị khóa trong cấu trúc của (các) vòng lặp liên quan, so với goto
tất nhiên - trong các ngôn ngữ có nó - đi đến bất cứ đâu.
Trong JavaScript cổ điển, bạn cần sử dụng các vòng lặp do-while để đạt được loại mã này. Tôi đoán bạn có thể tạo mã cho một số thứ khác.
Cách để làm điều đó, như đối với mã byte phụ trợ cho JavaScript là bao bọc mọi mục tiêu nhãn trong một thời gian "được gắn nhãn".
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);
Mỗi vòng lặp do-while được gắn nhãn mà bạn sử dụng như thế này thực sự tạo ra hai điểm nhãn cho một nhãn. Một ở đầu và một ở cuối vòng lặp. Nhảy trở lại sử dụng tiếp tục và nhảy về phía trước sử dụng phá vỡ.
// 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)
Thật không may, không có cách nào khác để làm điều đó.
Mã ví dụ thông thường:
while (x < 10 && Ok) {
z = 0;
while (z < 10) {
if (!DoStuff()) {
Ok = FALSE;
break;
}
z++;
}
x++;
}
Vì vậy, giả sử mã được mã hóa thành mã byte, vì vậy bây giờ bạn phải đặt mã byte vào JavaScript để mô phỏng phụ trợ của bạn cho một số mục đích.
Kiểu 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)
Vì vậy, sử dụng kỹ thuật này làm công việc tốt cho các mục đích đơn giản. Khác hơn là bạn không thể làm gì khác.
Đối với Javacript bình thường, bạn không cần phải sử dụng goto bao giờ, vì vậy có lẽ bạn nên tránh kỹ thuật này ở đây trừ khi bạn đặc biệt dịch mã kiểu khác để chạy trên JavaScript. Tôi giả sử đó là cách họ lấy kernel Linux để khởi động bằng JavaScript chẳng hạn.
GHI CHÚ! Đây là tất cả lời giải thích ngây thơ. Đối với phụ trợ Js thích hợp của mã byte cũng xem xét việc kiểm tra các vòng lặp trước khi xuất mã. Nhiều vòng lặp đơn giản có thể được phát hiện như vậy và sau đó bạn có thể sử dụng các vòng lặp thay vì goto.
let doLoop
việc này Và vòng lặp chính: let doLoop = false; do { if(condition){ doLoop = true; continue; } } while (doLoop)
github.com/patarapolw/HanziLevelUp/blob/iêu
Đây là một câu hỏi cũ, nhưng vì JavaScript là một mục tiêu di động - có thể có trong ES6 khi triển khai hỗ trợ các cuộc gọi đuôi thích hợp. Khi triển khai với sự hỗ trợ cho các cuộc gọi đuôi thích hợp, bạn có thể có một số lượng các cuộc gọi đuôi hoạt động không giới hạn (tức là các cuộc gọi đuôi không "phát triển ngăn xếp").
A goto
có thể được coi là một cuộc gọi đuôi không có tham số.
Ví dụ:
start: alert("RINSE");
alert("LATHER");
goto start
có thể được viết như
function start() { alert("RINSE");
alert("LATHER");
return start() }
Ở đây, lệnh gọi đến start
ở vị trí đuôi, do đó sẽ không có chồng tràn.
Đây là một ví dụ phức tạp hơn:
label1: A
B
if C goto label3
D
label3: E
goto label1
Đầu tiên, chúng tôi chia nguồn thành các khối. Mỗi nhãn chỉ sự bắt đầu của một khối mới.
Block1
label1: A
B
if C goto label3
D
Block2
label3: E
goto label1
Chúng ta cần liên kết các khối lại với nhau bằng gotos. Trong ví dụ, khối E theo D, vì vậy chúng ta thêm a goto label3
sau D.
Block1
label1: A
B
if C goto label2
D
goto label2
Block2
label2: E
goto label1
Bây giờ mỗi khối trở thành một chức năng và mỗi goto trở thành một cuộc gọi đuôi.
function label1() {
A
B
if C then return( label2() )
D
return( label2() )
}
function label2() {
E
return( label1() )
}
Để bắt đầu chương trình, sử dụng label1()
.
Việc viết lại hoàn toàn là cơ học và do đó có thể được thực hiện với một hệ thống macro như sweet.js nếu cần.
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;
}
Làm thế nào về một for
vòng lặp? Lặp lại nhiều lần như bạn muốn. Hoặc một while
vòng lặp, lặp lại cho đến khi một điều kiện được đáp ứng. Có các cấu trúc điều khiển sẽ cho phép bạn lặp lại mã. Tôi nhớ GOTO
trong Basic ... nó tạo ra mã xấu như vậy! Ngôn ngữ lập trình hiện đại cung cấp cho bạn các tùy chọn tốt hơn mà bạn thực sự có thể duy trì.
Có một cách này có thể được thực hiện, nhưng nó cần được lên kế hoạch cẩn thận. Lấy ví dụ chương trình QBASIC sau:
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."
Sau đó, tạo JavaScript của bạn để khởi tạo tất cả các biến trước, sau đó thực hiện lệnh gọi hàm ban đầu để bắt đầu lăn bóng (chúng tôi thực hiện lệnh gọi hàm ban đầu này ở cuối) và thiết lập các hàm cho mọi bộ dòng mà bạn biết sẽ được thực thi trong một đơn vị.
Thực hiện theo điều này với chức năng gọi ban đầu ...
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();
Kết quả trong trường hợp này là:
a = 1
a = 2
a = 3
a = 4
a = 5
a = 6
a = 7
a = 8
a = 9
a = 10
That's the end.
Nói chung, tôi không thích sử dụng GoTo cho khả năng đọc kém. Đối với tôi, đó là một cái cớ tồi để lập trình các hàm lặp đơn giản thay vì phải lập trình các hàm đệ quy, hoặc thậm chí tốt hơn (nếu những thứ như Stack Overflow bị sợ), các lựa chọn lặp thực sự của chúng (đôi khi có thể phức tạp).
Một cái gì đó như thế này sẽ làm:
while(true) {
alert("RINSE");
alert("LATHER");
}
Đúng là có một vòng lặp vô hạn. Biểu thức ("true") bên trong các mệnh đề của mệnh đề while là công cụ Javascript sẽ kiểm tra - và nếu biểu thức là đúng, nó sẽ giữ cho vòng lặp chạy. Viết "đúng" ở đây luôn luôn đánh giá là đúng, do đó là một vòng lặp vô hạn.
Chắc chắn, bằng cách sử dụng switch
cấu trúc bạn có thể mô phỏng goto
trong JavaScript. Thật không may, ngôn ngữ không cung cấp goto
, nhưng đây là một sự thay thế đủ tốt.
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
}
}
Có lẽ bạn nên đọc một số hướng dẫn JS như thế này một .
Không chắc chắn nếu goto
tồn tại trong JS, nhưng, dù bằng cách nào, nó khuyến khích phong cách mã hóa xấu và nên tránh.
Bạn có thể làm:
while ( some_condition ){
alert('RINSE');
alert('LATHER');
}
Bạn có thể đơn giản sử dụng một chức năng:
function hello() {
alert("RINSE");
alert("LATHER");
hello();
}
Để đạt được chức năng giống như goto trong khi giữ sạch ngăn xếp cuộc gọi, tôi đang sử dụng phương pháp này:
// 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();
}
// ...
Xin lưu ý rằng mã này chậm vì các lệnh gọi hàm được thêm vào hàng đợi hết thời gian, được đánh giá sau, trong vòng cập nhật của trình duyệt.
Cũng xin lưu ý rằng bạn có thể truyền các đối số (sử dụng setTimeout(func, 0, arg1, args...)
trong trình duyệt mới hơn IE9 hoặc setTimeout(function(){func(arg1, args...)}, 0)
trong các trình duyệt cũ hơn.
AFAIK, bạn không bao giờ gặp phải trường hợp yêu cầu phương pháp này trừ khi bạn cần tạm dừng một vòng lặp không song song trong một môi trường mà không có async / chờ hỗ trợ.
goto bắt đầu và kết thúc của tất cả các phụ huynh đóng cửa
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);
}
}
Một cách khác để đạt được điều tương tự là sử dụng các cuộc gọi đuôi. Nhưng, chúng tôi không có bất cứ thứ gì như thế trong JavaScript. Vì vậy, nhìn chung, goto được hoàn thành trong JS bằng cách sử dụng hai từ khóa dưới đây. phá vỡ và tiếp tục , tham khảo: Tuyên bố Goto trong JavaScript
Đây là một ví dụ:
var number = 0;
start_position: while(true) {
document.write("Anything you want to print");
number++;
if(number < 100) continue start_position;
break;
}