如何优化$ .find()。first()?

时间:2011-08-24 16:44:51

标签: javascript jquery optimization find findfirst

我需要检索第一个元素。

我用这段代码做到了......

$(element).find('.x').first();

据我所知,那段代码......

  1. 检索element中匹配.x
  2. 的所有元素
  3. 删除不需要的元素;
  4. 有没有更好的方法呢?像$.findOne()或其他什么?

10 个答案:

答案 0 :(得分:11)

根据jQuery docs:

  

因为:首先是jQuery扩展而不是CSS的一部分   规范,查询使用:首先不能利用   本机DOM querySelectorAll()提供的性能提升   方法。使用时达到最佳性能:首先选择   元素,首先使用纯CSS选择器选择元素   使用.filter(“:first”)。

所以将选择器重写为:

$(element).find('.x').filter(":first")

或(这只会给你直接的后代,并且会比.find更快,除非你也在寻找嵌套元素)

$(element).children('.x').filter(":first")

应该会给你更好的结果。


更新来自kingjivpatrick dw的有价值的输入(请参阅评论), 看起来这两个比.filter(':first')更快,与文档声称的相反。

$(element).find('.x').first();   // faster

$($(element).find('.x')[0]);     // fastest

答案 1 :(得分:4)

如果你想快速实现它,你应该使用本机浏览器方法。现代浏览器支持querySelector [docs]

var $result;
if(element.querySelector) {
    $result = $(element.querySelector('.x'));
}
else {
    $result = $(element).find('.x').first();
}

用法有点受限,因为它仅在element是单个元素并且选择器是有效的CSS选择器时才有效。你可以用它制作一个插件。但是,如果你考虑所有情况,比如多个元素等,那么可能就没有任何优势了。

所以,如果你有一个非常具体的用例,这可能是有用的,如果没有,坚持使用jQuery。

更新:结果表明,制作插件仍然更快:jsPerf benchmark

(function($) {
    $.fn.findOne = function(selector) {
        try {
            var element, i = 0, l = this.length;
            while(i < l && (element = this[i].querySelector(selector)) === null) {
                i++;
            }
            return $(element);
        }
        catch(e) {
            return this.find(selector).first();
        }
    };
}(jQuery));

这是如何运作的:

插件迭代选定的DOM元素,并在每个元素上调用querySelector。找到元素后,循环将终止并返回找到的元素。可能发生异常有两个原因:

  • 浏览器不支持querySelector
  • 选择器不是纯CSS选择器

在这两种情况下,插件都会回退使用普通的jQuery方法。

答案 2 :(得分:2)

看起来很疯狂,在我看过的每次性能测试中,.first()都有比:first更好的性能。

正如大多数人所建议的那样,似乎使用$(element).find(".x:first")应该有更好的表现。但是,实际上.first更快。我没有调查jquery的内部以找出原因。

http://jsperf.com/jquery-select-first

显然使用[0]然后在jquery对象中重新包装是最快的:

$($(element).find(".x")[0])

编辑:请参阅mrchief的答案,解释原因。显然他们现在已将其添加到文档中。

答案 3 :(得分:0)

这应该更好

$(element).find('.x:first');

答案 4 :(得分:0)

使用:first选择器:

$(element).find('.x:first')

答案 5 :(得分:0)

最好写一下:

$('a:first');

你写的是“在'元素'中,找到'.x'并返回第一个”。这可以像这样表达

$('.x:first', element);

答案 6 :(得分:0)

如何使用first-child伪类?喜欢

$(element).find('.x:first-child')

但是,如果您的结构类似于

,则可能会产生问题
<div>
   <p></p>
</div>
<div>
   <p></p>
</div>

所以实际上它不是你想要的(如果你的意思是一般解决方案)。其他建议:首先,这似乎是正确的方法

答案 7 :(得分:0)

你的瓶颈实际上是.find(),它会搜索所有后代,而不仅仅是直接的孩子。

最重要的是,您正在搜索类.x(使用jQuery自定义搜索)而不是ID或标记名(使用本机DOM方法)。

我会使用Mrchief的答案然后,如果可能的话,修复这两个瓶颈以加快你的选择。

答案 8 :(得分:0)

根据jQuery文档,这种方式很好,或者至少比使用:first选择器更好。

您可以尝试替代.filter(":first")或使用数组访问器获取第一个元素,而不是.find()结果[0]

此外,您可以将其更改为.find()而不是$('.x', element)

.x

将搜索范围缩小到元素内的{{1}}元素,搜索整个文档。

答案 9 :(得分:0)

您可以使用后代选择器合并$(element).find()个调用;我不确定性能比较:

$("#element .x").first().hide();