2012-04-11 12 views
16

He visto muchas discusiones sobre la manera más rápida de seleccionar un primer elemento hijo usando jQuery. Como se puede esperar, la propiedad de DOM firstChild nativa es mucho más rápida que usar un selector de jQuery o una combinación de selectores: consulte http://jsperf.com/jquery-first-child-selection-performance/6. Esto no suele ser un problema, ya sea que se use en un lugar donde el rendimiento no es un gran problema, o es bastante fácil simplemente acceder al elemento DOM y usar su propiedad .firstChild. Sin embargo, hay un par de problemas con esto:¿Por qué jQuery no proporciona un método .firstChild?

  • firstChild podría devolver un nodo de texto o comentario, en lugar de un elemento, como un selector de jQuery volvería
  • Si necesito para seleccionar el primer hijo de múltiples elementos , Debo usar un selector lento o realizar un trabajo extra iterando sobre los elementos DOM, agregándolos a una colección y luego volviendo a colocarlos en un objeto jQuery.

Me parece que el costo de agregar un método de firstChild a la biblioteca central de jQuery sería mucho menor que los beneficios. Tomé mi propio tiro en la creación de un procedimiento de este tipo para mi propio uso:

$.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); 
}; 

En las pruebas que he creado en http://jsperf.com/jquery-multiple-first-child-selection, esta función realiza más de cinco veces más rápido que cualquier otra opción. Las pruebas se basan en las pruebas mencionadas anteriormente, pero están seleccionando los primeros elementos secundarios de elementos múltiples, en lugar de seleccionar un solo elemento.

¿Hay algo que me falta? Una técnica que debería estar usando? ¿O es esto un problema de lo que uno nunca debería preocuparse? ¿Hay alguna razón para no incluir una función como esta en jQuery?

Respuesta

12

"¿Por qué jQuery no proporciona un método .firstChild?"

Feature creep, lo más probable.

Se puede lograr con otros métodos como usted indicó, y si el rendimiento es una preocupación, puede extender jQuery para esa necesidad específica como lo ha hecho.


Puede mejorar el rendimiento en el código un poco más ...

$.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, no sabía acerca de firstElementChild. Para los curiosos, encontré un cuadro de soporte del navegador aquí: http://www.quirksmode.org/dom/w3c_traversal.html – undefined

+1

También debo mencionar que agregué la función mejorada firstChild a los casos de prueba jsperf vinculados anteriormente. – undefined

+0

La gente se enojó conmigo por tu culpa ... :) mira [esto] (http://meta.stackexchange.com/q/129306/173320). – gdoron

0

Para los casos de un solo elemento puede utilizar el

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

que parece casi coincida con la suya en velocidad ..

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

+2

Es rápido porque es un selector no válido, por lo que no está haciendo ninguna selección de DOM.El selector válido es ': eq (0)', que es específico de Sizzle, y será lento, especialmente si se considera que sin ningún otro selector antes del ':', se está haciendo '': eq (0) ', que seleccionará todos los elementos en el DOM, verá si están en el índice '0', luego verá si su padre tiene' .test'. –

+1

@amnotiam jaja ... maldita sea, me lo perdí ... y pensé que estaba en lo cierto y estaba tratando de mejorarlo ... * risa *. Gracias por el aviso. –

+0

De nada. :) –

Cuestiones relacionadas