Подтвердить что ты не робот

Вложенный jQuery.each() - продолжить/разбить

Рассмотрим следующий код:

    var sentences = [
        'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
        'Vivamus aliquet nisl quis velit ornare tempor.',
        'Cras sit amet neque ante, eu ultrices est.',
        'Integer id lectus id nunc venenatis gravida nec eget dolor.',
        'Suspendisse imperdiet turpis ut justo ultricies a aliquet tortor ultrices.'
    ];

    var words = ['ipsum', 'amet', 'elit'];

    $(sentences).each(function() {
        var s = this;
        alert(s);
        $(words).each(function(i) {
            if (s.indexOf(this) > -1)
            {
                alert('found ' + this);
                return false;
            }
        });
    });

Интересной частью являются вложенные петли jQuery.each(). В соответствии с документацией, возвращающее ложь выйдет из цикла (прекращение выполнения цикла - похоже на обычный оператор разрыва JavaScript) и возвращение non-false остановит текущую итерацию и продолжит следующую итерацию (похожую на обычный оператор JavaScript continue).

Я могу разбить или продолжить jQuery.each() самостоятельно, но с вложенным jQuery.each мне было трудно вырваться из родительского цикла из дочернего цикла. Я мог бы использовать логическое значение и обновлять его на каждой дочерней итерации, но мне было интересно, был ли более простой способ.

Я установил пример в jsFiddle, если вы хотите пообщаться с ним. Просто нажмите кнопку "Тест", чтобы запустить пример, показанный выше.

TL;DR: Есть ли что-нибудь похожее на помеченное продолжение или разрыв в контексте jQuery?

4b9b3361

Ответ 1

Вы должны сделать это без jQuery, это может быть не так "красиво", но там меньше происходит, и вам проще делать именно то, что вы хотите, например:

var sentences = [
    'Lorem ipsum dolor sit amet, consectetur adipiscing elit.',
    'Vivamus aliquet nisl quis velit ornare tempor.',
    'Cras sit amet neque ante, eu ultrices est.',
    'Integer id lectus id nunc venenatis gravida nec eget dolor.',
    'Suspendisse imperdiet turpis ut justo ultricies a aliquet tortor ultrices.'
];

var words = ['ipsum', 'amet', 'elit'];

for(var s=0; s<sentences.length; s++) {
    alert(sentences[s]);
    for(var w=0; w<words.length; w++) {
        if(sentences[s].indexOf(words[w]) > -1) {
            alert('found ' + words[w]);
            return;
        }
    }
}

Вы можете попробовать здесь. Я не уверен, что это точное поведение, которое вам нужно, но теперь вы не закрыты внутри замыкания, созданного двойным .each(), и вы можете return или break, когда захотите в этом случае.

Ответ 2

Здесь много ответов. И это старо, но это для всех, кто приходит сюда через Google. В jQuery каждая функция

return false; похож на break.

просто

return; похож на continue

Они будут эмулировать поведение break и продолжить.

Ответ 3

Как указано в документации jQuery http://api.jquery.com/jQuery.each/ a return true; совпадает с continue; в цикле, а return false; - это то же самое как break;

Ответ 4

Нет никакого чистого способа сделать это, и, как @Nick, упомянутого выше, может быть проще использовать старый школьный путь циклов, как тогда вы можете это контролировать. Но если вы хотите придерживаться того, что у вас есть, есть один способ, которым вы могли бы справиться с этим. Я уверен, что я получу немного тепла для этого. Но...

Один из способов сделать то, что вы хотите, без оператора if - это поднять ошибку и обернуть цикл с помощью блока try/catch:

try{
$(sentences).each(function() {
    var s = this;
    alert(s);
    $(words).each(function(i) {
        if (s.indexOf(this) > -1)
        {
            alert('found ' + this);
            throw "Exit Error";
        }
    });
});
}
catch (e)
{
    alert(e)
}

Хорошо, пусть начинается трение.

Ответ 5

Проблема заключается в том, что, хотя вы можете вернуть false из обратного вызова .each, сама функция .each возвращает объект jQuery. Поэтому вам нужно вернуть ложь на обоих уровнях, чтобы остановить итерацию цикла. Кроме того, поскольку нет способа узнать, найдено ли внутреннее .each совпадение или нет, мы должны будем использовать общую переменную, используя закрытие, которое обновляется.

Каждая внутренняя итерация words относится к той же переменной notFound, поэтому нам просто нужно ее обновить, когда найдено совпадение, а затем верните ее. Внешнее закрытие уже имеет ссылку на него, поэтому при необходимости оно может break.

$(sentences).each(function() {
    var s = this;
    var notFound = true;

    $(words).each(function() {
        return (notFound = (s.indexOf(this) == -1));
    });

    return notFound;
});

Здесь вы можете попробовать здесь.

Ответ 6

К сожалению нет. Проблема здесь в том, что итерация происходит внутри функций, поэтому они не похожи на обычные циклы. Единственный способ вырваться из функции - это вернуть или выбросить исключение. Так что да, использование логического флага, по-видимому, является единственным разумным способом "вырваться" из внешнего "цикла".

Ответ 7

return true не работает

вернуть false

found = false;
query = "foo";

$('.items').each(function()
{
  if($(this).text() == query)
  {
    found = true;
    return false;
  }
});

Ответ 8

Я использовал шаблон "breakout" для этого:

$(sentences).each(function() {
    var breakout;
    var s = this;
    alert(s);
    $(words).each(function(i) {
        if (s.indexOf(this) > -1)
        {
            alert('found ' + this);
            return breakout = false;
        }
    });
    return breakout;
});

Это хорошо работает с любой глубиной вложенности. breakout - простой флаг. Он останется undefined, если и до тех пор, пока вы не установите его на false (как в моем возвратном выражении, как показано выше). Все, что вам нужно сделать, это:

  • объявите его в своем внешнем закрытии: var breakout;
  • добавьте его в инструкцию return false: return breakout = false
  • Возвратите прорыв в своем внешнем закрытии.

Не слишком неуловимый, не так ли? ... все равно работает для меня.

Ответ 9

Подтвердить в документации API http://api.jquery.com/jQuery.each/ сказать:

Мы можем разбить цикл $.each() на конкретной итерации, сделав функция обратного вызова возвращает false. Возврат не-false - это то же самое, что и continue в цикле for; он немедленно перейдет к следующему итерации.

и это мой пример http://jsfiddle.net/r6jqP/

(function($){
    $('#go').on('click',function(){
        var i=0,
            all=0;
        $('li').each(function(){
             all++;
             if($('#mytext').val()=='continue')return true;
             i++;
             if($('#mytext').val()==$(this).html()){
                 return false;
             }
        });
        alert('Iterazione : '+i+' to '+all);
    });
}(jQuery));

Ответ 10

Маркированный разрыв

outerloop:
$(sentences).each(function() 
{
    $(words).each(function(i) 
    {
        break; /* breaks inner loop */
    } 
    $(words).each(function(i)  
    {
        break outerloop; /* breaks outer loop */
    }
}