为啥 jQuery 不提供 .firstChild 方法?
Posted
技术标签:
【中文标题】为啥 jQuery 不提供 .firstChild 方法?【英文标题】:Why does jQuery not provide a .firstChild method?为什么 jQuery 不提供 .firstChild 方法? 【发布时间】:2012-04-23 07:28:00 【问题描述】:我已经看到很多关于使用 jQuery 选择第一个子元素的最快方法的讨论。正如所料,原生 DOM 的 firstChild 属性比使用 jQuery 选择器或选择器组合要快得多——参见http://jsperf.com/jquery-first-child-selection-performance/6。这通常不是问题——或者它被用在性能不是什么大问题的地方,或者它很容易访问 DOM 元素并使用它的 .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 中包含这样的函数?
【问题讨论】:
【参考方案1】:“为什么 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);
;
【讨论】:
+1,我不知道 firstElementChild。为了好奇,我在这里找到了一个浏览器支持图表:quirksmode.org/dom/w3c_traversal.html 我还应该提到,我在上面链接的 jsperf 测试用例中添加了改进的 firstChild 函数。 人们因为你而生我的气... :) 检查this。【参考方案2】:对于单元素情况,您可以使用
$('.test > eq(0)')
这似乎与你的速度几乎不相上下..
http://jsperf.com/jquery-multiple-first-child-selection/2
【讨论】:
它很快,因为它是一个无效的选择器,所以它实际上并没有做任何 DOM 选择。有效的选择器是:eq(0)
,它是 Sizzle 特有的,并且会很慢,特别是考虑到在 :
之前没有任何其他选择器,您实际上是在执行 *:eq(0)
,它将选择 DOM 中的所有元素,看看他们是否在索引0
,然后看看他们的父母是否有.test
。
@amnotiam 哈哈 .. 该死的我错过了... 我以为我正在做某事并试图改进它... 笑。感谢您的提醒。以上是关于为啥 jQuery 不提供 .firstChild 方法?的主要内容,如果未能解决你的问题,请参考以下文章