jQuery: 同时将函数应用于多个元素

5
使用jQuery.each(),我可以遍历数组中的元素:
// This is NOT what I am looking for.
$('.example a').each(function() {
    // do a lot of things here
    $(this).css('color', 'red');
});


然而,我需要将函数应用于jQuery数组本身,而不是其成员。因此,我编写了一个小插件来实现这一点:

$.fn.all = function( callback ) { return callback.call( this ); }

$('.example a').all(function() {
    // do a lot of things here
    $(this).css('color', 'red');
});

请注意以上函数中,this将被设置为元素的集合-这是我所需要的。
现在我确信jQuery应该有一种优雅的方法来做到这一点,但我在文档或通过谷歌搜索没有找到任何东西。
是否可能实现,并且如果可能,如何在不使用自定义插件的情况下实现?
更新:我不能直接执行$('.example a').css('color', 'red');。我在函数中有数十个计算,因此必须使用类似于我编写的插件的东西。
我正在寻求回调。正确的答案必须提供类似于自定义函数的回调。

“将函数应用于jQuery数组本身”是什么意思,确切地说? - Oriol
@Oriol 他可能是指作为整体而不是逐个地考虑。 - dokgu
.each通过迭代将回调应用于数组的每个成员,因此“this”将是该数组的成员。 我需要的是“this”将是数组本身,而不是它的成员。请阅读更新后的问题。 - David Refoua
“正确答案必须提供类似于自定义函数的回调函数”,您是指1)当所有函数都完成时的回调函数;2)当每个函数都完成时的回调函数;还是3)两者都需要? - guest271314
不,也许使用“回调”这个词不太合适。我需要将函数应用于数组,并且函数作用域内的this变量应该引用jQuery数组。请查看我的自定义函数以了解我想要的内容。 - David Refoua
6个回答

4
您不需要插件,可以直接使用call
(function() {
  // do a lot of things here
  this.css('color', 'red');
}).call($('.example a'));

或者考虑将类似数组的对象作为参数传递。
(function(arrayLike) {
  // do a lot of things here
  arrayLike.css('color', 'red');
})($('.example a'));

或者如果您更喜欢使用jQuery的方式

$.each([$('.example a')], function(){
  // do a lot of things here
  this.css('color', 'red');
});

这是一种非常优雅的方式,我赞成它。然而,基于当前的格式,我更倾向于使用$(...).something格式。 - David Refoua
2
然后将该方法添加到$.fn似乎是正确的方法。 - Oriol

2

不应该

$('.example a').css('color', 'red');

足够了吗?

除此之外,我还有更多的.css(),它们都需要a)在一个函数中 b)同时完成。 - David Refoua
@DRSDavidSoft,Javascript中无法同时执行多个命令/函数;那么...怎么办呢? - Thomas
我觉得我表达不够清楚。正如我所说,我想对数组本身执行操作,而不是一次性对所有成员执行操作。jQuery本身允许在所选元素上执行某些操作,例如$('a').hide()$('a').each(function() { $(this).hide() })具有完全相同的结果,但后者会更慢。但是,正如您所看到的,.hide()是一次性对所有链接执行的,而不是迭代成员并逐个执行操作。希望这很清楚。 - David Refoua
@DRSDavidSoft “$('a').hide()隐含地执行了each`,是这样吗? - dokgu
@PatrickGregorio 我已经尝试了很多次,似乎它要么不执行each,要么比传递回调函数来为每个元素执行操作做得更好。无论哪种方式,我都需要更好的性能。 - David Refoua

2
那将是实现您想要的方式的直接方法(类似于jQuery):
var $collection = $('.example a');
$collection.each(function() {
    // do a lot of things here
    $collection.css('color', 'red');
});

//另外一个我不喜欢jQuery的实现的原因是each()的参数顺序错误以及滥用this传递当前值/节点
这里是我首选的实现方式。大部分像Array.prototype.forEach(),并且包含$.each()的好处。
$.fn.forEach = function(fn, scope){
    if(scope != null) fn = fn.bind(scope);
    for(var i = 0, len = this.length; i < len; ++i)
        if(false === fn(this[i], i, this)) break;
    return this;
}

你的代码将会是这样的:

$('.example a').forEach(function(node, index, $collection){
    //and don't use `$(this)`, since `this` most of the time references `window`
    //unless you've bound the function to a scope, or passed one to forEach

    var $node = $(node);

    $collection.css('color', 'red');
});

尽管仍在使用自定义的$.fn方法,但这无疑是我见过的最好、最详细的forEach实现。此外,“this的滥用”部分也要点个赞,我赞同程度无法表达! - David Refoua

0

我认为同时获取所有计算结果是不可能的,你应该使用线程或者webWorker。你可以在mdn中获取更多信息。


谢谢,但实际上我需要回调是线性的。你的答案并没有解决我的问题,但它仍然是一篇很棒的文章可以阅读。 - David Refoua
我不使用foreach,因为它将函数应用于“for each”元素。例如:$els[0].doFunc(); $els[1].doFunc(); $els[2].doFunc(); ... 但是我需要将函数同时应用于所有元素:$els.doFunc(); - David Refoua

0

你可以缓存选择器,利用 $.queue()

var elems = $(".example a");
$.queue(elems, "q", function() {
  $(this).css("color", "red");
  console.log(this)
});
$.dequeue(elems, "q")
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<div class="example">
  <a href="#">a</a>
  <a href="#">b</a>
  <a href="#">c</a>
</div>


虽然这不是我直接要求的,但这是一种非常有用的定义队列的方式,我很高兴今天学到了它。谢谢! - David Refoua
@DRSDavidSoft “虽然不是我直接要求的”,但为什么包括了关于 $.when().then() 的注释?“我在函数中有数十个计算”是什么意思? - guest271314
但是这里使用了map,它会像foreach一样迭代元素,所以你并没有处理数组,只是处理其中的元素。或者我错了?(这很有可能) - Iván Rodríguez Torres
这是最接近本地jQuery方法的东西(我所要求的),但使用队列并不一定是必需的(我没有要求),因此有这个句子。尽管如此,我仍然很感激,因为我已经在我的代码的其他部分中使用了您提供的示例。再次感谢,如果我的问题有些不清楚,对不起,但学习jQuery队列肯定会让生活更轻松。 - David Refoua

0

这个

$('.example a')

返回匹配元素的集合。而且

$('.example a').css('color', 'red');

将集合中的所有元素设置为红色。

这就是jQuery的工作原理。


抱歉,我忘记提到我不仅在那里执行 .css()。请阅读更新后的问题。 - David Refoua

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接