Обойти отсутствие JavaScript в goto БЕЗ дополнительных флагов - PullRequest
4 голосов
/ 28 февраля 2011

Как я мог бы эмулировать программную конструкцию 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';
    */

Я знаю, что мог бы точно реализовать ONE из этих goto s как условие 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 с.И нет, мне не нужны дополнительные флаги.


РЕДАКТИРОВАТЬ:

@ Луис Эспиналь: Ваше предлагаемое решение не работает.Если 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 - true, мне не нужно проверятьдля condition2, и, если condition2 истинно, мне не нужно проверять condition3.Но, если condition1 && !condition2, мне, возможно, придется проверить на condition3.

Ответы [ 5 ]

3 голосов
/ 28 февраля 2011

Возможно изменить метки на функции и перейти к setTimeout (имя функции, 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, помещает ваш обратный вызов в конец цикла событий)

2 голосов
/ 21 марта 2012

В JavaScript есть оператор метки прерывания, который можно использовать для досрочного выхода из любого блока кода.Я полагаю, что вы получите тот эффект, который ищете, учитывая свой первый фрагмент кода, если бы вы сделали что-то вроде этого:

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';
    */
};

Метка разрыва не совсем подходит и не позволяет вам писатьспагетти, что бы гото.Он несколько структурирован в том смысле, что он рано выходит из текущего блока, поэтому вы не могли избежать обработки label2 после перехода к label1, но тогда ваш оригинальный фрагмент кода этого не сделал, так что это может выполнить то, что вы ищете.

2 голосов
/ 01 марта 2011

Если только мои глаза не подводят меня или у меня не хватает неясного побочного эффекта, первый приведенный в пример пример эквивалентен следующей версии, основанной на 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';
        }
    }
1 голос
/ 08 февраля 2015

может быть как то так?

  $.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';
    }
1 голос
/ 01 марта 2011

Ваша функция имеет неплоский график потока управления и поэтому не может быть реализована с использованием логики структурированного программирования.Если вас беспокоит скорость, лучше всего дублировать 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';}
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...