Почему jQuery не предоставляет метод .firstChild?

Я видел много дискуссий относительно самого быстрого способа выбрать первый дочерний элемент, используя jQuery. Как и следовало ожидать, собственное свойство DOM firstChild намного быстрее, чем использование селектора jQuery или комбинации селекторов - см. http://jsperf.com/jquery-first-child-selection-performance/6. Обычно это не проблема - либо она используется в месте, где производительность не имеет большого значения, либо достаточно просто получить доступ к элементу DOM и использовать его свойство .firstChild. Однако есть пара проблем с этим:

  • firstChild может вернуть текст или комментарий node, а не элемент, поскольку селектор 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);
};

Ответ 2

Для случаев с одним элементом вы можете использовать

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

который, по-видимому, почти соответствует вашей скорости.

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