在这种情况下,如何模拟goto
编程结构?
$.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's 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';
*/
我知道我可以将这些goto
的 ONE 作为else子句实现:
$.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's 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';
*/
或者:
$.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's 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';
*/
但我希望两个 goto
。而且,不,我不想要额外的标志。
修改
@Luis Espinal:您提出的解决方案不起作用。如果info
为{children: 'a'}
,则您的程序无法将info.children
转换为[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];
}
*/
编辑:有些人似乎认为第四个条件与我的问题有关。问题实际上是我不能做到以下几点:
If condition1 Then action1
If !condition1 && condition2 Then action2
If !condition2 && condition3 && regardlessOf(condition1) Then action3
不使用标志(临时布尔变量)。
基本上如果condition1
为真,我就不必测试condition2
,如果condition2
为真,我就不必测试condition3
}。但是,如果condition1 && !condition2
,我可能需要测试condition3
。
答案 0 :(得分:3)
可能会将标签更改为函数,并将其更改为setTimeout(functionname,0)
例如,而不是:
label1:
// do something
goto label2
label2:
// do something
goto label1
尝试这样的事情:
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
}
(你必须使用超时,因为第一个JavaScript不优化尾调用(第二个),第二个因为你不想阻止浏览器而超时为0会使你的回调在事件循环结束时)
答案 1 :(得分:2)
除非我的眼睛失败或者我错过了一个模糊的副作用,否则第一个转向的例子相当于以下基于if-else的版本(保佑1960年代的结构化编程结构) :
$.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 :(得分:2)
JavaScript确实有一个break标签语句,可用于提前退出任何代码块。我相信如果您做了类似的事情,那么考虑到您的第一个代码片段,您将获得所需的效果:
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's 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';
*/
};
Break标签实际上不是很好,并且不允许你写那种goto意大利面条。它有点结构化,因为它只是提前退出当前块,所以你跳转到label1之后就无法避免label2处理,但是你的原始代码片段却没有,所以这可能会满足你的目标。
答案 3 :(得分:1)
您的函数具有非平面控制流程图,因此无法使用结构化编程逻辑实现。
如果您关注速度,最好的办法是复制label 1
并按如下方式构建代码:
$.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';}
};
答案 4 :(得分:1)
也许是这样的?
$.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's 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';
}