JavaScript flaw is not available without additional flags

How could I emulate the goto programming construct in this case?

 $.fn.hierarchy = function(info, ret) { if (info.constructor !== Object) { info = {children: info}; goto label1; // Illegal JavaScript } if (!info.children) { info.children = []; goto label2; // Illegal JavaScript } label1: if (info.children.constructor !== Array) info.children = [info.children]; label2: /* // Forget this code. It irrelevant to my specific problem // (which is that JS doens't allow non-nested conditionals) // and caused much confusion. if (!info.tagc) info.tagc = info.tag || 'div'; */ 

I know that I can implement ONE of these goto as an else clause:

 $.fn.hierarchy = function(info, ret) { if (info.constructor !== Object) { info = {children: info}; //goto label1; } else if (!info.children) { info.children = []; goto label2; // Illegal JavaScript } //label1: if (info.children.constructor !== Array) info.children = [info.children]; label2: /* // Forget this code. It irrelevant to my specific problem // (which is that JS doens't allow non-nested conditionals) // and caused much confusion. if (!info.tagc) info.tagc = info.tag || 'div'; */ 

Or:

 $.fn.hierarchy = function(info, ret) { if (info.constructor !== Object) { info = {children: info}; goto label1; // Illegal JavaScript } if (!info.children) { info.children = []; //goto label2; } else { label1: if (info.children.constructor !== Array) info.children = [info.children]; } //label2: /* // Forget this code. It irrelevant to my specific problem // (which is that JS doens't allow non-nested conditionals) // and caused much confusion. if (!info.tagc) info.tagc = info.tag || 'div'; */ 

But I want to have like goto s. And no, I do not want additional flags.


EDIT:

@Luis Espinal: Your proposed solution does not work. If info is {children: 'a'} , your program will not be able to convert info.children to [a] .

 $.fn.hierarchy = function(info, ret) { if (info.constructor !== Object) { info = {children: info}; // goto label1; // Illegal JavaScript // label1: if (info.children.constructor !== Array){ info.children = [info.children]; } } else if (!info.children) { info.children = []; // goto label2; // Illegal JavaScript // label2: /* // Wrong. This has to be placed outside all of this. if (!info.tagc) { info.tagc = info.tag || 'div'; } */ } /* the following code is missing: else { // Handles the case when info.constructor === Object // from the beginning // AND // info.children isn't an array if (info.children.constructor !== Array) info.children = [info.children]; } */ 

EDIT: Some of you seem to have thought that the fourth condition is relevant to my problem. The problem is that I cannot do the following:

 If condition1 Then action1 If !condition1 && condition2 Then action2 If !condition2 && condition3 && regardlessOf(condition1) Then action3 

Without the use of flags (temporary Boolean variables).

Basically, if condition1 true, I don't need to check for condition2 , and if condition2 true, I don't need to test condition3 . But, if condition1 && !condition2 , I may have to test for condition3 .

+4
source share
5 answers

Your function has a non-planar control flow graph and therefore cannot be implemented using structured programming logic. If you are interested in speed, it is best to duplicate label 1 and structure the code as follows:

 $.fn.hierarchy = function(info, ret) { if (info.constructor !== Object) { info = {children: info}; //goto label1; // Illegal JavaScript //label1: if (info.children.constructor !== Array) {info.children = [info.children];} } else{ if (!info.children) { info.children = []; //goto label2; // Illegal JavaScript } else{ //label1: if (info.children.constructor !== Array) {info.children = [info.children];} } } //label2: if (!info.tagc) {info.tagc = info.tag || 'div';} }; 
+1
source

Maybe changing labels to functions and gotos to setTimeout (functionname, 0)

For example, instead of:

 label1: // do something goto label2 label2: // do something goto label1 

try something like this:

 function label1 () { // do something setTimeout(label2, 0); return; // may be needed if not at the end of function } function label2 () { // do something setTimeout(label1, 0); return; // may be needed if not at the end of function } 

(You should use timeouts because the first JavaScript does not optimize tail calls (for now) and the second because you do not want to block the browser, and a timeout of 0 puts your callback at the end of the event loop)

+3
source

If my eyes do not confuse me, or I miss an unclear side effect, the first example cited is equivalent to the next version of if-else (blessed 1960 structured )

 $.fn.hierarchy = function(info, ret) { if (info.constructor !== Object) { info = {children: info}; // goto label1; // Illegal JavaScript // label1: if (info.children.constructor !== Array){ info.children = [info.children]; } } else if (!info.children) { info.children = []; // goto label2; // Illegal JavaScript // label2: if (!info.tagc) { info.tagc = info.tag || 'div'; } } 
+2
source

JavaScript has a break label operator that you can use to exit any block of code earlier. I believe that you will get the effect you are looking for when considering your first piece of code if you did something like this:

 var ft = function(info, ret) { label2: { label1: { if (info.constructor !== Object) { info = {children: info}; break label1; } else if (!info.children) { info.children = []; break label2; } } //label1: if (info.children.constructor !== Array) info.children = [info.children]; } // label2: /* // Forget this code. It irrelevant to my specific problem // (which is that JS doens't allow non-nested conditionals) // and caused much confusion. if (!info.tagc) info.tagc = info.tag || 'div'; */ }; 

Labeling the shortcut is actually not very simple, and does not allow you to write the kind of spaghetti that would be. It is somewhat structured in that it only leaves its current block earlier, so you could not avoid processing label2 after switching to label1, but then your source code snippet did not do this, this could accomplish what you are looking for.

+2
source

maybe something like this?

  $.fn.hierarchy = function(info, ret) { if(((info.constructor !== Object && info = {children: info}) || (!!info.children || (info.children = [] && false))) && /* label1: */ info.children.constructor !== Array) { info.children = [info.children]; } /* label2: */ /* // Forget this code. It irrelevant to my specific problem // (which is that JS doesn't allow non-nested conditionals) // and caused much confusion. if (!info.tagc) { info.tagc = info.tag || 'div'; } 
+1
source

Source: https://habr.com/ru/post/1341690/


All Articles