绕过JavaScript缺少goto而没有额外的标志

时间:2011-02-28 19:24:23

标签: javascript goto

在这种情况下,如何模拟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

5 个答案:

答案 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';
    }