Вложенный jQuery.each () - продолжить / прервать - PullRequest
41 голосов
/ 16 июля 2010

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

    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 (). В соответствии с документацией , возвращение false будет прерывать цикл (прерывание выполнения цикла - аналогично обычному оператору JavaScript JavaScript), а возвращение не-false остановит текущую итерацию и продолжит со следующей итерация (аналогично обычному оператору JavaScript continue).

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

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

TLDR: Есть ли что-либо, напоминающее помеченное продолжение или разрыв в контексте jQuery?

Ответы [ 10 ]

92 голосов
/ 11 октября 2012

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

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

просто

return; похоже на continue

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

22 голосов
/ 16 июля 2010

Вы должны сделать это без 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 всякий раз, когда вы хотите в этом случае.

12 голосов
/ 16 августа 2012

Как указано в документации jQuery http://api.jquery.com/jQuery.each/

return true в jQuery.each совпадает с continue

return false так же, какbreak

8 голосов
/ 16 июля 2010

Чистого способа сделать это не существует, и, как упоминалось выше @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)
}

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

7 голосов
/ 16 июля 2010

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

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

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

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

    return notFound;
});

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

5 голосов
/ 02 апреля 2014

Для этого я использовал паттерн «прорыв»:

$(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 (как я делаю в моем заявлении на возврат, как показано выше) Все, что вам нужно сделать, это:

  1. объявите это в вашем внешнем закрытии: var breakout;
  2. добавьте его в свои операторы return false: return breakout = false
  3. возврат прорыва в ваше внешнее закрытие (я).

Не слишком не элегантно, верно? ... все равно работает на меня.

3 голосов
/ 15 июня 2013

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

Мы можем разорвать цикл $ .each () на определенной итерации, заставив функцию обратного вызова вернуть false.Возвращение non-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));
3 голосов
/ 18 марта 2011

вернуть true не работает

вернуть false работает

found = false;
query = "foo";

$('.items').each(function()
{
  if($(this).text() == query)
  {
    found = true;
    return false;
  }
});
3 голосов
/ 16 июля 2010

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

2 голосов
/ 15 мая 2012

Помеченный перерыв

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