2012-04-11 65 views
16

我已经看到很多关于使用jQuery选择第一个子元素的最快方法的讨论。可以预料,本地DOM firstChild属性比使用jQuery选择器或选择器组合快得多 - 请参阅http://jsperf.com/jquery-first-child-selection-performance/6。这通常不是问题 - 要么在性能不是很大的地方使用它,要么只是访问DOM元素并使用它的.firstChild属性就足够简单了。但是,有几个问题是:为什么jQuery不提供.firstChild方法?

  • 则firstChild可以返回文本或注释节点,而不是一个元素,如jQuery选择将返回
  • 如果我需要选择多个元素的第一个孩子,我必须使用慢速选择器,或者进行大量额外工作来迭代DOM元素,将它们添加到集合中,然后将它们放回到jQuery对象中。

在我看来,将firstChild方法添加到核心jQuery库的成本将远远小于好处。我把我自己在拍我自己用创建这样的方法:

$.fn.firstChild = function() { 
    var ret = []; 

    this.each(function() { 
     var el = this.firstChild; 

     //the DOM firstChild property could return a text node or comment instead of an element 
     while (el && el.nodeType != 1) 
      el = el.nextSibling; 

     if (el) ret.push(el); 
    }); 

    //maintain jQuery chaining and end() functionality 
    return this.pushStack(ret); 
}; 

在我在http://jsperf.com/jquery-multiple-first-child-selection创建的测试中,这个函数执行比任何其他选择快五倍以上。这些测试基于上述测试,但是选择多个元素的第一个子元素,而不是单个元素。

有什么我失踪?我应该使用的技术?还是这个问题比人们不应该担心的问题?有没有理由不在jQuery中包含这样的函数?

回答

12

“为什么jQuery不提供.firstChild方法?”

特征蠕变,最有可能的。

它可以与其他的方法来完成,你说,如果性能是一个问题,您可以为特定需要延长的jQuery为你所做的一切。


可以提高你的代码多一点的性能...

$.fn.firstChild = function() { 
    var ret = []; 
    // use a for loop 
    for (var i = 0, len = this.length; i < len; i++) { 
     var this_el = this[i], 
      el = this_el.firstElementChild; // try firstElementChild first 
     if (!el) { 
      el = this_el.firstChild; 
      while (el && el.nodeType != 1) 
       el = el.nextSibling; 
     } 
     if (el) ret.push(el); 
    } 
    //maintain jQuery chaining and end() functionality 
    return this.pushStack(ret); 
}; 
+2

+1,我不知道firstElementChild。为了好奇,我在这里找到了一个浏览器支持图表:http://www.quirksmode.org/dom/w3c_traversal.html – undefined 2012-04-11 04:04:08

+1

我还应该提到,我将改进的firstChild函数添加到上面链接的jsperf测试用例中。 – undefined 2012-04-11 17:31:48

+0

人们因我而生我的气... :)检查[this](http://meta.stackexchange.com/q/129306/173320)了。 – gdoron 2012-04-15 09:12:27

0

对于单个元素情况下,你可以使用

$('.test > eq(0)') 

这似乎几乎匹配您在速度..

http://jsperf.com/jquery-multiple-first-child-selection/2

+2

这很快,因为它是一个无效的选择器,所以它实际上并没有做任何DOM选择。有效的选择符是':eq(0)',它特定于Sizzle,并且会很慢,特别是考虑到在':'之前没有任何其他选择器,您实际上在执行'*:eq(0)',它将选择DOM中的所有元素,看它们是否在索引'0'处,然后查看它们的父代是否具有'.test'。 – 2012-04-11 02:49:55

+1

@amnotiam大声笑..该死的我错过了......我以为我正在做的事情,并试图改善它...... *轻笑*。感谢您的提醒。 – 2012-04-11 10:05:36

+0

不客气。 :) – 2012-04-11 14:38:09

相关问题