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

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

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

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

41
задан Ryan Kinal 16 July 2010 в 17:45
поделиться

4 ответа

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

22
ответ дан 27 November 2019 в 00:06
поделиться

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

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

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

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

    return notFound;
});

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

7
ответ дан 27 November 2019 в 00:06
поделиться

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

3
ответ дан 27 November 2019 в 00:06
поделиться

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

Ok, let the thrashing begin.

8
ответ дан 27 November 2019 в 00:06
поделиться
Другие вопросы по тегам:

Похожие вопросы: