7

首先,一些伪伪代码:

$("some-selector-logic").each(function() {
  if (someLogic($(this))) {
    return false;
  }
  // Otherwise do stuff related to $(this)
});

someMoreExcitingCode();

在这个例子中,我们基于一些选择器逻辑获得了一组 DOM 元素,然后遍历每个元素。对于我们调用的每个元素someLogic()。如果返回,true我们将中止每个循环。否则,我们对元素执行一些逻辑,然后移动到下一个元素。一旦我们完成了所有元素,我们将继续调用someMoreExcitingCode().

我想知道,在调用之前someMoreExcitingCode(),循环是否过早中止。显然你可以这样做:

var aborted = false;
$("..").each(function() {
  if (someLogic($(this))) {
    aborted = true;
    return false;
  }
});

但这对我来说感觉很草率,就像 jQuery 应该以另一种方式向我提供这些信息一样。有没有一种我不知道的更惯用的方法来实现这一点?

4

4 回答 4

3

由于 jQuery 函数倾向于返回调用它们的相同对象集合(以允许链接)的方式,该each()函数无法将该信息返回给您 - 它已经返回了一个 jQuery 对象,您可以链接其他方法调用上。

根据您提供的信息,我认为使用外部标志或计数器变量获取此信息没有问题。如果您告诉我们更多关于您为什么需要知道这一点的信息,我们也许能够提供更多有用的建议。

于 2013-06-12T03:50:58.517 回答
2

没什么神奇的$.each()。这是一个简单的功能,它要么满足你的需求,要么不满足。如果没有,那么在代码示例中设置变量没有任何问题。编写自己的each()函数来满足您的需要并没有错。它只是运行循环并调用您的回调函数的几行代码。

$.each()这是jQuery 1.10.1 中的源代码:

// args is for internal usage only
each: function( obj, callback, args ) {
    var value,
        i = 0,
        length = obj.length,
        isArray = isArraylike( obj );

    if ( args ) {
        if ( isArray ) {
            for ( ; i < length; i++ ) {
                value = callback.apply( obj[ i ], args );

                if ( value === false ) {
                    break;
                }
            }
        } else {
            for ( i in obj ) {
                value = callback.apply( obj[ i ], args );

                if ( value === false ) {
                    break;
                }
            }
        }

    // A special, fast, case for the most common use of each
    } else {
        if ( isArray ) {
            for ( ; i < length; i++ ) {
                value = callback.call( obj[ i ], i, obj[ i ] );

                if ( value === false ) {
                    break;
                }
            }
        } else {
            for ( i in obj ) {
                value = callback.call( obj[ i ], i, obj[ i ] );

                if ( value === false ) {
                    break;
                }
            }
        }
    }

    return obj;
},

这段代码唯一的复杂性在于它同时处理对象和数组,每种情况都有两种不同的情况。

对于您正在处理的案例,它归结为:

        for ( ; i < length; i++ ) {
            value = callback.call( obj[ i ], i, obj[ i ] );

            if ( value === false ) {
                break;
            }
        }

那里没有那么多代码,如果没有做你想要的,你可以很容易地编写你自己的类似迭代器来完全满足你的需要。

你甚至可以使用一个简单的for循环。

function doExcitingStuff() {
    var $elements = $("some-selector-logic");
    for( var i = 0;  i < $elements.length;  i++ ) {
        var $element = $($elements[i]);
        if( someLogic($element) )
            return;
        // Otherwise do stuff related to $element
    }
    someMoreExcitingCode();  // only runs if the loop completes
}

这实际上完全取决于使您的代码最干净的原因。您可以使用$.each()或编写自己的。

于 2013-06-12T03:45:42.233 回答
0

如果您真的非常想避免该abort布尔值,并且您不关心效率,那么您可以执行以下操作:

$("..").removeClass('aborted').each(function() {
    if(someLogic($(this))) {
        $(this).addClass('aborted');
        return false;
    }
});

if( $("..").find('aborted').length ) {
    //each was aborted
}
else {
    //each ran to completion
}

但这实际上是使用 DOM 来注册您的布尔状态,而不是设置 js var。

就个人而言,我会硬着头皮使用你的abort = true想法。

于 2013-06-12T04:28:22.947 回答
0

也许没有你希望的那么优雅,但你可以使用Array.prototype.some

var aborted = Array.prototype.some.call($(".foo"), function(el) {
    if ($(el).hasClass('bar')) {
        return true;
    }
});

jsfiddle

于 2013-06-12T04:15:29.637 回答