16

我已经看到很多关于使用 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 中包含这样的函数?

4

2 回答 2

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);
};
于 2012-04-11T01:38:49.133 回答
0

对于单元素情况,您可以使用

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

这似乎几乎与你的速度相匹配..

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

于 2012-04-11T01:59:51.513 回答